先序线索化

合集下载

计算机专业基础综合数据结构(树和二叉树)历年真题试卷汇编6

计算机专业基础综合数据结构(树和二叉树)历年真题试卷汇编6

计算机专业基础综合数据结构(树和二叉树)历年真题试卷汇编6(总分:88.00,做题时间:90分钟)一、单项选择题(总题数:33,分数:66.00)1.一棵完全二叉树又是一棵( )。

【华中科技大学2006一、7(2分)】A.平衡二叉树B.堆√C.二叉排序树D.哈夫曼(Huffman)树完全二叉树的叶子至多在下面两层上,且一个结点若无左子树,绝不能有右子树。

平衡二叉树任何结点的左右子树的高度差的绝对值不超过1,但其结点的值符合二叉排序树的定义。

平衡二叉树(包括二叉排序树)的树形不一定是完全二叉树。

堆是一个序列,有大堆和小堆,编号为i的结点,其父结点、左右子女结点之间位置的关系,符合完全二叉树父结点、左右子女结点之间的关系,从这点上说,可以把堆看成完全二叉树。

哈夫曼树是二叉树,但树形不一定满足完全二叉树的定义。

2.一棵左子树为空的二叉树在先序线索化后,其中空的链域的个数是( )。

【合肥工业大学1999一、5(2分)】A.不确定B.0C.1D.2 √左子树为空的二叉树的根结点的左线索为空(无前驱),先序序列的最后结点的右线索为空(无后继),共2个空链域。

3.一棵左右子树均不空的二叉树在先序线索化后,其中空的链域的个数是( )。

【合肥工业大学2000一、5(2分)】A.0B.1 √C.2D.不确定4.若X是二叉中序线索树中一个有左孩子的结点,且X不为根,则X的前驱为( )。

【南京理工大学1996一、6(2分)】A.X的双亲B.X的右子树中最左的结点C.X的左子树中最右结点√D.X的左子树中最右叶结点5.引入二叉线索树的目的是( )。

【南京理工大学1998一、5(2分)】A.加快查找结点的前驱或后继的速度√B.为了能在二叉树中方便地进行插入与删除C.为了能方便地找到双亲D.使二叉树的遍历结果唯一6.线素二叉树是一种( )结构。

【西安电子科技大学1996一、9(2分)】A.逻辑B.逻辑和存储C.物理√D.线性7.甩个结点的线索二叉树上含有的线索数为( )。

8哈夫曼树

8哈夫曼树
a
b d e c
2 3 4 5 6 7 b c d e
d
e f g f g h
f
g
h
8
h
25
3、用孩子兄弟表示法来存储
思路:用二叉链表来表示树,但链表中的两个 指针域含义不同。 左指针指向该结点的第一个孩子; 右指针指向该结点的下一个兄弟结点。
firstchild data nextsibling
100
40
21 32 g e 17 7 a
60
28 11 10 h 6 d 2 c 5 3 f
10
对应的哈夫曼编码(左0右1):
符 编码 频率 符 编码 频率
100
a
b
1100
00
0.07
0.19
a
b
000
001
0.07
0.19 0.06
0 b
0 40
1
1
0 60 1 28 1 0 6 d 0 2 c 11 1d Path Length
树的带权路径长度如何计算? WPL = 哈夫曼树则是:WPL 最小的树。
w kl k
k=1
n
经典之例:
4 d
2 c 7 a (b) 5 b
Huffman树
7 a
7 a
5
2 b c
4 d
5 b
2 c (c)
4 d
(a)
WPL=36
WPL=46
WPL= 35
3
构造霍夫曼树的基本思想: 权值大的结点用短路径,权值小的结点用长路径。 构造Huffman树的步骤(即Huffman算法):
(1) 由给定的 n 个权值{w0, w1, w2, …, wn-1},构造具有 n 棵扩充 二叉树的森林F = { T0, T1, T2, …, Tn-1 },其中每一棵扩充二叉树 Ti 只有一个带有权值 wi 的根结点,其左、右子树均为空。 (2) 重复以下步骤, 直到 F 中仅剩下一棵树为止: ① 在 F 中选取两棵根结点的权值最小的扩充二叉树, 做为左、 右子树构造一棵新的二叉树。置新的二叉树的根结点的权值为 其左、右子树上根结点的权值之和。 ② 在 F 中删去这两棵二叉树。 ③ 把新的二叉树加入 F。

