1、 此时,你应当输入:(表示回车确认) ABE F C DGHI J K 提示:为方便确认输入了几个空格,用星号*表示输入序列中的空格,则序列如下 ABE*F*C*DGHI*J*K*(不是真实的输入序列,供计算需输入空格个数时用) 这时,建好的树的先根和后根次序序列如下: 树的先根序列 A B E F C D G H I J K 树的后根序列 E F B C I J K H G D A 由树和二叉树的转换关系知,二叉树的先序和中序遍历所得序列分别与树的先根和后根遍历所得序列相同,据此验证转化是否正确。二叉树的先序和中序遍历序列如下: 二叉树先序序列 A B E F C D G H I J K 二
2、叉树中序序列 E F B C I J K H G D A2、概要设计为了实现上述程序功能,树采用孩子兄弟表示法,二叉树采用二叉链表表示法。为此,需要两个抽象数据类型,树和二叉树的抽象数据类型。1.树的抽象数据类型定义ADT Tree数据对象D:D是具有相同特性的数据元素的集合。 数据关系R:若D为空集,则称为空树;若D仅含有一个数据元素,则R为空集,否则R=H,H是如下二元关系: (1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱; (2)若D-root,则存在D-root的一个划分D1,D2,D3,Dm(m0), 对于任意jk(1j,km)有DjDk=,且对任意的i(1im)
3、, 唯一存在数据元素xiDi有H; (3)对应于D-root的划分,H-,有唯一的一个划分 H1,H2,Hm(m0),对任意jk(1j,km)有HjHk=,且对任意i (1im),Hi是Di上的二元关系,(Di,Hi)是一棵符合本定义的树, 称为根root的子树。基本操作P: InitTree(&T); 操作结果:构造空树T。 DestroyTree(& 初始条件:树T存在。销毁树T。 CreateTree(&T,definition);definition给出树T的定义。按definition构造树T。 ClearTree(&将树T清为空树。 TreeEmpty(T);若T为空树,则返回TR
4、UE,否则返回FALSE。 TreeDepth(T);返回的深度。 Root(T);返回T的根。 Value(T,cur_e);树T存在,cur_e是T中某个结点。返回cur_e的值。 Assign(T,cur_e,value);结点cur_e赋值为value。 Parent(T,cur_e);若cur_e是T的非根结点,则返回它的双亲,否则函数值为“空”。 LeftChild(T,cur_e);若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回“空”。 RightSibling(T,cur_e);若cur_e有右兄弟,则返回它的右兄弟,否则返回“空”。 InsertChild(&T,
5、&p,I,c);树存在,指向中某个结点,1ip指结点的度,非空树与不相交。插入c为中指结点的第棵子树。 DeleteChild(&p,i);树T存在,p指向T中某个结点,1ip指结点的度。删除中所指结点的第棵子树。 TraverseTree(T,visit();树T存在,visit是对结点操作的应用函数。按某种次序对T的每个结点调用函数visit( )一次且至多一次。一旦visit( )失败,则操作失败。ADTTree2.二叉树的抽象数据类型定义ADT BinaryTree 数据对象D: 若D=,则R=,称BinaryTree为空二叉树; 若D,则R=H,H是如下二元关系; (1)在D中存在惟
6、一的称为根的数据元素root,它在关系H下无前驱; (2)若D-root,则存在D-root=D1,Dr,且D1Dr =; (3)若D1,则D1中存在惟一的元素x1,H,且存在D1上的关系H1 H;若Dr,则Dr中存在惟一的元素xr,H,且存在上的关系Hr H;H=,data=ch; /生成根结点 CreateCSTree(CT-firstchild); /构建左子树 nextsibling); /构建右子树 /else return OK;/CreateCSTree3.转换为二叉树 树和二叉树的转换关键在于树的二叉链表与其对应的二叉树的二叉链表是相同的,只是对同一个二叉链表的解释不同,二叉树
7、的数据域存放结点名称,左指针域指向左孩子,右指针域指向右孩子;树的数据域存放结点名称,左指针域指向孩子结点,右指针域指向与该结点相邻的一个兄弟结点。当两者具有相同的存储结构时,便可以完成转换,转换过程的实质是按照二叉树的定义将二叉链表解释为二叉树的过程。Status ExchangeToBiTree(CSTree &CT,BiTree &T) /将一棵用二叉链表表示的树递归地转换为二叉树 if(!CT) /树CT为空时,二叉树T为空 T=NULL; else /若树的对应结点不空,申请内存空间(T=(BiNode *)malloc(sizeof(BiNode) /将树的数据域复制到二叉树对应的
8、数据域 T-data=CT-data; /若树的孩子域不为空,则用树的孩子域创建二叉树的左子树 ExchangeToBiTree(CT-firstchild,T-lchild); /若树的兄弟域不为空,则用树的兄弟域创建二叉树的右子树 nextsibling,T-rchild);/ExchangeToBiTree4.二叉树的遍历二叉树有先序、中序、后序、层序四种遍历方式,而先序、中序、后序遍历又有递归和非递归两种算法,总共有7个遍历算法。其中,先序、中序、后序非递归遍历算法需要用到栈,层序遍历需要使用队列,队列和栈的相关定义和算法请参考详细设计P21。二叉树先序、中序、后序遍历的区别仅在于访问
9、根结点的时机不同,而层序遍历则是逐层从左到右访问每一个结点。先序遍历二叉树算法的框架是: 若二叉树为空,则空操作; 否则 访问根结点 (D); 先序遍历左子树 (L); 先序遍历右子树 (R)。中序遍历二叉树算法的框架是: 否则 中序遍历左子树 (L); 访问根结点 (D); 中序遍历右子树 (R)。后序遍历二叉树算法的框架是: 否则 后序遍历左子树 (L); 后序遍历右子树 (R); 访问根结点 (D)。虽然访问根结点的时机不同,但是先左后右的规则并没有改变。所有的遍历函数都调用元素访问函数Visit,他们的参数列表中均含有一个函数指针变量Status(* Visit)(TElemType)
10、,通过主函数向他们传递元素访问函数Visit的函数名,就可以实现按元素访问函数Visit设定格式输出的目的。这样的好处在于当输出格式改变时,只需修改元素访问函数Visit的输出格式而无需更改7个遍历函数,做到一改全改。以下是所有遍历算法的实现以及元素访问函数Visit:/-元素访问函数Visit- Status PrintElement(TElemType e) /输出元素e的值 printf( %c ,e); /元素类型设定为字符型/PrintElement/-递归算法- Status PreOrderTraverse(BiTree T,Status(* Visit)(TElemType)
11、/先序遍历递归算法 /采用二叉链表存储结构,Visit是对数据元素操作的应用函数 /先序遍历二叉树T的递归算法,对每个数据元素调用函数Visit if(T) if(Visit(T-data) /访问根结点 if(PreOrderTraverse(T-lchild,Visit) /访问左子树rchild,Visit) /访问右子树 return ERROR; /if else return OK;/PreOrderTraverseStatus InOrderTraverse(BiTree T,Status(* Visit)(TElemType) /中序遍历递归算法 /中序遍历二叉树T的递归算法,
12、对每个数据元素调用函数Visit if(T) if(InOrderTraverse(T- if(Visit(T- if(InOrderTraverse(T-/InOrderTraverse Status PostOrderTraverse(BiTree T,Status(* Visit)(TElemType) /后序遍历递归算法 /后序遍历二叉树T的递归算法,对每个数据元素调用函数Visit if(PostOrderTraverse(T- if(PostOrderTraverse(T-data) /访问根结点 /if/PostOrderTraverse/-非递归遍历算法-Status PreO
13、rderTraverse1(BiTree T,Status(* Visit)(TElemType) /先序遍历非递归算法 /先序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit Stack S; InitStack(S); /初始化栈 BiTree p=T; /设置工作指针p并对其赋初值 while(p|!(StackEmpty(S) if(p) if(!Visit(p- return ERROR; Push(S,p); /根指针进栈 p=p-lchild; /遍历左子树 else Pop(S,p); /根指针退栈 rchild; /遍历右子树 /else /while /PreOrderTraverse1Status InOrderTraverse1(BiTree T,Status(* Visit)(TElemType) /中序遍历非递归算法 /中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit /InOrderTraverse1Status PostOrderTraverse1(BiTree T,Status(* Visit)(TElemType) /后序遍历非递归算法 /后序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit BiTree p=T, q=NULL; /
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1