文章目录
实验五 树的应用–二叉树的遍历
一、实验目的:
1、了解二叉树的逻辑结构和物理结构;
逻辑结构:1对多的关系,层次关系明显
物理结构:在内存的存储结构,常用的有二叉链表和三叉链表
2、掌握二叉树数据类型定义;
3、熟练掌握二叉树在链式存储结构上的遍历操作;
深度遍历:先序遍历、中序遍历、后序遍历
*广度遍历:层次遍历
二、实验要求:
基本要求:编程实现二叉树的先序、中序、后序遍历方式(递归方式);
*编程实现二叉树的层次遍历方式(递归或非递归方式);
*统计二叉树中各种结点的个数;
三、实验任务:
1.从终端输入二叉树元素序列,
2.建立对应的二叉树;
3.采用递归的方式先序遍历并输出遍历序列
4.中序遍历并输出遍历序列
5.后序遍历二叉树并输出遍历序列;
6.*采用递归或非递归的方式层次遍历二叉树;*采用递归的方式统计二叉树中度为0、度为1、度为2的结点个数;ps:下面我采用的是递归方式
7.采用递归方式销毁二叉树。
例如:建立如下图1所示的二叉树,则在终端输入“AB##DE##C##”序列,其中“#”表示空树。程序运行结果参考见图2。
图1 二叉树
图2 程序运行结果
四、代码如下
// 采用递归算法实现二叉树的三种深度遍历:先序遍历、中序遍历、后序遍历,并统计二叉树中各种结点的个数。
// 二叉树的存储结构采用的二叉链表
// 例如输入AB##DE##C##,则确定要建立的二叉树
// 采用递归方式先序、中序、后序遍历二叉树
// 采用后序方式销毁二叉树
// 统计二叉树中各种结点的个数
#include<iostream.h>
#include<stdlib.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
typedef int status;
typedef char TElemType;
//二叉树的二叉链表存储结构
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode, *BiTree;
//创建二叉树status CreatBiTree(BiTree &t)
void CreateBiTree(BiTree &T){
TElemType ch;
cin>>ch;
if(ch=='#'){
T=NULL;
}else{
T=new BiTNode;
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//先序遍历二叉树void PreOrderTraverse(BiTree t)
void PreOrderTraverse(BiTree T){
if(T){
cout<<T->data;
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
//中序遍历二叉树void InOrderTraverse(BiTree t)
void InOrderTraverse(BiTree T){
if(T){
InOrderTraverse(T->lchild);
cout<<T->data;
InOrderTraverse(T->rchild);
}
}
//后序遍历二叉树void PostOrderTraverse(BiTree t)
void PostOrderTraverse(BiTree T){
if(T){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data;
}
}
//后序销毁二叉树void DestroyBiTree(BiTree &t)
void Destroy(BiTree &T){
if(T){
if(T->lchild!=NULL){
Destroy(T->lchild);}
if(T->rchild!=NULL){
Destroy(T->rchild);}
if(T!=NULL){
free(T);}
}
}
//统计二叉树中度为0的结点的个数int Node0Count( BiTree t)
int Node0Count(BiTree T) {
if(T){
//是叶子节点就返回1,不是就继续递归
if(T->lchild==NULL&&T->rchild==NULL){
return 1;
}else{
return Node0Count(T->lchild)+Node0Count(T->rchild);
}
}else{
return 0;
}
}
//统计二叉树中度为1的结点的个数int Node1Count( BiTree t)
int Node1Count(BiTree T) {
if(T){
if(T->lchild!=NULL&&T->rchild==NULL||T->lchild==NULL&&T->rchild!=NULL){
//如果有一个结点,但是我们不能确定之后的节点出现在哪个子树上,所以还需要遍历子树
return Node1Count(T->lchild)+Node1Count(T->rchild)+1;
}else{
return Node1Count(T->lchild)+Node1Count(T->rchild);
}
}
return 0;
}
//统计二叉树中度为2的结点的个数int Node2Count( BiTree t)
int Node2Count(BiTree T) {
if(T){
if(T->lchild!=NULL&&T->rchild!=NULL){
//如果有两个结点,我们需要遍历左右两个子树
return Node2Count(T->lchild)+Node2Count(T->rchild)+1;
}else{
return Node2Count(T->lchild)+Node2Count(T->rchild);
}
}
return 0;
}
void main(){
int ch;
BiTree t=NULL;
cout<<"命令菜单:\n\t1.建立二叉树\n\t2.先序遍历\n\t3.中序遍历\n\t4.后序遍历\n\t5.遍历二叉树所有节点\n\t6.销毁二叉树\n\t7.退出"<<endl;
cout<<"\n请输入命令:";
cin>>ch;
while(ch!=8){
switch(ch){
case 1: cout<<"\n请输入要建立的二叉树中的元素,#代表空树\n";
CreateBiTree(t);
cout<<"二叉树建立成功\n";
cout<<"\n请继续输入命令:";
break;
case 2: cout<<"先序遍历的结果为:";
PreOrderTraverse(t);
cout<<"\n\n请继续输入命令:";
break;
case 3: cout<<"中序遍历的结果为:";
InOrderTraverse(t);
cout<<"\n\n请继续输入命令:";
break;
case 4: cout<<"后序遍历的结果为:";
PostOrderTraverse(t);
cout<<"\n\n请继续输入命令:";
break;
case 5: cout<<"二叉树中度为0的结点个数为:"<<Node0Count(t)<<endl;
cout<<"二叉树中度为1的结点个数为:"<<Node1Count(t)<<endl;
cout<<"二叉树中度为2的结点个数为:"<<Node2Count(t)<<endl;
cout<<"\n\n请继续输入命令:";
break;
case 6: Destroy(t);
cout<<"二叉树已销毁.";
cout<<"\n\n请继续输入命令:";
break;
default: cout<<"\n输入命令出错,请重新输入命令:";
}
cin>>ch;
}
}//main