先序线索化转圈问题

先序线索化转圈问题

先序线索化转圈问题先序线索化转圈问题是一种经典的数学问题,它可以帮助我们探索数学中的先序遍历、线索化和环的概念。

让我们来了解一下先序遍历和线索化的含义。

我们将研究如何将这些概念应用到转圈问题上,并通过一些具体的例子来进一步理解。

1. 先序遍历在二叉树中,先序遍历是指先访问根节点,然后遍历左子树,最后遍历右子树。

这个遍历顺序可以用一个节点序列来表示,我们可以把先序遍历的结果存储在一个数组中。

在这个数组中,根节点的位置总是在左子树和右子树之前。

2. 线索化线索化是将二叉树中的空指针调整为指向前驱节点或后继节点的方式。

通过线索化,我们可以用指针在树中前进而不需要使用递归或栈。

对于一个二叉树的节点,如果它没有左子树,我们可以把它的左指针指向它的前驱节点;如果它没有右子树,我们可以把它的右指针指向它的后继节点。

3. 先序线索化转圈问题现在让我们来考虑一个有趣的问题:如何将一棵已经线索化的二叉树转化为一个环形链表呢?我们需要把每一个节点的右指针指向它的后继节点,并使得最后一个节点的后继节点指向第一个节点。

为了解决这个问题,我们可以使用先序遍历的思想。

我们可以从根节点开始,依次遍历每个节点,并将它的右指针指向它的后继节点。

我们还需要记录前一个访问的节点,以便将它的后继节点指向当前节点。

具体的步骤如下:- 如果当前节点为根节点,将它的右指针指向它的后继节点,并记录当前节点为前一个节点。

- 如果当前节点有左子树,递归处理左子树。

- 如果当前节点有右子树,继续遍历它的右子树。

通过这种方式,我们可以将一个已经线索化的二叉树转化为一个环形链表。

这个环形链表可以让我们在任意节点中,通过右指针循环遍历所有节点。

在实际应用中,先序线索化转圈问题可以用于优化二叉树的遍历算法。

由于线索化的特性,我们可以避免使用递归或栈,从而提高遍历的效率。

通过对先序线索化转圈问题的深入研究,我们可以更好地理解先序遍历、线索化和环的概念。

这个问题不仅提供了一个数学的挑战,还具有一定的实际应用价值。

数据结构(Java版)_郑州大学中国大学mooc课后章节答案期末考试题库2023年

数据结构(Java版)_郑州大学中国大学mooc课后章节答案期末考试题库2023年

数据结构(Java版)_郑州大学中国大学mooc课后章节答案期末考试题库2023年1.对不含相同元素的同一输入序列进行两组不同的、合法的入栈和出栈组合操作,所得的输出序列一定相同。

参考答案:错误2.在链队列中,即使不设置尾指针,也能进行入队操作。

参考答案:正确3.循环顺序队列和循环链队列都存在空间一处问题。

参考答案:错误4.直接选择排序的时间复杂度与关键字的初始排列无关。

参考答案:正确5.一个循环链表可以由给定的头指针或尾指针来唯一标识。

参考答案:正确6.所谓随机存取,就是通过首地址和元素的序号可以在O(1)的时间内找到指定的元素。

参考答案:正确7.快速排序在最坏情况下的时间复杂度是O(【图片】)。

参考答案:正确8.哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近()参考答案:正确9.在队列中存取数据元素的原则是()。

参考答案:先进先出10.将整数1、2、3、4依次进栈,则不可能得到的出栈序列是()。

参考答案:142311.完全二叉树的存储结构通常采用顺序存储结构()。

参考答案:正确12.在中序线索二叉树中,每一非空的线索均指向其祖先结点()参考答案:正确13.二叉树中序线索化后,不存在空指针域()参考答案:错误14.二叉树的层次遍历需要栈结构的支持。

参考答案:错误15.下列关于AOE网的叙述中,不正确的是()参考答案:任何一个关键活动提前完成,那么整个工程将会提前完成16.一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足()参考答案:只有一个叶子结点17.引入二叉线索树的目的是()参考答案:加快查找结点的前驱或后继的速度18.单源最短路径算法的时间复杂度为()参考答案:O()19.对6个不同的数据元素进行直接插入排序,最多需要进行()次关键字的比较。

