数据结构——二叉树的遍历

信息科学与技术学院 《数据结构》课程设计报告

完成日期: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<i<

qq[tail++] = tn[j].l->i;

k++;

}

if(tn[j].r != NULL)

{

cout<i<

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<data;

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<data<

}

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;

}

相关文档
最新文档