数据结构——二叉树的遍历
信息科学与技术学院 《数据结构》课程设计报告
完成日期:2013-01-09
题目名称: 二叉树的遍历
专业班级: 111111 11111
学生学号: 11111 指导教师: 11111
目录
1 课程设计的目的 (3)
1.1 课程设计的目的 (3)
2 概要设计 (3)
2.1总体组成框图 (3)
2.2 基本操作 (4)
3 详细设计 (4)
3.1 流程图 (4)
3.2 源程序 (6)
4 测试 (21)
4.1创建二叉树 (21)
4.2二叉树的递归遍历(以先序为例) (21)
4.3二叉树的非递归遍历(以先序为例) (22)
4.4层次序遍历: (22)
4.5二叉树与树的转换: (23)
5 课程设计总结 (24)
6参考书目: (25)
1 课程设计的目的
1.1 课程设计的目的
培养学生用学到的书本知识解决实际问题的能力;培养实际工作所需要的动手能力;培养学生以科学理论和工程上能力的技术,规范地开发大型、复杂、高质量的应用软件和系统软件具有关键性作用;通过课程设计的实践,学生可以在程序设计方法、上机操作等基本技能和科学作风方面受到比较系统和严格的训练。
1.2 课程设计的题目
二叉树的中序、前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现,应包含建树的实现。 1.3 题目要求
遍历的内容应是千姿百态的。树与二叉树的转换的实现。以及树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现,应包含建树的实现。
2 概要设计
2.1总体组成框图
二叉树转化为树
创建二叉树
前序递归遍历算法
中序递归遍历算法 后序递归遍历算法 前序非递归遍历算法 中序非递归遍历算法 后序非递归遍历算法 层序非递归遍历算法
树转换为二叉树 树和二叉树
2.2 基本操作
//队列数据类型定义
typedef struct
{
BiTreeNode queue[maxsize];
int rear; //队尾指针
int front; //队头指针
int count; //计数器
} SeqCQueue;//栈数据类型定义
typedef struct//堆栈的结构体,用于非递归的后序遍历
{
stacknode Elem[maxsize];
int top;
} SequenceStack;
主要模块设计
void PreOrder(BiTreeNode *root, void Visit(char item));//先序递归遍历二叉树void InOrder(BiTreeNode *root, void Visit(char item));//中序递归遍历二叉树void PostOrder(BiTreeNode *root, void Visit(char item));//后序递归遍历二叉树void PreOrderUnrec(BiTreeNode *t);//先序非递归遍历二叉树
void InOrderUnrec(BiTreeNode *t);//中序非递归遍历二叉树
void PostOrderUnrec(BiTreeNode *t);//后序非递归遍历二叉树
void ccbl(BiTreeNode *h);//层次遍历
其他模块包括栈的初始化及其基本操作和队列的初始化及基本操作。
3 详细设计
3.1 流程图
二叉树的递归遍历(以先序遍历为例)
N Y
结点为空
访问根节点
先序遍历方式遍历左子树先序遍历方式遍历右子树
结束
开始
二叉树的非递归遍历(以先序遍历为例)
二叉树的层次遍历
访问元素所指结点,若该元素所指结点的左右孩子结点非空,则该元素所指
结点的左孩子指针和右孩子指针顺序入队。
初始化队列,root 入队
队列非空
出队p ;打印p->data
Y
p->lchild!=null
Y
p->lchild 入队
p->lchild!=null
N
Y
N
p->rchild 入
结束
N
出栈p ;打印p->data
N
初始化队列,root 入队 栈非空
Y
p->lchild!=null
p->lchild 入栈
p->lchild!=null
Y
p->rchild 入栈
结束
N
3.2 源程序
#include
#include
using namespace std;
#define maxsize 100
struct node
{int i;
node *next;
};
struct treenode
{
int i;
treenode *l,*r;
};
node nod[105], temp[1005];
int edge, tt, qq[1000], head, tail;
treenode tn[105];
void change1(int k)
{
if(nod[k].next == NULL)
return ;
int i, j;
node *p;
for(p=nod[k].next,j=0;p!=NULL;p=p->next) {
i=p->i;
if(j==0)
{
tn[k].l=&tn[i];
change1(i);
j=1;
}
else
{
tn[i].r=tn[k].l->r;
tn[k].l->r=&tn[i];
change1(i);
}
}
}
void bfs1(int sum)
{
if(sum==0)
return ;
int i,j,k=0;
for(i=1;i<=sum;i++)
{
j=qq[head++];
if(tn[j].l!=NULL)
{
cout< qq[tail++] = tn[j].l->i; k++; } if(tn[j].r != NULL) { cout< qq[tail++] = tn[j].r->i; k++; } } bfs1(k); } void fun1() //树转换二叉树 { memset(nod, 0, sizeof(nod)); cout<<"输入树,结点1默认位根结点\n"< cout<<"输入边数: "< cin>>edge; int i, j, k = 0, x, y; cout<<"以父亲指向儿子方式输入边信息"< for(i = 1, j = 1; i <= edge; i++) { cin>>x>>y; // 将y存入对应结点的i中,next指向父结点的next temp[j].i = y; temp[j].next = nod[x].next; // 父亲的next指向新的结点y nod[x].next = &temp[j]; // 父结点的孩子数增1 nod[x].i++; j++; } // 将tn的内存单元清0 memset(tn, 0, sizeof(tn)) for(i = 1; i <= 100; i++) tn[i].i = i; // 默认1为树的根点 change1(1); cout<<"成功将树转换为二叉树"< cout<<"以边形式输出树"< head = tail = 1; qq[tail++] = 1; bfs1(1); } void dfs(int d, int k) // 二叉树转换为树函数{ int i, j; if(tn[k].l != NULL) { i = tn[k].l->i; temp[tt].i = i; temp[tt].next = nod[k].next; nod[k].next = &temp[tt]; nod[k].i++; tt++; dfs(k, i); } if(tn[k].r != NULL) { j = tn[k].r->i; temp[tt].i = j; temp[tt].next = nod[d].next; nod[d].next = &temp[tt]; nod[d].i++; tt++; dfs(d, j); } } void bfs2(int sum)//输出边 { if(sum == 0) return ; int i, j, k = 0; node *h; for(i = 1; i <= sum; i++) { j = qq[head++]; for(h = nod[j].next; h != 0; h = h->next) { printf("%d %d\n", j, h->i); qq[tail++] = h->i; k++; } } bfs2(k); } void fun2() //二叉树转换树 { memset(nod, 0, sizeof(nod)); //初始化nod memset(tn, 0, sizeof(tn)); //初始化tn int i, j, k = 0, x, y, z; for(i = 1; i <= 100; i++) tn[i].i = i; cout<<"输二叉入树,结点1默认位根结点"< cout<<"输入边数: "; cin>>edge; cout<<"以父亲指向儿子方式输入边信息x y z(z为0或1,0为左儿子,1为右儿子)"< for(i = 1, j = 1; i <= edge; i++) { cin>>x>>y>>z; if(tn[x].l != NULL && tn[x].r != NULL) { cout<<"输入的不是二叉树,退出"< return ; } if(z == 0) { if(tn[x].l != NULL) { cout<<"输入有误,退出"< return; } tn[x].l = &tn[y]; } else { if(tn[x].r != NULL) { cout<<"输入有误,退出"< return; } tn[x].r = &tn[y]; } } if(tn[1].r != NULL) { cout<<"输入的二叉树无法转化为树,退出"< return ; } tt = 1; dfs(0, 1); cout<<"成功将二叉树转换为树"< cout<<"以边形式输出树"< head = tail = 1; qq[tail++] = 1; bfs2(1); } typedef struct Node { char data; //数据域 struct Node *leftChild; //左子树指针 struct Node *rightChild; //右子树指针 } BiTreeNode; //结点的结构定义 // 静态堆,用于前序和中序非递归遍历 typedef struct { BiTreeNode Elem[maxsize]; int top; } SqStack; // 以下的几个结构体用于后序非递归遍历 // 枚举数据,L=left, R=right,用于非递归的后序遍历typedef enum {L, R} tagtype; typedef struct //数据存放的节点定义 { BiTreeNode ptr; tagtype tag; } stacknode; typedef struct//堆栈的结构体,用于非递归的后序遍历{ stacknode Elem[maxsize]; int top; } SequenceStack; typedef struct { BiTreeNode queue[maxsize]; int rear; //队尾指针 int front; //队头指针 int count; //计数器 } SeqCQueue; //(1)初始化QueueInitiate(Q) void QueueInitiate(SeqCQueue *Q) { Q->rear = 0; Q->front = 0; Q->count = 0; } //(2)非空否QueueNotEmpty(Q) //判断循环队列Q非空否,非空则返回1,否则返回0 int QueueNotEmpty(SeqCQueue Q) { if(Q.count != 0) return 1; else return 0; } //(3)入队列QueueAppend(Q, x) //把数据元素值x插入顺序循环队列Q的队尾,成功返回1,失败返回0 int QueueAppend(SeqCQueue *Q, BiTreeNode *x) { if(Q->count > 0 && Q->rear == Q->front) { printf("队列已满无法插入! \n"); return 0; } else { Q->queue[Q->rear] = *x;//数据元素x插入对尾 Q->rear = (Q->rear + 1) % maxsize;//队尾指示器加1 Q->count++; return 1; } } //(4)出队列QueueDelete(Q, d) //删除顺序循环队列Q的队头元素并赋值给d,成功则返回1,失败返回0 int QueueDelete(SeqCQueue *Q, BiTreeNode *d) { if(Q->count == 0) { cout<<"队列已空无数据元素出队列! "< return 0; } else { *d = Q->queue[Q->front];//去队头元素存入d中 Q->front = (Q->front + 1) % maxsize;//队头指示器加1 Q->count--; return 1; } } /*初始化*/ void Initiate(BiTreeNode **root); //初始化建立二叉树的头结点 /*左子树插入结点*/ BiTreeNode *InsertLeftNode(BiTreeNode *curr, char x); /*右子树插入结点*/ BiTreeNode *InsertRightNode(BiTreeNode *curr, char x); //删除左子树 BiTreeNode *DeleteLeftTree(BiTreeNode *curr); //删除右子树 BiTreeNode *DeleteRightTree(BiTreeNode *curr); void PreOrder(BiTreeNode *root, void Visit(char item)); /*前序遍历二叉树t,访问操作为Visit()函数*/ void InOrder(BiTreeNode *root, void Visit(char item)); /*中序遍历二叉树t */ void PostOrder(BiTreeNode *root, void Visit(char item)); /*后序遍历二叉树t */ void Destroy(BiTreeNode **root); void PrintBiTree(BiTreeNode *bt, int n); void Visit(char item);//访问操作为Visit()函数// void PreOrderUnrec(BiTreeNode *t);/*前序遍历二叉树t */ void InOrderUnrec(BiTreeNode *t);/*中序遍历二叉树t */ void PostOrderUnrec(BiTreeNode *t);/*后序遍历二叉树t */ void ccbl(BiTreeNode *h) { SeqCQueue sq1;//初始化设置一个队列 BiTreeNode *sq2 = h; sq2 = (BiTreeNode *)malloc(sizeof(BiTreeNode)); QueueInitiate(&sq1);//初始化队列 QueueAppend(&sq1, h->leftChild); //把根结点指入队列 for(; QueueNotEmpty(sq1) != 0;) //如果队列非空 { QueueDelete(&sq1, sq2); //出列 cout< if(sq2->leftChild != NULL) //左子树非空 { QueueAppend(&sq1, sq2->leftChild); //将该节点的左孩子树指针入列} if(sq2->rightChild != NULL) //右子树非空 QueueAppend(&sq1, sq2->rightChild); //将该节点的右孩子树指针入列} } /*初始化*/ void Initiate(BiTreeNode **root) //初始化建立二叉树的头结点 { *root = (BiTreeNode *)malloc(sizeof(BiTreeNode));//申请动态空间 (*root)->leftChild = NULL;//根节点为空 (*root)->rightChild = NULL;//根节点为空 } /*左子树插入结点*/ BiTreeNode *InsertLeftNode(BiTreeNode *curr, char x) { BiTreeNode *s, *t; if(curr == NULL) return NULL;//若当前结点curr非空,则在curr的左子树插入元素x的新结点 t = curr->leftChild; //保存原curr所指结点的左子树指针 s = (BiTreeNode *)malloc(sizeof(BiTreeNode)); s->data = x; s->leftChild = t; //新插入结点的左子树为原curr的左子树 s->rightChild = NULL; curr->leftChild = s; //新结点为curr的左子树 return curr->leftChild; //返回新插入结点的指针 } /*右子树插入结点*/ BiTreeNode *InsertRightNode(BiTreeNode *curr, char x) { BiTreeNode *s, *t; if(curr == NULL) return NULL; t = curr->rightChild; //保存原curr所指结点的右子树指针 s = (BiTreeNode *)malloc(sizeof(BiTreeNode)); s->data = x; s->rightChild = t; //新插入结点的右子树为原curr的右子树 s->leftChild = NULL; curr->rightChild = s; //新结点为curr的右子树 return curr->rightChild; } //删除左子树 BiTreeNode *DeleteLeftTree(BiTreeNode *curr) { if(curr == NULL || curr->leftChild == NULL) //若curr非空,则删除curr所有指结点的左子树 return NULL; Destroy(&curr->leftChild); curr->leftChild = NULL; return curr;//删除成功,则返回删除结点的双亲结点指针,否则返回空指针} //删除右子树 BiTreeNode *DeleteRightTree(BiTreeNode *curr) { if(curr == NULL || curr->rightChild == NULL) return NULL; Destroy(&curr->rightChild); curr->rightChild = NULL; return curr; } void PreOrder(BiTreeNode *root, void Visit(char item)) /*前序遍历二叉树t,访问操作为Visit()函数*/ { if(root != NULL) { Visit(root->data); PreOrder(root->leftChild, Visit); PreOrder(root->rightChild, Visit); } } void InOrder(BiTreeNode *root, void Visit(char item)) /*中序遍历二叉树t */ { if(root != NULL) { InOrder(root->leftChild, Visit); Visit(root->data); InOrder(root->rightChild, Visit); } } void PostOrder(BiTreeNode *root, void Visit(char item)) /*后序遍历二叉树t */ { if(root != NULL) { PostOrder(root->leftChild, Visit); PostOrder(root->rightChild, Visit); Visit(root->data); } } void Destroy(BiTreeNode **root)//撤销二叉树 if((*root) != NULL && (*root)->leftChild != NULL) Destroy(&(*root)->leftChild); if((*root) != NULL && (*root)->rightChild != NULL) Destroy(&(*root)->rightChild); free(*root); } void PrintBiTree(BiTreeNode *bt, int n)//打印二叉树 { int i; if(bt == NULL) return; //递归出口 PrintBiTree(bt->rightChild, n + 1); //遍历打印右子树 for(i = 0; i < n - 1; i++) cout<<" "; //访问根结点 if(n > 0) { cout<<"---"; cout< } PrintBiTree(bt->leftChild, n + 1); //遍历打印左子树 } //非递归数据的初始化 void StackInit(SqStack *s)//初始化堆栈 { s->top = -1; } void push(SqStack *s, BiTreeNode *p)//入栈 { s->Elem[++s->top] = *p; } BiTreeNode *pop(SqStack *s)//出栈 { return &s->Elem[s->top--]; } int StackEmpty(SqStack *s)//判断顺序堆栈s是否为空,空返回1,非空返回0 { if (s->top <= 0) return 1; else return 0; } void Visit(char item)//访问函数Visit { cout< // 前序非递归 void PreOrderUnrec(BiTreeNode *t) { SqStack s; BiTreeNode *p = t; StackInit(&s);//初始化堆栈s push(&s, p); //把根结点的元素入栈 p = p->leftChild; while (p != NULL || !StackEmpty(&s)) //若堆栈非空 { while (p != NULL) // //遍历左子树 { Visit(p->data);//出栈取得一个结点指针 push(&s, p); p = p->leftChild; } if (!StackEmpty(&s)) //通过下一次循环中的内嵌while实现右子树遍历 { p = pop(&s); p = p->rightChild; } } } // 中序非递归 void InOrderUnrec(BiTreeNode *t) { SqStack s; BiTreeNode *p = t; StackInit(&s); while (p != NULL || !StackEmpty(&s)) { while (p != NULL) //遍历左子树 { push(&s, p); p = p-> leftChild; }//endwhile if (!StackEmpty(&s)) { p = pop(&s); Visit(p-> data); //访问根结点 p = p-> rightChild; //通过下一次循环实现右子树遍历 }//endif }//endwhile }//InOrderUnrec //为后序遍历非递归算法而设置的堆栈 void StackInit3(SequenceStack *s) { s->top = -1; } void push3(SequenceStack *s, stacknode *p) { s->Elem[++s->top] = *p; } stacknode *pop3(SequenceStack *s) { return &s->Elem[s->top--]; } int StackEmpty3(SequenceStack *s) { if (s->top <= 0) return 1; else return 0; } // 3.后序遍历非递归算法 void PostOrderUnrec(BiTreeNode *t) { SequenceStack s;//堆栈的定义 stacknode x;//数据存放的节点定义 BiTreeNode *p = t; //二叉树的定义 StackInit3(&s); do { while (p != NULL) //遍历左子树 { x.ptr = *p; x.tag = L; //标记为左子树 push3(&s, &x); p = p-> leftChild; } while (!StackEmpty3(&s) && s.Elem[s.top].tag == R) { x = *pop3(&s); p = &x.ptr; Visit(p-> data); //tag为R,表示右子树访问完毕,故访问根结点 } if (!StackEmpty3(&s)) { s.Elem[s.top].tag = R; //遍历右子树 p = s.Elem[s.top].ptr.rightChild; } } while (!StackEmpty3(&s)); }//PostOrderUnrec void menu(BiTreeNode *root,BiTreeNode *p) { Initiate(&root); p = InsertLeftNode(root, 'A'); p = InsertLeftNode(p, 'B'); p = InsertLeftNode(p, 'D'); p = InsertRightNode(p, 'G'); p = InsertRightNode(root->leftChild, 'C'); InsertLeftNode(p, 'E'); InsertRightNode(p, 'F'); { int k; cout<<" 王亚斌的课程设计"; cout<<" 树和二叉树的遍历"; cout<<" "; cout< do { cout< cout< cout< cout< cout< cout< cout< cout< cout< cout< cout< cout< cin>>k; switch(k) { case 1: { cout<<"二叉树的建立:"< PrintBiTree(root, 0); } break; case 2: { cout<<"二叉树的前序递归遍历:";//调用PreOrder(root->leftChild, Visit)前序遍历 PreOrder(root->leftChild, Visit); } break; case 3: { cout<<"二叉树的中序递归遍历:";//调用InOrder(root->leftChild, Visit)中序遍历 InOrder(root->leftChild, Visit); } break; case 4: { cout<<"二叉树的后序递归遍历:"; //调用PostOrder(root->leftChild, Visit) 后序遍历 PostOrder(root->leftChild, Visit); } break; case 5: { cout<<"二叉树前序非递归遍历:";//调用PreOrderUnrec(root)前序非递归遍历 PreOrderUnrec(root); } break; case 6: { cout<<"二叉树中序非递归遍历:";//调用InOrderUnrec(root) 中序非递归遍历 InOrderUnrec(root); } break; case 7: { cout<<"二叉树后序非递归遍历:";//调用PostOrderUnrec(root)后序非递归 遍历 PostOrderUnrec(root); } break; case 8: { cout<<"二叉树层序非递归遍历:";//调用ccbl(root) 层次非递归遍历 ccbl(root); } break; case 9: { fun1(); } break; case 10: { fun2(); } break; } } while(k >= 0 && k < 9); } } int main() { BiTreeNode *root, *p; menu(root,p); Destroy(&root); return 0; }