一、实验目的
(1)掌握二叉树的逻辑结构;
(2)掌握二叉树的二叉链表存储结构;
(3)掌握基于二叉链表存储的二叉树的遍历操作的实现。
二、实验内容
(1)建立一棵含有n个结点的二叉树,采用二叉链表存储;
(2)前序(或中序、后序)遍历该二叉树。
(3)统计该二叉树中叶子个数。
(4)统计该二叉树中结点个数。
(5)求该二叉树的深度。
要求:
(1)设计菜单,根据菜单提示进行操作。
(2)按先序遍历序列创建二叉树的二叉链表。
注:二叉树的遍历一般采用递归算法,只要涉及到递归,一定会使用堆栈来实现。虽然在程序中看不到具体的堆栈,但可以通过观察函数调用的关系来理解认识堆栈。堆栈是实现二叉树遍历的最基本的数据结构。
三、算法设计
1、先序遍历递归建立二叉树
步骤
- 扫描字符序列, 读入字符
ch
。 - 如果ch是一个
"#"
字符, 则表明该二叉树为空树, 即BT
为NULL
; 3. 否则执行以下操作:
申请一个结点空间BT
;
将ch
赋给BT-> data
;
递归创建BT
的左子树;
递归创建BT
的右子树;
算法
void CreateBiTree(BiTree &BT){
if(ch=='#')
BT = NULL;
else{
BT = new BiTNode;
BT->data = ch;
CreateBiTree (BT->Lchild);
CreateBiTree (BT->Rchild);
}
}
2、遍历二叉树
2.1 先序遍历
步骤
若二叉树为空,则空操作;
否则 :
- 访问根结点;
- 先序遍历左子树;
- 先序遍历右子树
算法
void PreOrder(BiTree &BT){
if(BT){
Visit(BT);
PreOrder(BT->Lchild);
PreOrder(BT->Rchild);
}
}
2.2 中序遍历
步骤
若二叉树为空,则空操作;
否则
- 中序遍历左子树;
- 访问根结点;
- 中序遍历右子树。
算法
void InOrder(BiTree BT){
if(BT){
InOrder(BT->Lchild);
Visit(BT);
InOrder(BT->Rchild);
}
}
2.3 后序遍历
步骤
若二叉树为空,则空操作;
否则
- 后序遍历左子树;
- 后序遍历右子树;
- 访问根结点。
算法
void PostOrder(BiTree BT){
if(BT){
PostOrder(BT->Lchild);
PostOrder(BT->Rchild);
Visit(BT);
}
}
3、统计二叉树叶子结点个数
步骤
- 如果是空树,则结点个数为 0;
- 如果只有根结点则就1个叶子结点;
- 否则,结点个数为左子树的叶子结点个数加上右子树的叶子结点个数。
算法
int LeafCount(BiTree &BT){
if(!BT)
return ERROR;
if(!BT->Lchild&&!BT->Rchild)
return OK;
return(LeafCount(BT->Lchild)+LeafCount(BT->Rchild));
}
4、交换二叉树左右子树
算法
void ChangeLR(BiTree BT){
BiTree St;
if(BT){
ChangeLR(BT->Lchild);
ChangeLR(BT->Rchild);
St = BT->Lchild;
BT->Lchild = BT->Rchild;
BT->Rchild = St;
}
}
5、统计二叉树中结点的总数
步骤
- 如果是空树,则结点个数为 0;
- 否则,结点个数为左子树的结点个数加上右子树的结点个数再加上 1 。
算法
int NodeCount(BiTree BT){
if(!BT)
return ERROR;
else
return(NodeCount(BT->Lchild)+NodeCount(BT->Rchild)+1);
}
6、求二叉树的深度
步骤
如果是空树,递归结束,深度为0;
否则执行以下操作:
- 递归计算左子树的深度记为m;
- 递归计算右子树的深度记为n;
- 如果 m 大于 n, 二叉树的深度为 m+1, 否则为 n+1。
算法
int Depth(BiTree BT){
int h1,h2;
if(BT==NULL)
return ERROR;
h1 = Depth(BT->Lchild);
h2 = Depth(BT->Rchild);
if(h1>h2)
return(h1 + 1);
else
return(h2 + 1);
}
四、运行结果
五、代码实现
#include<stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
#define TElemType char
typedef struct BiTNode{
TElemType data;
struct BiTNode *Lchild,*Rchild;
}BiTNode,*BiTree;
//显示根结点
void Visit(BiTree BT){
printf("%c",BT->data);
}
//先序遍历
void PreOrder(BiTree BT){
if(BT){
Visit(BT);
PreOrder(BT->Lchild);
PreOrder(BT->Rchild);
}
}
//中序遍历
void InOrder(BiTree BT){
if(BT){
InOrder(BT->Lchild);
Visit(BT);
InOrder(BT->Rchild);
}
}
//后序遍历
void PostOrder(BiTree BT){
if(BT){
PostOrder(BT->Lchild);
PostOrder(BT->Rchild);
Visit(BT);
}
}
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树
void CreateBiTree(BiTree &BT){
char ch;
scanf("%c",&ch);
if(ch!='#'){
BT =new BiTNode;
// if(!BT)
// exit(-1);
BT->data = ch;
CreateBiTree(BT->Lchild);
CreateBiTree(BT->Rchild);
}
else{
BT = NULL;
}
}
//统计二叉树中叶子结点的个数
int LeafCount(BiTree &BT){
if(!BT)
return ERROR;
if(!BT->Lchild&&!BT->Rchild)
return OK;
return(LeafCount(BT->Lchild)+LeafCount(BT->Rchild));
}
//交换二叉树的左右子树
void ChangeLR(BiTree BT){
BiTree St;
if(BT){
ChangeLR(BT->Lchild);
ChangeLR(BT->Rchild);
St = BT->Lchild;
BT->Lchild = BT->Rchild;
BT->Rchild = St;
}
}
//统计二叉树中结点的总数
int NodeCount(BiTree BT){
if(!BT)
return ERROR;
else
return(NodeCount(BT->Lchild)+NodeCount(BT->Rchild)+1);
}
//求二叉树的深度
int Depth(BiTree BT){
int h1,h2;
if(BT==NULL)
return ERROR;
h1 = Depth(BT->Lchild);
h2 = Depth(BT->Rchild);
if(h1>h2)
return(h1 + 1);
else
return(h2 + 1);
}
//销毁二叉树
void DestroyBiTree(BiTree BT){
if(!BT)return;
DestroyBiTree(BT->Lchild);
DestroyBiTree(BT->Rchild);
delete BT;
}
void Showmenu(){
printf("\n");
printf(" --二叉树基本操作运算-- \n");
printf("******************************\n");
printf("* 1---建立二叉树 *\n");
printf("* 2---先序遍历 *\n");
printf("* 3---中序遍历 *\n");
printf("* 4---后序遍历 *\n");
printf("* 5---统计叶子数 *\n");
printf("* 6---统计结点数 *\n");
printf("* 7---求二叉树深度 *\n");
printf("* 8---交换左右子树 *\n");
printf("* 0---退出 *\n");
printf("*****************************\n");
printf("请选择菜单号(0-8):");
}
void binaryOP(){
BiTree BT;
int count = 0;
int choice;
while(choice){
Showmenu();
scanf("%d",&choice);
switch(choice){
case 1:
printf("按先序输入二叉树结点序列:\n");//以#结束
CreateBiTree(BT);
printf("二叉树建立成功!\n");
break;
case 2:
if(BT == NULL){
printf("空树!\n");
}
else{
printf("先序遍历序列为:");
PreOrder(BT);
}
break;
case 3:
if(BT == NULL){
printf("空树!\n");
}
else{
printf("中序遍历序列为:");
InOrder(BT);
}
break;
case 4:
if(BT == NULL){
printf("空树!\n");
}
else{
printf("后序遍历序列为:");
PostOrder(BT);
}
break;
case 5:
count = LeafCount(BT);
printf("该二叉树有%d个叶子结点。\n",count);
break;
case 6:
count = NodeCount(BT);
printf("该二叉树有%d个结点。\n",count);
break;
case 7:
printf("该二叉树的深度为%d !\n",Depth(BT));
break;
case 8:
ChangeLR(BT);
printf("交换成功!\n");
printf("先序序列为:\n");
PreOrder(BT);
break;
case 0:
printf("程序结束!\n");
break;
}
}
}
int main(){
binaryOP();
return 0;
}
作者文坛写于 2020年5月21日