二叉树的基本操作

实验内容

设计一个与二叉树基本操作相关的演示程序,要求实现以下功能:

(1)创建二叉树。按照用户需要的二叉树,构建二叉树。

(2)将创建的二叉树以树状形式输出。

(3)分别以先序,中序,后序三种遍历方式访问二叉树。

(4)输出二叉树的叶子结点以及叶子结点的个数。

(5)输出二叉树的高度。

存储结构设计

本程序采用二叉链式存储结构(BiTNode)存储二叉树的结点信息。二叉树的链表中的结点至少包括三个域:数据域(data),左孩子指针域(LChild),右孩子指针域(RChild)。

系统功能设计

本程序除了完成二叉树的创建功能外,还设置了8个子功能菜单。由于这8个子功能都是建立在二叉树的构造上,所以二叉树的创建由主函数main()完成。8个子功能设计描述如下:

(1)树状输出二叉树。树状输出二叉树由函数TranslevelPrint()实现。当用户选择该功能时,系统以树状的形式输出用户所创建的二叉树。

(2)先序遍历二叉树。由函数PreOrder()实现。该功能按照先序遍历访问二叉树的方法输出先序序列。

(3)中序遍历二叉树。由函数InOrder()实现。该功能按照中序遍历访问二叉树的方法输出中序序列。

(4)后序遍历二叉树。由函数PostOrder()实现。该功能按照后序遍历访问二叉树的方法输出后序序列。

(5)输出叶子结点。该功能采用先序遍历二叉树的方法,依次输出叶子结点。由函数PreOrderLeaf()实现。

(6)输出叶子结点个数。该功能计算并输出二叉树叶子结点的个数,由LeafCount()函数实现。采用递归算法计算二叉树叶子结点的个数,算法思想是:当二叉树为空时,叶子总结点数为0;当二叉树只有一个结点时,叶子结点个数为1;否则,叶子结点总数为左右子树结点之和。

(7)输出二叉树的深度。该功能即输出二叉树结点所在层次的最大值。由函数PostOrderDepth()实现。

