二叉树

     

实验题目:

1.         建立二叉树(按先序遍历的顺序输入结点值)。

2.         分别用先、中、后序遍历输出二叉树。

3.         建立中序线索二叉树,并建立头指针,从该指针出发对线索二叉树扫描。

一、需求分析

1.         提示输入信息,用户在键盘上按先序依次输入二叉树的结点值,以空格为分隔符,以-1代表空,直至输完整个二叉树。

2.         执行的命令包括:

1)按先序建立二叉树2)先中后序遍历       3)中序线索化二叉树4)中序扫描线索二叉树

3.         测试数据:

输入数据:124-1-15-1-136-1-17-1-1

所建立二叉树为:

1

2               3

4   5    6   7

输出结果:先序:1245367

          中序:4251637

          后序:4526731

二、概要设计

抽象数据类型二叉树的定义如下:

ADT BinaryTree{

 数据对象DD是具有相同特性的数据元素集合。

 数据关系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包含于HH={ < SPAN> 1>, < SPAN> r >,H 1 ,H r }

(4)       (D1,{H1})是一棵符合本定义的二叉树,称为根的右子树。

基本操作 P

                     InitBiTree(&T);

                            操作结果:构造空二叉树T.

                     DestroyBiTree(&T);

                            初始条件:二叉树T存在。

                            操作结果:销毁二叉树T.

                     CreateBiThrTree(&T);

                            操作结果:先序构造二叉树T,LtagRTag初始置为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.  本次实验报告所用的算法,书中均有具体算法演示,且易实现,除存储结构外没有大问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值