参考答案:1520.完全二叉树中,若一个结点没有左孩子,则它必是树叶()。

参考答案:正确21.已知循环队列存储在一维数组A[0【图片】n]中,且队列非空时front和rear分别指向队首元素和队尾元素。

《数据结构》精品课程题库

《数据结构》精品课程题库
A.BT[i/2] B.BT[2*i-1]
B.BT[2*i] D.BT[2*i+1]
13. 由同一关键字集合构造的各棵二叉排序树( )
A. 其形态不一定相同,但平均查找长度相同
B. 其形态不一定相同,平均查找长度也不一定相同
C. 其形态均相同,但平均查找长度不一定相同
C.三叉链表 D.顺序存储结构
28. 对一个满二叉树,M个树叶,N个结点,深度为H,则( )
A.N=H+M B.H+M=2H
C.M=H-1 D.N=2*eh-1
29. 如果某二叉树的前序为stuwv,中序为uwtvs,那么该二叉树的后序中( )
A. LL B. LR
C. RL D. RR
6. 一棵含18个结点的二叉树的高度至少为( )
A.3 B.4
C.5 D.6
7. 已知二叉树的先序序列为ABDECF,中序序列为DBEAFC,则后序序列为( )
A.DEBAFC B.DEFBCA
A.只有右子树上的所有结点 B.只有右子树上的部分结点
C.只有左子树上的所有结点 D.只有左子树上的部分结点
25. 树最适合用来表示( )
A.有序数据元素 B.无序数据元素
C.元素之间具有分层次关系的数据 D.元素之间无联系的数据
A.N在M右方 B.N是M祖先
C.N在M左方 D.N是M子孙
32. 线索二叉树是一种__结构( )
A.逻辑 B.逻辑和存储
C.物理 D.线性
33. l 将一棵有 100个结点的完全二叉树,从根这一层开始,每一层从左到右依次对结点编号,根据点的 编号为1,则编号为49的结点的双亲的编号为 ( )

实验8 线索二叉树的创建和遍历

实验8 线索二叉树的创建和遍历

实验八线索二叉树的创建和遍历1.实验目的(1)掌握二叉树的线索链表存储结构。

(2)能够实现二叉树的线索链表的创建、遍历等基本操作。

2.实验内容编程实现二叉树的线索链表存储表示的基本操作,包括线索二叉树的创建与遍历。

3.实验要求(1)根据实验内容编写程序,上机调试并获得运行结果(2)撰写实验报告4.准备工作本次实验将会构造此二叉树,并会对此二叉树进行遍历5.关键步骤与算法(1)构造线索二叉树算法步骤;若某节点的左孩子节点指针域(lchild)为空,就可以利用它来指出该节点在某种遍历序列中的直接前驱的存储地址;若某节点的右孩子指针域(rchild)为空,就可以利用它来指出该节点在某种遍历序列中的直接后继的存储地址。

那些非空的指针域仍存放指向该节点左、右孩子节点的指针域。

这样,就得到了一棵线索二叉树。