(8)退出。由函数exit()实现。

  1 #include<conio.h>
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #define MAXLEN 100
  6 #define NLAYER 4
  7 typedef struct BiTNode
  8 {
  9     /* data */
 10     char data;
 11     struct BiTNode *LChild,*RChild;
 12 }BiTNode,*BiTree;
 13 BiTree T;
 14 //建立二叉树
 15 void CreatBiTree(BiTree *bt)//按照先序序列建造二叉树
 16 {
 17     char ch;
 18     scanf("%c",&ch);
 19     if(ch=='#') *bt=NULL;
 20     else
 21     {
 22         *bt=(BiTree)malloc(sizeof(BiTNode));//生成一个新的结点
 23         (*bt)->data=ch;
 24         CreatBiTree(&((*bt)->LChild));//生成左子树
 25         CreatBiTree(&((*bt)->RChild));
 26     }
 27 }
 28 //树形打印二叉树
 29 void TranslevelPrint(BiTree bt)
 30 {
 31     //本算法实现二叉树的按层打印
 32     struct node
 33     {
 34         /* data */
 35         BiTree vec[MAXLEN];//存放树结点
 36         int layer[MAXLEN];//结点所在的层
 37         int locate[MAXLEN];//打印结点的位置
 38         int front,rear;
 39     }q;  //定义队列q
 40     int i,j=1,k=0,nlocate;
 41     q.front=0;    q.rear=0;//初始化队列q队头,队尾
 42     printf("  ");
 43     q.vec[q.rear]=bt;//将二叉树根节点入队列
 44     q.layer[q.rear]=1;
 45     q.locate[q.rear]=20;
 46     q.rear=q.rear+1;
 47     while(q.front<q.rear)
 48     {
 49         bt=q.vec[q.front];
 50         i=q.layer[q.front];
 51         nlocate=q.locate[q.front];
 52         if (j<i)   //进层打印时换行
 53         {
 54             printf("\n\n");
 55             j=j+1; k=0;
 56             while(k<nlocate)
 57             {
 58                 printf("  ");
 59                 k++;
 60             }
 61         }
 62         while(k<(nlocate-1))
 63         {
 64             printf("  ");
 65             k++;
 66         }
 67         printf("%c",bt->data );
 68         q.front=q.front+1;
 69         if(bt->LChild !=NULL)//存在左子树,将左子树根节点入队列
 70         {
 71             q.vec[q.rear]=bt->LChild;
 72             q.layer[q.rear]=i+1;
 73             q.locate[q.rear]=(int)(nlocate-pow(2,NLAYER-i-1));
 74             q.rear=q.rear+1;
 75         }
 76         if(bt->RChild !=NULL)
 77         {
 78             q.vec[q.rear]=bt->RChild;
 79             q.layer[q.rear]=i+1;
 80             q.locate[q.rear]=(int)(nlocate+pow(2,NLAYER-i-1));
 81             q.rear=q.rear+1;
 82         }
 83     }
 84 }
 85 //输出结点
 86 void Visit(char ch)
 87 {
 88     printf("%c",ch );
 89 }
 90 //先序遍历二叉树
 91 void PreOrder(BiTree root)
 92 {
 93     //先序遍历二叉树,root为指向二叉树跟结点的指针
 94     if(root!=NULL)
 95     {
 96         Visit(root->data);//访问根结点
 97         PreOrder(root->LChild);//先序遍历左子树
 98         PreOrder(root->RChild);//先序遍历右子树
 99     }
100 }
101 //中序遍历二叉树
102 void InOrder(BiTree root)
103 {
104     if(root!=NULL)
105     {
106         InOrder(root->LChild);
107         Visit(root->data);
108         InOrder(root->RChild);
109     }
110 }
111 //后序遍历二叉树
112 void PostOrder(BiTree root)
113 {
114     if(root!=NULL)
115     {
116         PostOrder(root->LChild);
117         PostOrder(root->RChild);
118         Visit(root->data);
119     }
120 }
121 //输出叶子结点
122 void PreOrderLeaf(BiTree root)
123 {
124     //先序遍历二叉树并输出叶子结点
125     if(root!=NULL)
126     {
127         if(root->LChild==NULL&& root->RChild==NULL)
128             printf("%c",root->data );//输出叶子结点
129         PreOrderLeaf(root->LChild);
130         PreOrderLeaf(root->RChild);
131     }
132 }
133 //输出叶子结点的个数
134 int LeafCount(BiTree root)
135 {
136     int LeafNum;
137     if(root==NULL) LeafNum=0;
138     else if((root->LChild==NULL)&&(root->RChild==NULL))  LeafNum=1;
139     else LeafNum=LeafCount(root->LChild)+LeafCount(root->RChild);
140     //叶子数为左右子树数目之和
141     return LeafNum;
142 }
143 //输出二叉树的深度
144 int PostTreeDepth(BiTree root)
145 {
146     //后序遍历求二叉树的深度递归算法
147     int hl,hr,max;
148     if(root!=NULL)
149     {
150         hl=PostTreeDepth(root->LChild);//求左子树的深度
151         hr=PostTreeDepth(root->RChild);//求右子树的深度
152         max=hl>hr?hl:hr;//得到左右子树深度较大者
153         return(max+1);
154     }
155     else
156         return 0;
157 }
158 //主要工作函数,操作区用户界面
159 void mainwork()
160 {
161     int yourchoice;
162     printf("\n-------------------------欢迎使用二叉树基本操作程序-------------------\n");
163     printf("\n                                菜 单 选 择                         \n\n");
164     printf("      1.树状输出二叉树                        2.先序遍历二叉树          \n");
165     printf("      3.中序遍历二叉树                        4.后序遍历二叉树          \n");
166     printf("      5.输出叶子结点                          6.输出叶子结点的个数      \n");
167     printf("      7.输出二叉树的深度                      8.退出                    \n");
168     printf("\n----------------------------------------------------------------------\n");
169     printf("请输入您的选择:");
170     scanf("%d",&yourchoice);
171     while(!(yourchoice==1||yourchoice==2||yourchoice==3||yourchoice==4
172                ||yourchoice==5||yourchoice==6||yourchoice==7||yourchoice==8))
173     {
174         printf("输入选择不明确,请重新输入:\n");
175         scanf("%d",&yourchoice);
176     }
177     while(1)
178     {
179         switch(yourchoice)
180         {
181             case 1:printf("树的形状为:\n"); TranslevelPrint(T);getch();break;
182             case 2:printf("先序遍历序列:\n"); PreOrder(T);getch(); break;
183             case 3:printf("中序遍历序列:\n"); InOrder(T); getch();break;
184             case 4:printf("后序遍历序列:\n"); PostOrder(T); getch();break;
185             case 5:printf("叶子结点为:\n");   PreOrderLeaf(T); getch();break;
186             case 6:printf("叶子结点的个数为:%d",LeafCount(T)); getch();break;
187             case 7:printf("二叉树的深度为:%d",PostTreeDepth(T)); getch();break;
188             case 8:system("cls");exit(0);break;
189         }
190         printf("\n-------------------------欢迎使用二叉树基本操作程序-------------------\n");
191         printf("\n                                菜 单 选 择                         \n\n");
192         printf("      1.树状输出二叉树                        2.先序遍历二叉树          \n");
193         printf("      3.中序遍历二叉树                        4.后序遍历二叉树          \n");
194         printf("      5.输出叶子结点                          6.输出叶子结点的个数      \n");
195         printf("      7.输出二叉树的深度                      8.退出                    \n");
196         printf("\n----------------------------------------------------------------------\n");
197         printf("请输入您的选择:");
198         scanf("%d",&yourchoice);
199     }
200 }
201 //主函数
202 int main()
203 {
204 
205     printf("首先请输入二叉树的结点序列:\n");
206     CreatBiTree(&T);
207     printf("请按菜单提示操作:\n");
208     mainwork();
209     return 0;
210 }

测试结果

(1)首先输入二叉树结点:

 

(2)出现主界面:

 

(3)分别选择不同的功能即可得到不同的结果:

 

树状输出: 先序,中序,后序遍历分别显示如下:

 

 

 

(4)选择功能5,6,7即可出现叶子结点,叶子结点的个数,和该二叉树的深度

 

 

 

最后,选择功能8,退出该系统。

 

posted @ 2015-05-02 18:55  CSUER  阅读(9953)  评论(0编辑  收藏  举报