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