算法如下;1.//按先序遍历序列输入树中各节点的值,构造线索二叉树2.BiThrTree* CreateBiThrTree()3.{4. BiThrTree *s;5. DataType ch;6. scanf("%c",&ch);7.8.if(ch == '#')9. exit(0);10.if(ch == '@')11. s = NULL;12.else if (ch=='\n')13. getchar();14.15.else16. {17. s = (BiThrTree *)malloc(sizeof(BiThrTree));18.if(!s)19. exit(ERROR);20. s->data = ch;21. s->lflag = 0;22. s->rflag = 0;23. s->lchild = CreateBiThrTree();24. s->rchild = CreateBiThrTree();25. }26.return s;27.}(2) 将二叉树中序线索化现将树递归到左子树然后再判断这个树的左右子树是否为空,如果为空则把它们的标志设为1,代表线索,首先设一个current代表前驱结点,然后判断它是否为空,如果为空则进行下一次递归,如果不为空,则判断左标志和右标志如果左标志为线索,则让前驱节点的右孩子指向当前节点,如果右标志为1,则让当前节点的左孩子指向前驱结点算法如下;1.void InThreading(BiThrTree *t)2.{3.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数4. {5. InThreading(t->lchild);//递归调用左子树进行线索化6.if(t->lchild == NULL)7. t->lflag = 1;8.if(t->rchild == NULL)9. t->rflag = 1;10.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上111.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL12. {13.if(current->rflag == 1)14. current->rchild = t;//前驱结点的右孩子指针指向当前节点t15.if(t->lflag == 1)16. t->lchild = current;//现结点t的左孩子指针指向前驱结点17. }18. current = t;//让前驱结点为t为下一次执行函数做准备19. InThreading(t->rchild);//递归调用右子树进行线索化20. }21.}6.源代码1.#include<malloc.h>2.#include<stdio.h>3.#include<stdlib.h>4.#include<io.h>5.#define ERROR -16.7.typedef char DataType;8.typedef struct BiThrNode//二叉树的二叉链表的存储结构9.{10. DataType data;11.struct BiThrNode *lchild,*rchild;12.int lflag,rflag;//左右标志,值为0表示指针,值为1表示线索13.}BiThrTree;14.BiThrTree *current = NULL;15.//检查if的==16.//按先序遍历序列输入树中各节点的值,构造线索二叉树17.BiThrTree* CreateBiThrTree()18.{19. BiThrTree *s;20. DataType ch;21. scanf("%c",&ch);22.23.if(ch == '#')24. exit(0);25.if(ch == '@')26. s = NULL;27.else if (ch=='\n')28. getchar();29.30.else31. {32. s = (BiThrTree *)malloc(sizeof(BiThrTree));33.if(!s)34. exit(ERROR);35. s->data = ch;36. s->lflag = 0;37. s->rflag = 0;38. s->lchild = CreateBiThrTree();39. s->rchild = CreateBiThrTree();40. }41.return s;42.}43.//将二叉树前序线索化(递归)44.void PreThreading(BiThrTree *t)45.{46.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数47. {48.if(t->lchild == NULL)49. t->lflag = 1;50.if(t->rchild == NULL)51. t->rflag = 1;52.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上153.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL54. {55.if(current->rflag == 1)56. current->rchild = t;//前驱结点的右孩子指针指向当前节点t57.if(t->lflag == 1)58. t->lchild = current;//现结点t的左孩子指针指向前驱结点59. }60. current = t;//让前驱结点为t为下一次执行函数做准备61.if(t->lflag == 0)62. PreThreading(t->lchild);//递归调用右子树进行线索化63.if(t->rflag == 0)64. PreThreading(t->rchild);65. }66.}67.//遍历前序线索二叉树68.void PreVisitThrtree(BiThrTree *t)69.{70.while(t != NULL)//大循环71. {72.while(t->lflag == 0)73. {74. printf("%c\t",t->data);75. t = t->lchild;76. }77. printf("%c\t",t->data);78. t = t->rchild;79. }80.}81.82.//检查if的==83.//将二叉树中序线索化(递归)84.void InThreading(BiThrTree *t)85.{86.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数87. {88. InThreading(t->lchild);//递归调用左子树进行线索化89.if(t->lchild == NULL)90. t->lflag = 1;91.if(t->rchild == NULL)92. t->rflag = 1;93.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上194.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL95. {96.if(current->rflag == 1)97. current->rchild = t;//前驱结点的右孩子指针指向当前节点t98.if(t->lflag == 1)99. t->lchild = current;//现结点t的左孩子指针指向前驱结点100. }101. current = t;//让前驱结点为t为下一次执行函数做准备102. InThreading(t->rchild);//递归调用右子树进行线索化103. }104.}105.//检查if的==106.//遍历中序线索二叉树107.void InVisitThrtree(BiThrTree *t)108.{109.while(t != NULL)//大循环110. {111.while(t->lflag == 0)//小循环1;此循环第一次进行时首先要去找到最左节点112. t = t->lchild;113.if(t == NULL)114. exit(ERROR);115. printf("%c\t",t->data);116.while(t->rflag == 1 && t->rchild != NULL)//小循环2117. {118. t = t->rchild;119. printf("%c\t",t->data);120. }121. t = t->rchild;122./*123.两种情况:124. 1.如果t的右子树为空则t直接指向t的中序后继结点.125. 2.如果t的右子树不为空,即t->rflag为0,那么退出这个小循环2回到大循环中,再到小循环1中去找t的右子树的最左下的结点.126. */127. }128.}129.130.//将二叉树后序线索化(递归)131.void PostThreading(BiThrTree *t)132.{133.if(t != NULL)//先判断树为不为空,如果为空,则不执行函数134. {135. PreThreading(t->lchild);136. PreThreading(t->rchild);137.if(t->lchild == NULL)138. t->lflag = 1;139.if(t->rchild == NULL)140. t->rflag = 1;141.//以上两步是判断这个结点的左右结点是否为空,若为空,把他们对应的flag标上1142.if(current != NULL)//因为要用到current所以要判断一下,且current只有当t回到倒数第二个结点时,才会不为NULL143. {144.if(current->rflag == 1)145. current->rchild = t;//前驱结点的右孩子指针指向当前节点t146.if(t->lflag == 1)147. t->lchild = current;//现结点t的左孩子指针指向前驱结点148. }149. current = t;//让前驱结点为t为下一次执行函数做准备150. }151.}152.//遍历后序线索二叉树153.void PostVisitThrtree(BiThrTree *t)154.{155.if(t)156. {157.while(t->lchild != NULL && t->lflag == 0)158. {159. t = t->lchild;//先遍历到最左边的节点160. }161. }162.}163.//主函数164.void main()165.{166. BiThrTree *t,*s;167. printf("\t\t请按先序序列输入二叉树(如:ABC@@DE@G@@F@@@#)\n\t\t");168. t = CreateBiThrTree();169. InThreading(t);170. printf("\t\t按中序遍历输出线索二叉树:\n\t\t");171. InVisitThrtree(t);172. printf("\n");173.//getchar();174.//getchar();175. fflush(stdin);//这个操作必须要进行,或者是进行上面注释的那两步操作,要不然176. printf("\t\t请按先序序列输入二叉树(如:ABC@@DE@G@@F@@@#)\n\t\t");177. s = CreateBiThrTree();178. PreThreading(s);179. printf("\t\t按前序遍历输出线索二叉树:\n\t\t");180. PreVisitThrtree(s);181.}7.测试图8.实验总结然对于这一节,主要是讨论线索二叉树的建立以及遍历,对于二叉树的建立,主要有五个部分构成,分别是data,lchild,rchild,lflag,rflag,而它与二叉树不同的地方就是多了lflag和rflag的判断,当当前节点的左节点为空时一定会指向它的前驱结点,当前驱节点的右节点为空时,让前驱结点的右指针域指向当前节点,这就是线索化,而对于前序中序后序的线索化本质都是一样的。

