实验目标
(1)掌握二叉树的定义、性质及存储方式;
(2)掌握二叉树的各种遍历算法。
实验要求
(1)采用二叉树链表作为存储结构,完成二叉树的建立;
(2)提供对二叉树的先序、中序和后序以及按层次遍历的操作;
(3)提供求所有叶子及结点总数的操作。
开发环境
(1)开发语言:C语言或C++语言;
(2)操作系统:Windows、Linux、Mac OS等均可;
(3)开发IDE:工具不限,推荐使用CodeBlocks和Dev C++。
实验完整代码
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#define Max 20 //结点的最大个数
typedef struct node{
char data;
struct node *lchild, *rchild;
}BinTNode; //自定义二叉树的结点类型
typedef BinTNode *BinTree; //定义二叉树的指针
int NodeNum,leaf; //NodeNum为结点数,leaf为叶子数,其实并没有用到这两个定义
typedef struct{
BinTree base[100];
int front,rear;
}SqQueue; //为了后面层序遍历做准备,定义一个队列
BinTree CreateBinTree(void); //基于先序遍历算法创建二叉树
void Preorder(BinTree T) ; //先序遍历二叉树
void Inorder(BinTree T) ; //中序遍历二叉树
void Postorder(BinTree T) ; //后序遍历二叉树
int TreeDepth(BinTree T) ; //采用后序遍历求二叉树的深度、结点数及叶子数的递归算法
void Levelorder(BinTree T) ; //层次遍历二叉树
int countleaf(BinTree T) ; //数叶子节点个数
int NodeCount(BinTree T) ; //数所有节点个数【原来没有这个函数】
/*****************************/
/* 主函数 */
/*****************************/
void main()
{
BinTree root;
char i;
int depth;
printf("\n");
printf("Creat Bin_Tree; Input preorder:"); //输入完全二叉树的先序序列,用#代表虚结点,如ABD###CE##F##
root=CreateBinTree(); //创建二叉树,返回根结点
do { //从菜单中选择遍历方式,输入序号。
printf("\t********** select ************\n");
printf("\t1: Preorder Traversal\n");
printf("\t2: Iorder Traversal\n");
printf("\t3: Postorder traversal\n");
printf("\t4: PostTreeDepth,Node number,Leaf number\n");
printf("\t5: Level Depth\n"); //按层次遍历之前,先选择4,求出该树的结点数。
printf("\t0: Exit\n");
printf("\t*******************************\n");
fflush(stdin);
scanf("%c",&i); //输入菜单序号(0-5)
switch (i-'0'){
case 1: printf("Print Bin_tree Preorder: ");
Preorder(root); //先序遍历
break;
case 2: printf("Print Bin_Tree Inorder: ");
Inorder(root); //中序遍历
break;
case 3: printf("Print Bin_Tree Postorder: ");
Postorder(root); //后序遍历
break;
case 4:
depth=TreeDepth(root); //求树的深度及叶子数
printf("BinTree Depth=%d BinTree Node number=%d",depth,NodeCount(root));
printf(" BinTree Leaf number=%d",countleaf(root));
break;
case 5: printf("LevePrint Bin_Tree: ");
Levelorder(root); //按层次遍历
break;
default: exit(1);
}
printf("\n");
} while(i!=0);
}
/********************************/
/* 基于先序遍历算法创建二叉树 */
/********************************/
//要求输入先序序列,其中加入虚结点"#"以示空指针的位置
BinTree CreateBinTree(void)
{
char ch;
BinTree T=NULL;
scanf("%c",&ch);
if(ch=='#')return T;
else
{
T= (BinTree)malloc(sizeof(BinTNode));//先创建一个结点,使用递归算法
T->data=ch;
T->lchild=CreateBinTree();//创建左子树
T->rchild=CreateBinTree();//创建右子树
}
return T;
}
/********************************/
/* 先序遍历二叉树 */
/********************************/
void Preorder(BinTree T)
{
if(T==NULL)return ;
else
{
printf("%c-->",T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
/********************************/
/* 中序遍历二叉树 */
/********************************/
void Inorder(BinTree T)
{
if(T==NULL)return ;
else
{
Inorder(T->lchild);
printf("%c-->",T->data);
Inorder(T->rchild);
}
}
/********************************/
/* 后序遍历二叉树 */
/********************************/
void Postorder(BinTree T)
{
if(T==NULL)return ;
else
{
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c-->",T->data);
}
}
/************************************************/
/* 采用后序遍历求二叉树的深度、结点数及叶子数 */
/************************************************/
//要求采用递归算法
int TreeDepth(BinTree T)
{
int h1,h2;
if(T==NULL)return 0;
else
{
h1=TreeDepth(T->lchild);//后序遍历,先求左右子树的深度
h2=TreeDepth(T->rchild);
if(h1>h2)//进行比较,树的深度是左右子树深度的最大值加1
{
h1+=1;
}
else
{
h2+=1;
}
}
}
/**************************************************/
/* 利用"先进先出"(FIFO)队列,按层次遍历二叉树 */
/**************************************************/
/*队列的front指向第一个数据,rear指向最后一个数据的
后一位。队列最大长度为100*/
/*思路:将根节点放入队伍,再从队伍取出,读出结点的数
据,将左右子树的结点排入队伍,实现一层一层,从上至下,
从左到右遍历二叉树的目的
*/
void Levelorder(BinTree T)
{
BinTree temp;
SqQueue Q;
Q.rear=Q.front=0;//建立一个空队伍
if(T)
{
Q.base[Q.rear]=T;
Q.rear=(Q.rear+1)%100;//入队操作,循环链表的长度是100
while(Q.rear!=Q.front)
{
temp=Q.base[Q.front];
printf("%c-->",temp->data);
Q.front=(Q.front+1)%100;//出队操作
if(temp->lchild)
{
Q.base[Q.rear]=temp->lchild;
Q.rear=(Q.rear+1)%100;//左子树进入队伍
}
if(temp->rchild)
{
Q.base[Q.rear]=temp->rchild;
Q.rear=(Q.rear+1)%100;//右子树进入队伍
}
}
}
}
/********************************/
/* 数叶子节点个数 */
/********************************/
int countleaf(BinTree T)
{
if(T==NULL){return 0;}
if(T->lchild==NULL&&T->rchild==NULL)//判断是否是叶子结点,是的话返回1
{
return 1;
}
else
//不是叶子的结点的话继续向下层查找叶子结点,并将左右子树的叶子结点相加
{
return countleaf(T->lchild)+countleaf(T->rchild);
}
}
/********************************/
/* 数总的节点个数 */
/********************************/
int NodeCount(BinTree T)
{
if(T==NULL)return 0;
else
return NodeCount(T->lchild)+NodeCount(T->rchild)+1;//记得+1,加上根节点
}