一. 实验目的
将树的基本操作C语言实现,主要考察树的先序,中序,后序和层次遍历。
二.主要内容
本文所使用的二叉树如图:
显然
先序:ABCDEGF
中序:CBEGDFA
后序:CGEFDBA
层次:ABCDEFG
BiTree.h内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
typedef char TElemType; typedef int Status; typedef struct BiTNode{ TElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; Status PreCreateBiTree(BiTree &T);//先序输入二叉树 Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e)); Status InOrderTraverse1(BiTree T,Status(*Visit)(TElemType e)); Status InOrderTraverse2(BiTree T,Status(*Visit)(TElemType e)); Status PostOrderTraverse(BiTree T,Status(*Visit)(TElemType e)); Status LevelOrderTraverse(BiTree T,Status(*Visit)(TElemType e)); Status Visit(TElemType e); Status GetDepth(BiTree T); Status CountNode(BiTree T,int &d); |
主要函数:
① 先序创建二叉树
注意创建的时候如果没有左右子树要输入空格
输入:ABC_ _DE_G_ _F_ _ _
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Status PreCreateBiTree(BiTree &T) { char ch; ch=getchar(); if(ch==' ')T=NULL; else { if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))exit(OVERFLOW); T->data=ch; PreCreateBiTree(T->lchild); PreCreateBiTree(T->rchild); } return OK; } |
② 先序遍历(递归算法)
1 2 3 4 5 6 7 8 9 |
Status PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e)) { if(T){ if(Visit(T->data)) if(PreOrderTraverse(T->lchild,Visit)) if(PreOrderTraverse(T->rchild,Visit))return OK; return ERROR; }else return OK; } |
③ 中序遍历(递归算法)
1 2 3 4 5 6 7 8 9 |
Status InOrderTraverse2(BiTree T,Status(*Visit)(TElemType e)) { if(T){ InOrderTraverse2(T->lchild,Visit); Visit(T->data); InOrderTraverse2(T->rchild,Visit); } return OK; } |
④ 中序遍历(非递归算法)
注意此处需要包含C++STL头文件include<stack>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Status InOrderTraverse1(BiTree T,Status(*Visit)(TElemType e)) { stack<BiTree>S; BiTree p; S.push(T); while(!S.empty()){ while(p=S.top())S.push(p->lchild); p=S.top(); S.pop(); if(!S.empty()){ p=S.top(); S.pop(); if(!Visit(p->data))return ERROR; S.push(p->rchild); } return OK; } } |
⑤ 后序遍历(递归算法)
1 2 3 4 5 6 7 8 9 10 |
Status PostOrderTraverse(BiTree T,Status(*Visit)(TElemType e)) { if(T){ PostOrderTraverse(T->lchild,Visit); PostOrderTraverse(T->rchild,Visit); Visit(T->data); } return OK; } |
⑥ 层次遍历(使用QUEUE)
可以包含STL<queue>或者定义一个数组,使用循环队列即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Status LevelOrderTraverse(BiTree T,Status(*Visit)(TElemType e)) { BiTree p; BiTNode *Q[100]; int front,rear; front=rear=-1; rear++; Q[rear]=T; while(front!=rear){ front=(front+1)%100; p=Q[front]; Visit(p->data); if(p->lchild!=NULL){ rear=(rear+1)%100; Q[rear]=p->lchild; } if(p->rchild!=NULL){ rear=(rear+1)%100; Q[rear]=p->rchild; } } return OK; } |
⑦ Visit函数此处使用的是输出
1 2 3 4 5 |
Status Visit(TElemType e) { printf("%c ",e); return OK; } |
⑧ 计算树的节点数
1 2 3 4 5 6 7 8 9 |
Status CountNode(BiTree T,int &d) { if(T){ d++; CountNode(T->lchild,d); CountNode(T->rchild,d); } return OK; } |
⑨ 计算树的深度
1 2 3 4 5 6 7 8 9 10 11 |
Status GetDepth(BiTree T) { int hl,hr; if(T==NULL)return 0; else{ hl=GetDepth(T->lchild); hr=GetDepth(T->rchild); if(hl>hr)return hl+1; else return hr+1; } } |
Main函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
int main() { printf("16软件工程 徐奕 E21614061\n"); printf("Create\n"); BiTree T; PreCreateBiTree(T); printf("先序PreTraverse:\n"); PreOrderTraverse(T,Visit); printf("\n中序InTraverse:\n"); InOrderTraverse2(T,Visit); printf("\n后序PostTraverse:\n"); PostOrderTraverse(T,Visit); printf("\nLevelTraverse:\n"); LevelOrderTraverse(T,Visit); printf("\n"); CountNode(T,d); printf("\n节点数:%d\n",d); printf("树的深度:%d\n",GetDepth(T)); system("pause"); return 0; } |
实验小结
1. 遍历函数可以写成递归和非递归,递归函数更加简洁。
2. 层次遍历需要使用队列,可以包含C++STL<queue>或者定义一个数组,使用循环队列即可。注意每次判断时要把队列的头赋值给临时变量P,左右子树从队尾插入。
3.先序创建树时,要注意创建的时候如果没有左右子树要输入空格
输入:ABC_ _DE_G_ _F_ _ _