《数据结构》模拟试卷八

《数据结构》模拟试卷八

模拟试卷八一、选择题(每小题2分,共10分)1.一个栈的输入序列为12345,则下列序列中不可能是栈的输出序列的是。

(l)12345 (2)54321(3)23451 (4)412352.一棵左子树为空的二叉树在先序线索化后,其中的空链域的个数为。

(1)0 (2)1(3)2 (4)不确定3.在用邻接表表示图的情况下,拓扑排序算法的时间复杂度为。

(l) O(n+e)(2) O(n2)(3) O(n×e)(4) O(n3)4.下列排序算法中,在每一趟都能选出一个元素放到其最终位置上,并且其时间性能受数据初始特性影响的是。

(1)直接插入排序(2)快速排序(3)直接选择排序(4)堆排序5.下列排序算法中,依次将待排序序列中的元素和前面有序序列合并为一个新的有序序列的排序算法是。

(1)直接插入排序(2)冒泡排序(3)快速排序(4)直接选择排序二、判断题(每小题1分,共10分)l.()设指针 P指向单链表中一个结点,则语句序列U:=P^.next; U :=U^.next 将删除一个结点。

2.()栈和队列都是运算受限的线性表。

3.()广义表的长度是指广义表中的原子个数。

4.()若某二叉树的叶子结点数为1,则其先序序列和后序序列一定相反。

5.()二叉树在按任一种次序线索化后,都可以很容易地求出相应次序下的前趋和后继。

6.()在采用线性探测法处理冲突的散列表中,所有同义词在表中相邻。

7.()对B树中任一非叶子结点中的某关键字K,比K小的最大关键字和比K大的最小关键字一定都在叶子结点中。

