数据结构二叉树实验报告
数据结构实习题目二
二叉树及其操作
尹星晨 (0806230331)
一、问题描述
利用先序建立一棵二叉树,数据以字符串形式从键盘输入。在此二叉树上完成如下操作:
必做:
(1)实现二叉树的前序、中序、后序遍历。
(2)求出二叉树叶子结点的数目。
(3)求二叉树的树高。
(4)完成二叉树的左右子树交换,输出交换后的前序、中序遍历序列。
选做:
(1)给出二叉树的非递归后序遍历。
(2)将二叉树扩充为中序线索树,写出非递归的中序遍历。
(3)已知在两个数组中分别有前序和中序遍历序列,试建立该二叉树。
二、算法描述
1、整体思路:
S1: 建立二叉树;
S2: 递归遍历该二叉树;
S3: 二叉树的相关操作;
S4: 非递归后续遍历;
S5: 中序线索化及输出;
S6: 由数组中的序列建立二叉树且输出;
2、细节描述:
1)先序创建二叉树
默认为键盘输入,当输入‘ # ’时,输入结束;当输入‘ @’时当前结点为空;当输入其他字符时,该字符保存入当前结点的数据域。
void Create_BinTree(BinTree *T)
{
char ch;cin>>ch;//从键盘接收输入字符
if(ch=='#')return;//当输入为#时,输入结束
else{//否则继续
if(ch=='@') *T=NULL;//当输入为@时,当前结点为空
else{//否则保存该结点
*T=(BinTree)malloc(sizeof(BinTreeNode));//为当前结点申请空间
(*T)->data=ch;//键盘接收的字符保存入数据域
Create_BinTree(&(*T)->lchild);//递归方法创建左孩子结点
Create_BinTree(&(*T)->rchild); //递归方法创建右孩子结点
}}}//创建结束
2)递归方法遍历二叉树
以下涉及的遍历方法均采用递归遍历,非递归的先序,中序,后序遍历将在第四小节中涉及。
void NR_PreOrder(BinTree T)void NR_InOrder(BinTree T)void NR_PostOrder(BinTree T) {// 非递归方法的先序遍历{// 非递归方法的中序遍历{// 非递归方法的后序遍历if(T){// 若 T 树非空则遍历if(T){if(T){
cout<
NR_PreOrder(T->lchild);//递归cout<
NR_PreOrder(T->rchild);//递归NR_InOrder(T->rchild);cout<
}}}}}}
3)二叉树相关操作
这里涉及的关于二叉树的相关操作的方法均采用递归法
a)计算二叉树叶子结点数目
int LeafNum(BinTree T)
{//计算二叉树 T 叶子结点数
if(T){//若树 T 非空则开始计算
int m=LeafNum(T->lchild);//递归计算以左孩子结点为根的叶子数
int n=LeafNum(T->rchild);;//递归计算以右孩子结点为根的叶子数
if(m+n==0) return 1;//只有根结点
else return m+n;//返回左右孩子的叶子总数
}else return 0;//树空返回 0
}
b)求二叉树树高
int Height(BinTree T)
{//求二叉树 T 的高度
if(T==NULL)return 0;//若树空,高度为 0
else{
int lheight=Height(T->lchild);//递归法求以左孩子为根的树的高度
int rheight=Height(T->rchild);//递归法求以右孩子为根的树的高度
return 1+(lheight>rheight ? lheight : rheight);//返回最大值为树的高度}}
c)二叉树左右子树交换
void exchange(BinTree T)
{//二叉树左右子树交换
if(T->lchild==NULL && T->rchild==NULL) return;//若一边为空则无法交换
else{
BinTreeNode * temp=NULL;//
定义临时结点辅助交换
temp=T->lchild;
T->lchild=T->rchild;
交换左右结点
T->rchild=temp;
}
if(T->lchild) exchange(T->lchild);//递归交换左孩子
if(T->rchild) exchange(T->rchild);//递归交换右孩子
}
4)非递归后序遍历
采用栈辅助实现非递归后序遍历
void PostOrder( BinTree T)
{//非递归后序遍历
stack
BinTreeNode *cur = T,*visited = NULL;
while( ! s.empty() || cur != NULL ){
while( cur != NULL ){
s.push( cur );
cur = cur->lchild;
}
cur = s.top();
if( cur->rchild == visited || cur->rchild == NULL ){
cout<
s.pop();
visited = cur;
cur = NULL;
}
else cur = cur->rchild;
}}
5)中序线索化
typedef struct BinThrNode{
char data;
struct BinThrNode * lchild, * rchild;
int ltag,rtag;
}BinThrNode,*BinThrTree;
BinThrTree pre;
void Creat_BinThrTree(BinTree * T,BinThrTree * p)
{
if(T){
*p=(BinThrTree)malloc(sizeof(BinThrNode));
(*p)->data=(*T)->data;
Creat_BinThrTree(&(*T)->lchild,p);
Creat_BinThrTree(&(*T)->rchild,p);
}}
void Inthread(BinThrTree p)
{//中序线索化二叉树
if(p){
Inthread(p->lchild);
if(p->lchild) p->ltag=0;
else p->ltag=1;
if(p->rchild) p->rtag=0;
else p->rtag=1;
if(pre){
if(pre->rtag==1)pre->rchild=p;
if(p->ltag==1)p->lchild=pre;
}
pre=p;
Inthread(p->rchild);
}}
BinThrTree insucc(BinThrTree p)
{//寻找p结点的后继
if(p->rtag==1)return p->rchild;
else{
p=p->rchild;
while(p->ltag==0){
p=p->lchild;
return p;
}}}
void T_InOrder(BinThrTree T)
{//中序遍历线索化后的二叉树
BinThrTree p=T;
if(p){
while(p->ltag==0) p=p->lchild;
do{
cout<
p=insucc(p);
}while(p);
}}
6)由数组中已有的前序。中序序列建立二叉树
void set(BinTreeNode *&p,char pre[],char in[],int p1,int q1,int p2,int q2)
{//p1,q1,p2,q2分别为数组前序,中序的边界
p=new BinTreeNode;
p->data=pre[p1];
// 建立根结点 , 输入数值
int t=p2;
while(in[t]!=pre[p1]) t++;// 中序数组后移
if(t==p2) p->lchild=NULL; //无左子树
else set(p->lchild,pre,in,p1+1,p1+t-p2,p2,t-1);// 递归
if(t==q2) p->rchild=NULL; //无右子树
else set(p->rchild,pre,in,p1+t-p2+1,q1,t+1,q2);// 递归}
三、程序结构
1 、数据结构;
typedef struct BinTreeNode{
ElemType data;//数据区
struct BinTreeNode *lchild,*rchild;//左右孩子结点}BinTreeNode,*BinTree;
typedef struct BinThrNode{//中序线索化时定义的结点
char data; //数据区
struct BinThrNode * lchild, * rchild; //左右孩子结点
int ltag,rtag;//标志
}BinThrNode,*BinThrTree;
2 、函数调用结构:
3、函数功能说明:
功能区函数名功能描述创建二叉树Create_BinTree()创建二叉树(采用先序建立二叉树)
Traversal()递归遍历二叉树
NR_PreOrder()递归遍历二叉树 _ 先序
遍历
NR_InOrder()递归遍历二叉树 _ 中序
NR_PostOrder()递归遍历二叉树 _ 后序
Operation()二叉树基本操作
LeafNum()计算二叉树叶子结点数目操作
Height()计算二叉树的树高
Exchang()e交换二叉树左右子树
非递归R_PostOrder()非递归遍历二叉树 _ 后序
Creat_BinThrTree()创建修改后的含有标记的二叉树
Inthread()中序线索化
中序线索化
Insucc()寻找当前结点的后继结点
T_InOrder()非递归遍历二叉树 _ 中序
由数组创建TrFrArray()由数组创建二叉树
四、测试结果与分析
测试结果