实 验 报 告
实验题目:
1. 建立二叉树(按先序遍历的顺序输入结点值)。
2. 分别用先、中、后序遍历输出二叉树。
3. 建立中序线索二叉树,并建立头指针,从该指针出发对线索二叉树扫描。
一、需求分析
1. 提示输入信息,用户在键盘上按先序依次输入二叉树的结点值,以空格为分隔符,以-1代表空,直至输完整个二叉树。
2. 执行的命令包括:
1)按先序建立二叉树2)先中后序遍历 3)中序线索化二叉树4)中序扫描线索二叉树
3. 测试数据:
输入数据:1,2,4,-1,-1,5,-1,-1,3,6,-1,-1,7,-1,-1
所建立二叉树为:
1
2 3
4 5 6 7
输出结果:先序:1,2,4,5,3,6,7
中序:4,2,5,1,6,3,7
后序:4,5,2,6,7,3,1
二、概要设计
抽象数据类型二叉树的定义如下:
ADT BinaryTree{
数据对象D:D是具有相同特性的数据元素集合。
数据关系R:如D=Ф,则R=Ф,称BinaryTree为空二叉树;
如D≠Ф,则R={H},H是如下二元关系:
(1) 在D中存在唯一的称为根的数据元素root,它在关系H下无前驱;
(2) 如D-{root}≠Ф,则存在D-{root}={D1,Dr},且D1∩Dr=Ф;
(3) 如D1≠Ф,则D1中存在唯一元素x1, < SPAN> 1 >∈H, 且存在D 1 上的关系H 1 ∈H;如D r ≠Ф,则D r 中存在唯一的元素x r , < SPAN> r>∈H,且存在Dr上的关系Hr包含于H;H={ < SPAN> 1>, < SPAN> r >,H 1 ,H r } ;
(4) (D1,{H1})是一棵符合本定义的二叉树,称为根的右子树。
基本操作 P:
InitBiTree(&T);
操作结果:构造空二叉树T.
DestroyBiTree(&T);
初始条件:二叉树T存在。
操作结果:销毁二叉树T.
CreateBiThrTree(&T);
操作结果:先序构造二叉树T,Ltag和RTag初始置为Link.
PreOrderTraverse(T );
初始条件:二叉树T存在。
操作结果:先序递归遍历T。
InOrderTraverse(T);
初始条件:二叉树T存在。
操作结果:中序递归遍历T。
PostOrderTraverse(T);
初始条件:二叉树T存在。
操作结果:后序递归遍历T。
InOrderThreading(&ThrT, T);
初始条件:二叉树T存在。
操作结果:建立头结点ThrT,并调用InThreading(T);函数。
InThreading(T);
初始条件:二叉树T存在。
操作结果:中序线索化二叉树T;
InOrderTrasverse_Thr(T);
初始条件:二叉树T存在。
操作结果:中序扫描线索化的二叉树。
}ADT BinaryTree
三.具体算法实现:
/*二叉树的操作*/
#include
#include
/*
//***********************二叉树的顺序存储表示**************************
typedef struct BiTNode{
int data;
BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
*/
//********************二叉树的二叉线索化存储表示***********************
typedef enum PointerTag{Link,Thread};
typedef struct BiThrNode{
int data;
BiThrNode *lchild,*rchild;
PointerTag LTag,RTag;
}BiThrNode,*BiThrTree;
//**************************函数原型说明*******************************
void CreateBiTree(BiThrTree &T);
void PreOrderTraverse(BiThrTree T);
void InOrderTraverse(BiThrTree T);
void PostOrderTraverse(BiThrTree T);
void LevelOrderTraverse(BiThrTree T);
void InOrderThreading(BiThrTree T,BiThrTree &Thrt);
void InThreading(BiThrTree p);
void InOrderTrasverse_Thr(BiThrTree t);
BiThrTree pre; //使pre始终指向p的前驱,定为全局指针
//***************************函数体部分********************************
void CreateBiTree(BiThrTree &T){//建立二叉树
int d;
cin>>d;
if(d==-1){
T=NULL;//出错处
return;
}
T=new BiThrNode;
T->data=d;
T->LTag=Link;
T->Rtag=Link;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
return;
}
//**************************递归算法遍历*****************
void PreOrderTraverse(BiThrTree T){//先序遍历二叉树
if(T!=NULL){
cout< data<<' ';
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BiThrTree T){//中序遍历二叉树
if(T!=NULL){
InOrderTraverse(T->lchild);
cout< data<<' ';
InOrderTraverse(T->rchild);
}
}
void PostOrderTraverse(BiThrTree T){//后序遍历二叉树
if(T!=NULL){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout< data<<' ';
}
}
void InOrderThreading(BiThrTree T,BiThrTree &Thrt){//建立头结点并调用InThreading(T)函数
Thrt=new BiThrNode;//建立头结点
if(!T)return;
Thrt->LTag=Link;
Thrt->RTag=Thread;
Thrt->rchild=Thrt;//右指针回指
if(!T)Thrt->lchild=Thrt;//如是空树则左指针回指
else{
Thrt->lchild=T;//左指针指向T
pre=Thrt;//pre可设置成全局变量,始终是工作指针的前驱
InThreading(T);//中序线索化树T
pre->rchild=Thrt;//最后一个结点的右指针指向头结点
pre->RTag=Thread;
Thrt->rchild=pre;//头结点的右指针指向最后一个结点
}
}
void InThreading(BiThrTree p){//中序线索化
if(p)
{
InThreading(p->lchild);//中序线索化左子树
if(!p->lchild)
{//前驱线索
p->LTag=Thread;
p->lchild=pre;
}
if(!pre->rchild)
{//后继线索
pre->RTag=Thread;
pre->rchild=p;
}
pre=p;//保持pre指向p的前驱
InThreading(p->rchild);//线索化右子树
}
}
void InOrderTrasverse_Thr(BiThrTree T){//中序扫描线索二叉树
if(!T)return;
BiThrTree p=T->lchild;//p先指向头结点的左指针,即根
while(p!=T){
while(p->LTag==Link)//找中序第一个结点
p=p->lchild;
cout< data<<' ';
while(p->RTag==Thread&&p->rchild!=T)
{//顺着后继扫描
p=p->rchild;
cout< data<<' ';
}
p=p->rchild;//扫描右子树
}
}
void main()//主程序,完成函数的调用
{
BiThrTree T,ThrT;
CreateBiTree(T);
cout<<"先序遍历:";
PreOrderTraverse(T);
cout< < SPAN>
cout<<"中序遍历:";
InOrderTraverse(T);
cout< < SPAN>
cout<<"后序遍历:";
PostOrderTraverse(T);
cout< < SPAN>
InOrderThreading(T,ThrT);
cout<<"输出线索化树:";
InOrderTrasverse_Thr(T);
cout< < SPAN>
}
四.调试分析:
1. 在线索化二叉树时,如象书上把二叉树和线索二叉树的存储结构分开,则二叉树中的数据域不能传递到线索二叉树中(两个类型的指针不能互相赋值)。比较两种存储结构发现,线索二叉树比二叉树多了两个标志域LTag,Rtag。于是把两种存储结构合并为BiThrNode,并在建立二叉树时把LTag,Rtag均置为Link。修改后程序正常。
2. 本次实验报告所用的算法,书中均有具体算法演示,且易实现,除存储结构外没有大问题。