8.()若一个无向图的以顶点1为起点的深度遍历序列唯一,则可唯一确定该图。

9.()在对一有向无环图执行拓扑排序算法之后,入度数组中的所有元素的值为0。

10.()在数据表基本有序时,冒泡排序算法的时间复杂度一定接近O(n)。

三、填空题(每小题2分,共20分)1.在单链表中,在指针P所指结点的后面插入一个结点到的语句序列是。

数据结构_2_试题卷

数据结构_2_试题卷

山东工商学院2020学年第一学期数据结构课程试题 A卷(考试时间:120分钟,满分100分)特别提醒:1、所有答案均须填写在960数字加起来827参考答案207上,写在试题纸上无效。

2、每份答卷上均须准确填写函授站、专业、年级、学号、姓名、课程名称。

一单选题 (共20题,总分值40分 )1. 以下属单链表优点的是()。

(2 分)A. 顺序存取B. 插入操作能在O(1)的时间复杂度上完成C. 插入时不需移动数据元素D. 节省存储空间2. 外部排序是指()。

(2 分)A. 在外存上进行的排序方法B. 不需要使用内存的排序方法C. 数据量很大,需要人工干预的排序方法D. 排序前后数据在外存,排序时数据调入内存的排序方法3. 若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用()存储方式最节省时间。

(2 分)A. 顺序表B. 双链表C. 带头结点的双向循环链表D. 单循环链表4. 下列不属算法特性的是()。

(2 分)A. 有穷性B. 确定性C. 零或多个输入D. 健壮性5. 设有一组关键字值(46,79,56,38,40,84),则用快速排序的方法,以第一个记录为基准得到的一次划分结果为()。

(2 分)A. 38,40,46,56,79,84B. 40,38,46,79,56,84C. 40,38,46,56,79,84D. 40,38,46,84,56,796. ISAM文件和VSAM文件属于()。

(2 分)A. 索引非顺序文件B. 索引顺序文件C. 顺序文件D. 散列文件7. 直接插入排序在最好情况下的时间复杂度为()。

(2 分)A. O(logn)B. O(n)C. O(n*logn)D. O(n2)8. 判定一个栈顶指针为S且不带头结点的链栈为空栈的条件是()。

(2 分)A. SB. S->nextC. S->next==NULLD. !S9. 在树形结构中,数据元素间存在()的关系。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

南通大学数据结构实践课实验报告册姓名:耿智班级:软件工程092学号:0913063042实验名称:先序线索化指导老师:丁卫平南通大学杏林学院2011年6月16日1.程序设计简介本实验程序用于验证二叉树的先序线索化及先序线索二叉树先序遍历算法,为了查看线索结果,增加了线索显示功能。

设计时综合考虑到中序线索化需求,采用设计一个基类,然后在此基础上生成所需的对象。

2.源程序#include "Base.cpp"template <class T>class CPreThreading:public CThr<T>{bool IsThreaded;public:CPreThreading(){IsThreaded=false;}void Pre_ThreadBiTree(); //生成先序线索二叉树void Pre_Thread(BiThrNode<T>*p,BiThrNode<T>**h); //先序线索void Pre_TraThrBiTree(); //遍历先序线索二叉树void ShowPreTree(); //显示线索化后的信息};template <class T>void CPreThreading<T>::Pre_ThreadBiTree(){ //生成先序线索二叉链表BiThrNode<T>*bt,*q=NULL;bt=BT; //根结点Pre_Thread(bt,&q);}//--------------------------------------------------------------------------------template <class T>void CPreThreading<T>::Pre_TraThrBiTree(){if(IsThreaded==false){cout<<"请先线索化!"<<endl;return;}cout<<"\n--------------------------------------------------"<<endl;cout<<"遍历先序线索二叉树得:";BiThrNode<T>*p;if(BT==NULL) return ; //二叉链表为空cout<<BT->data<<' '; //输出根结点的值p=BT->lchild; //沿左子树if(p==NULL) p=BT->rchild; //左子树为空则沿右子树while(p!=NULL){cout<<p->data<<' '; //输出当前结点的值while(p->lflag==0) //沿左链访问直到左标志非0{p=p->lchild;cout<<p->data<<' ';}p=p->rchild;}cout<<"\n--------------------------------------------------"<<endl;}//--------------------------------------------------------------------------------template <class T>void CPreThreading<T>::Pre_Thread(BiThrNode<T>*bt,BiThrNode<T>**h) {BiThrNode<T>*p,*q; //定义两个结点指针变量if(bt!=NULL) //bt指向的结点不空{p=bt->lchild ;q=bt->rchild ;//若当前访问的结点的左指针为空,则将上次访问的结点赋给左指针域,并置标志域if((*h!=NULL)&&(p==NULL)){bt->lchild= *h;bt->lflag= 1;}//若上次访问的结点的右指针为空//则将访问过的结点指针赋给当前结点的右指针域,并置标志域为1if((*h!=NULL)&&((*h)->rchild==NULL)){(*h)->rchild=bt;(*h)->rflag=1;}*h=bt; //记下当前访问的结点Pre_Thread(p,h); //访问左子树Pre_Thread(q,h); //访问右子树}IsThreaded=true;}//--------------------------------------------------------------------------------template <class T>void CPreThreading<T>::ShowPreTree(){if(IsThreaded==false){cout<<"请先线索化!"<<endl;return;}cout<<"\n--------------------------------------------------"<<endl;cout<<"下面显示的是先序线索化以后的结果:"<<endl;BiThrNode<T>*p;if(BT==NULL) return ; //二叉链表为空。

if(BT->lflag==1) //如果标志域为1,输出它的前驱。

cout<<"值为:"<<BT->data<<"结点的前驱是:"<<BT->lchild->data<<endl;if(BT->rflag==1) //如果标志域为1,输出它的后继。

cout<<"值为:"<<BT->data<<"结点的后继是:"<<BT->rchild->data<<endl;p=BT->lchild; //沿左子树。

if(p==NULL) p=BT->rchild; //左子树为空则沿右子树。

while(p!=NULL){if(p->lflag==1) //如果标志域为1,输出它的前驱。

cout<<"值为:"<<p->data<<"结点的前驱是:"<<p->lchild->data<<endl;if(p->rflag==1) //如果标志域为1,输出它的后继。

cout<<"值为:"<<p->data<<"结点的后继是:"<<p->rchild->data<<endl;while(p->lflag==0) //沿左链访问直到左标志非0{p=p->lchild;if(p->lflag==1) //如果标志域为1,输出它的前驱。

cout<<"值为:"<<p->data<<"结点的前驱是:"<<p->lchild->data<<endl;if(p->rflag==1) //如果标志域为1,输出它的后继。

cout<<"值为:"<<p->data<<"结点的后继是:"<<p->rchild->data<<endl;}p=p->rchild;}cout<<"--------------------------------------------------"<<endl;}//--------------------------------------------------------------------------------void main(){int opr;//操作变量CPreThreading<int> Tr;//创建一个int 模板类型的对象do{system("cls");cout<<"----------菜单---------------"<<endl;cout<<"--* 1:创建二叉树*--"<<endl;cout<<"--* 2:先序线索化二叉树*--"<<endl;cout<<"--* 3:先序线索化二叉树先序遍历*--"<<endl;cout<<"--* 4:显示先序线索信息*--"<<endl;cout<<"--* 5:退出操作*--"<<endl;cout<<"--------------------------------"<<endl;cout<<"请选择操作[ ]";cout<<"\b\b";cin>>opr;switch(opr){case 1:if(Tr.GetRoot()) Tr.DeleteNode(); //释放之前创建的对象的所有结点空间Tr.CreateBiTree(-1); //创建二叉树system("pause");break;case 2:Tr.Pre_ThreadBiTree(); //先序线索化二叉树cout<<"线索化完成!"<<endl;system("pause");break;case 3:Tr.Pre_TraThrBiTree(); //先序遍历二叉树system("pause");break;case 4:Tr.ShowPreTree(); //显示线索化之后的标志域信息system("pause");break;case 5:cout<<"结束运行,Bye-Bye!"<<endl;break;default:cout<<"选择不合理,请重选!"<<endl;break;}}while(opr!=5);}3.程序运行4.调试感想在线索化二叉树时,如果像书上把二叉树和线索二叉树的存储结构分开,则二叉树中的数据域不能传递到线索二叉树中(两个类型的指针不能互相赋值)。

相关文档
最新文档