数据结构第六章课后答案
- 格式:pdf
- 大小:805.97 KB
- 文档页数:29
第6章查找一、选择题1. B2. A3. C4. C5. D6. B7. C8. D9. D 10. D 11. C 12. D 13. B 14. C 15. B二、判断题1. Ⅹ2. √3. Ⅹ4. √5. Ⅹ6. √7. √8. Ⅹ9. Ⅹ 10. Ⅹ11. √ 12. √ 13. √ 14. √ 15. Ⅹ 16. Ⅹ 17. √ 18. Ⅹ 19. √ 20. √三、简答题1. 画出对长度为18的有序的顺序表进行折半查找时的判定树,并指出在等概率时查找成功的平均查找长度,以及查找失败时所需的最多的关键字比较次数。
【解答】(1)(2) 平均查找长度为1/18(1+2*2+3*4+4*8+5*3)=32/9查找最多比较5次。
2. 已知如下所示长度为12的关键字有序的表:{Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec}(1) 试按表中元素的顺序依次插入到一棵初始为空的二叉排序树,画出插入完成后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
(2) 若对表中元素先进行排序构成有序表,求在等概率的情况下查找成功的平均查找长度。
(3) 按表中元素的顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
【解答】(1) 按关键字的顺序构造的二叉排序树:(2) 根据构造的二叉排序树,求查找成功时的平均查找长度: ASL SUCC =(1*1+2*2+3*3+4*3+5*2+6*1)/12=3.5(3) 若对表中元素先进行排序构成有序表再构造二叉排序树,则构造的二叉排序树是一棵单支树,在等概率的情况下查找成功的平均查找长度则为:ASL SUCC =(1+2+…+12)/12=6.5 这种情况就退化成为顺序查找。
3. 试推导含有12个结点的平衡二叉树的最大深度,并画出一棵这样的树。
【解答】令F k 表示含有最少结点的深度为k 的平衡二叉树的结点数目。
《数据结构(C语言版第2版)》(严蔚敏著)第六章练习题答案第6章图1.选择题(1)在一个图中,所有顶点的度数之和等于图的边数的()倍。
A.1/2B.1C.2D.4答案:C(2)在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的()倍。
A.1/2B.1C.2D.4答案:B解释:有向图所有顶点入度之和等于所有顶点出度之和。
(3)具有n个顶点的有向图最多有()条边。
A.n B.n(n-1)C.n(n+1)D.n2答案:B解释:有向图的边有方向之分,即为从n个顶点中选取2个顶点有序排列,结果为n(n-1)。
(4)n个顶点的连通图用邻接距阵表示时,该距阵至少有()个非零元素。
A.n B.2(n-1)C.n/2D.n2答案:B所谓连通图一定是无向图,有向的叫做强连通图连通n个顶点,至少只需要n-1条边就可以了,或者说就是生成树由于无向图的每条边同时关联两个顶点,因此邻接矩阵中每条边被存储了两次(也就是说是对称矩阵),因此至少有2(n-1)个非零元素(5)G是一个非连通无向图,共有28条边,则该图至少有()个顶点。
A.7B.8C.9D.10答案:C解释:8个顶点的无向图最多有8*7/2=28条边,再添加一个点即构成非连通无向图,故至少有9个顶点。
(6)若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问图中所有的顶点,则该图一定是()图。
A.非连通B.连通C.强连通D.有向答案:B解释:即从该无向图任意一个顶点出发有到各个顶点的路径,所以该无向图是连通图。
(7)下面()算法适合构造一个稠密图G的最小生成树。
A.Prim算法B.Kruskal算法C.Floyd算法D.Dijkstra算法答案:A解释:Prim算法适合构造一个稠密图G的最小生成树,Kruskal算法适合构造一个稀疏图G的最小生成树。
(8)用邻接表表示图进行广度优先遍历时,通常借助()来实现算法。
A.栈 B.队列 C.树D.图答案:B解释:广度优先遍历通常借助队列来实现算法,深度优先遍历通常借助栈来实现算法。
一、基础知识题6.1设树T的度为4,其中度为1,2,3和4的结点个数分别为4,2,1,1,求树T中的叶子数。
【解答】设度为m的树中度为0,1,2,…,m的结点数分别为n0, n1, n2,…, nm,结点总数为n,分枝数为B,则下面二式成立n= n0+n1+n2+…+nm (1)n=B+1= n1+2n2 +…+mnm+1 (2)由(1)和(2)得叶子结点数n0=1+即: n0=1+(1-1)*4+(2-1)*2+(3-1)*1+(4-1)*1=86.2一棵完全二叉树上有1001个结点,求叶子结点的个数。
【解答】因为在任意二叉树中度为2 的结点数n2和叶子结点数n0有如下关系:n2=n0-1,所以设二叉树的结点数为n, 度为1的结点数为n1,则n= n0+ n1+ n2n=2n0+n1-11002=2n0+n1由于在完全二叉树中,度为1的结点数n1至多为1,叶子数n0是整数。
本题中度为1的结点数n1只能是0,故叶子结点的个数n0为501.注:解本题时要使用以上公式,不要先判断完全二叉树高10,前9层是满二叉树,第10层都是叶子,……。
虽然解法也对,但步骤多且复杂,极易出错。
6.3 一棵124个叶结点的完全二叉树,最多有多少个结点。
【解答】由公式n=2n0+n1-1,当n1为1时,结点数达到最多248个。
6.4.一棵完全二叉树有500个结点,请问该完全二叉树有多少个叶子结点?有多少个度为1的结点?有多少个度为2的结点?如果完全二叉树有501个结点,结果如何?请写出推导过程。
【解答】由公式n=2n0+n1-1,带入具体数得,500=2n0+n1-1,叶子数是整数,度为1的结点数只能为1,故叶子数为250,度为2的结点数是249。
若完全二叉树有501个结点,则叶子数251,度为2的结点数是250,度为1的结点数为0。
6.5 某二叉树有20个叶子结点,有30个结点仅有一个孩子,则该二叉树的总结点数是多少。
数据结构答案第6章第6章数据结构答案1. 栈的应用栈是一种常见的数据结构,其特点是先进后出。
下面是一些关于栈的应用场景。
1.1 函数调用栈在程序中,每当一个函数被调用时,相关的变量和状态信息会被存储在一个称为函数调用栈的栈中。
1.2 表达式求值栈也常用于表达式求值,特别是中缀表达式转后缀表达式的过程中。
通过使用栈,我们可以很方便地进行算术运算。
1.3 逆序输出如果我们需要逆序输出一段文本、字符串或者其他数据,可以使用栈来实现。
将数据依次压入栈中,然后再逐个弹出即可。
2. 队列的实现与应用队列是另一种常见的数据结构,其特点是先进先出。
下面是一些关于队列的实现和应用。
2.1 数组实现队列队列可以使用数组来实现。
我们可以使用两个指针分别指向队列的前端和后端,通过移动指针来实现入队和出队的操作。
2.2 链表实现队列队列还可以使用链表来实现。
我们可以使用一个指针指向队列的头部,并在尾部添加新元素。
通过移动指针来实现出队操作。
2.3 广度优先搜索(BFS)队列常用于广度优先搜索算法。
在BFS中,我们需要按照层级来访问节点。
使用队列可以帮助我们按照顺序存储和访问节点。
3. 树的遍历和应用树是一种非常重要的数据结构,在计算机科学中应用广泛。
下面是一些关于树的遍历和应用的介绍。
3.1 深度优先搜索(DFS)深度优先搜索是树的一种遍历方式。
通过递归或者使用栈的方式,可以按照深度优先的顺序遍历树的所有节点。
3.2 广度优先搜索(BFS)广度优先搜索也可以用于树的遍历。
通过使用队列来保存要访问的节点,可以按照层级的顺序遍历树。
3.3 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值都大于左子树中的值,小于右子树中的值。
这种结构可以用于高效地进行数据查找。
4. 图的表示与遍历图是由节点和边组成的一种数据结构。
下面是一些关于图的表示和遍历的说明。
4.1 邻接矩阵表示法邻接矩阵是一种常见的图的表示方法。
使用一个二维数组来表示节点之间的连接关系。
第六章图习题解答一、选择题1.某无向图的邻接矩阵A=[010101010],可以看出该图共有()个顶点A.3B.6C.9D.以上答案均不正确【解答】A2.无向图的邻接矩阵是一个(),有向图的邻接矩阵是一个()A 上三角矩阵B 下三角矩阵C 对称矩阵D 无规律【解答】C,D3.下列命题正确的是()。
A 一个图的邻接矩阵表示是唯一的,邻接表表示也唯一B 一个图的邻接矩阵表示是唯一的,邻接表表示不唯一C 一个图的邻接矩阵表示不唯一的,邻接表表示是唯一D 一个图的邻接矩阵表示不唯一的,邻接表表示也不唯一【解答】B4. 在一个具有n 个顶点的有向完全图中包含有()条边:A n(n-1)/2B n(n-1)C n(n+1)/2D n2【解答】B5.一个具有n个顶点k条边的无向图是一个森林(n>k),则该森林中必有()棵树。
A kB nC n - kD 1【解答】C6.用深度优先遍历方法遍历一个有向无环图,并在深度优先遍历算法中按退栈次序打印出相应的顶点,则输出的顶点序列是()。
A 逆拓扑有序B 拓扑有序C 无序D 深度优先遍历序列【解答】A7. 关键路径是AOE网中()。
A 从源点到终点的最长路径B从源点到终点的最长路径C 最长的回路D 最短的回路【解答】A二、填空题1.设无向图G中顶点数为n,则图G至少有()条边,至多有()条边;若G为有向图,则至少有()条边,至多有()条边。
【解答】0,n(n-1)/2,0,n(n-1)2.任何连通图的连通分量只有一个,即是()。
【解答】其自身3.图的存储结构主要有两种,分别是()和()。
【解答】邻接矩阵,邻接表4.已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为()。
【解答】O(n+e)5.已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是()。
【解答】求第j列的所有元素之和6.有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的()。
第6章树和二叉树习题解答一、下面是有关二叉树的叙述,请判断正误(每小题1分,共10分)(√)1. 若二叉树用二叉链表作存贮结构,则在n个结点的二叉树链表中只有n—1个非空指针域。
(×)2.二叉树中每个结点的两棵子树的高度差等于1。
(√)3.二叉树中每个结点的两棵子树是有序的。
(×)4.二叉树中每个结点有两棵非空子树或有两棵空子树。
(×)5.二叉树中每个结点的关键字值大于其左非空子树(若存在的话)所有结点的关键字值,且小于其右非空子树(若存在的话)所有结点的关键字值。
(应当是二叉排序树的特点)(×)6.二叉树中所有结点个数是2k-1-1,其中k是树的深度。
(应2i-1)(×)7.二叉树中所有结点,如果不存在非空左子树,则不存在非空右子树。
(×)8.对于一棵非空二叉树,它的根结点作为第一层,则它的第i层上最多能有2i—1个结点。
(应2i-1)(√)9.用二叉链表法(link-rlink)存储包含n个结点的二叉树,结点的2n个指针区域中有n+1个为空指针。
(正确。
用二叉链表存储包含n个结点的二叉树,结点共有2n个链域。
由于二叉树中,除根结点外,每一个结点有且仅有一个双亲,所以只有n-1个结点的链域存放指向非空子女结点的指针,还有n+1个空指针。
)即有后继链接的指针仅n-1个。
(√)10. 〖01年考研题〗具有12个结点的完全二叉树有5个度为2的结点。
最快方法:用叶子数=[n/2]=6,再求n2=n0-1=5二、填空(每空1分,共15分)1.由3个结点所构成的二叉树有5种形态。
2. 【计算机研2000】一棵深度为6的满二叉树有n1+n2=0+ n2= n0-1=31 个分支结点和26-1 =32个叶子。
注:满二叉树没有度为1的结点,所以分支结点数就是二度结点数。
3.一棵具有257个结点的完全二叉树,它的深度为9。
(注:用⎣ log2(n) ⎦+1= ⎣ 8.xx ⎦+1=94.【全国专升本统考题】设一棵完全二叉树有700个结点,则共有350个叶子结点。
一.名词解释(1)结点—— 树的结点包含一个数据及若干指向其子树的分支。
(2)结点的度—— 结点所拥有的子树数称为该结点的度。
(3)树的度—— 树中各结点度的最大值称为该树的度。
(4)二叉树—— 一棵非空的二叉树,每个结点至多只有两棵子树,分别称为左子树和右子树,左、右子树的次序不能任意交换,且左右子树又分别是一棵二叉树。
(5)哈夫曼树—— 带权路径长度最小的二叉树,即最优二叉树,也称为哈夫曼树。
二.判断题(下列各题,正确的请在前面的括号内打√;错误的打ㄨ) (1)√ (2)ㄨ (3)√ (4)√(5)√(6)ㄨ (7)ㄨ(8)√三.填空题1.结点拥有的子树数 2.度为零的3. 树内各结点度的最大值 4.深度(或高度) 5.2i-1 6. 2h -1 7. n-1 8.6 9.中序 10.5 11.20 12. ⎣⎦1log 2+n13.顺序存储结构和链式存储结构 14.最小 15.EBCAD16.(1) ABEFHCG (2).EBHFACG (3).EHFBGCA 17.空二叉树 18.4四.选择题(1)B (2)C (3)C (4)C (5)D(6)B (7)A (8)B (9)D (10)D(11)B (12)A (13)C五.简答题1.答:一般树(非空)除了根结点之外,每个结点有且仅有一个前驱结点,但每个结点都可以有多个互不相交的子集(后继结点)。
二叉树(若非空)除了根结点之外,每个结点有且仅有一个前驱结点,但每个结点至多只有两个后继结点,称为左子树和右子树,左、右子树的次序不能交换,且左右子树又分别都是二叉树。
一般树和二叉树主要有以下区别:二叉树结点的度最大为2,而一般树结点的最大度数无限制;一般树的结点无左、右之分,而二叉树的结点有左、右之分。
2.答:一棵度为2的树与一棵二叉树的区别在于:对于度为1的结点,度为2的树无须区分左右;对于二叉树必须有左右之分,且不能任意交换。
3.答:(1)A是根结点。
第6章 树和二叉树(参考答案)6.1(1)根结点a6.2三个结点的树的形态: 三个结点的二叉树的形态:(1) (1) (2) (4) (5)6.3 设树的结点数是n ,则n=n0+n1+n2+……+nm+ (1)设树的分支数为B ,有n=B+1n=1n1+2n2+……+mnm+1 (2)由(1)和(2)有:n0=n2+2n3+……+(m-1)nm+16.4(1) k i-1 (i 为层数)(2) (n-2)/k+1(3) (n-1)*k+i+1(4) (n-1)%k !=0; 其右兄弟的编号 n+16.5(1)顺序存储结构注:#为空结点6.6(1) 前序 ABDGCEFH(2) 中序 DGBAECHF(3) 后序 GDBEHFCA6.7(1) 空二叉树或任何结点均无左子树的非空二叉树(2) 空二叉树或任何结点均无右子树的非空二叉树(3) 空二叉树或只有根结点的二叉树6.8int height(bitree bt)// bt是以二叉链表为存储结构的二叉树,本算法求二叉树bt的高度{ int bl,br; // 局部变量,分别表示二叉树左、右子树的高度if (bt==null) return(0);else { bl=height(bt->lchild);br=height(bt->rchild);return(bl>br? bl+1: br+1); // 左右子树高度的大者加1(根) }}// 算法结束6.9void preorder(cbt[],int n,int i);// cbt是以完全二叉树形式存储的n个结点的二叉树,i是数// 组下标,初始调用时为1。
本算法以非递归形式前序遍历该二叉树{ int i=1,s[],top=0; // s是栈,栈中元素是二叉树结点在cbt中的序号 // top是栈顶指针,栈空时top=0if (n<=0) { printf(“输入错误”);exit(0);}while (i<=n ||top>0){ while(i<=n){visit(cbt[i]); // 访问根结点if (2*i+1<=n) s[++top]=2*i+1; //若右子树非空,其编号进栈i=2*i;// 先序访问左子树}if (top>0) i=s[top--]; // 退栈,先序访问右子树} // END OF while (i<=n ||top>0)}// 算法结束//以下是非完全二叉树顺序存储时的递归遍历算法,“虚结点”用‘*’表示void preorder(bt[],int n,int i);// bt是以完全二叉树形式存储的一维数组,n是数组元素个数。
第六章树和二叉树(下载后用阅读版式视图或web版式可以看清)习题一、选择题1.有一“遗传”关系:设x是y的父亲,则x可以把它的属性遗传给y。
表示该遗传关系最适合的数据结构为( )。
A.向量B.树C图 D.二叉树2.树最合适用来表示( )。
A.有序数据元素 B元素之间具有分支层次关系的数据C无序数据元素 D.元素之间无联系的数据3.树B的层号表示为la,2b,3d,3e,2c,对应于下面选择的( )。
A. la (2b (3d,3e),2c)B. a(b(D,e),c)C. a(b(d,e),c)D. a(b,d(e),c)4.高度为h的完全二叉树至少有( )个结点,至多有( )个结点。
A. 2h_lB.h C.2h-1 D. 2h5.在一棵完全二叉树中,若编号为f的结点存在右孩子,则右子结点的编号为( )。
A. 2iB. 2i-lC. 2i+lD. 2i+26.一棵二叉树的广义表表示为a(b(c),d(e(,g(h)),f)),则该二叉树的高度为( )。
A.3B.4C.5D.67.深度为5的二叉树至多有( )个结点。
A. 31B. 32C. 16D. 108.假定在一棵二叉树中,双分支结点数为15,单分支结点数为30个,则叶子结点数为( )个。
A. 15B. 16C. 17D. 479.题图6-1中,( )是完全二叉树,( )是满二叉树。
10.在题图6-2所示的二叉树中:(1)A结点是A.叶结点 B根结点但不是分支结点C根结点也是分支结点 D.分支结点但不是根结点(2)J结点是A.叶结点 B.根结点但不是分支结点C根结点也是分支结点 D.分支结点但不是根结点(3)F结点的兄弟结点是A.EB.D C.空 D.I(4)F结点的双亲结点是A.AB.BC.CD.D(5)树的深度为A.1B.2C.3D.4(6)B结点的深度为A.1B.2C.3D.4(7)A结点所在的层是A.1B.2C.3D.411.在一棵具有35个结点的完全二叉树中,该树的深度为( )。
数据结构答案第6章第6章图2005-07-14第6章图课后习题讲解1.填空题⑴设无向图G中顶点数为n,则图G至少有()条边,至多有()条边;若G为有向图,则至少有()条边,至多有()条边。
【解答】0,n(n-1)/2,0,n(n-1)【分析】图的顶点集合是有穷非空的,而边集可以是空集;边数达到最多的图称为完全图,在完全图中,任意两个顶点之间都存在边。
⑵任何连通图的连通分量只有一个,即是()。
【解答】其自身⑶图的存储结构主要有两种,分别是()和()。
【解答】邻接矩阵,邻接表【分析】这是最常用的两种存储结构,此外,还有十字链表、邻接多重表、边集数组等。
⑷已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为()。
【解答】O(n+e)【分析】在无向图的邻接表中,顶点表有n个结点,边表有2e个结点,共有n+2e个结点,其空间复杂度为O(n+2e)=O(n+e)。
⑸已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是()。
【解答】求第j列的所有元素之和⑹有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的()。
【解答】出度⑺图的深度优先遍历类似于树的()遍历,它所用到的数据结构是();图的广度优先遍历类似于树的()遍历,它所用到的数据结构是()。
【解答】前序,栈,层序,队列⑻对于含有n个顶点e条边的连通图,利用Prim算法求最小生成树的时间复杂度为(),利用Krukal算法求最小生成树的时间复杂度为()。
【解答】O(n2),O(elog2e)【分析】Prim算法采用邻接矩阵做存储结构,适合于求稠密图的最小生成树;Krukal算法采用边集数组做存储结构,适合于求稀疏图的最小生成树。
⑼如果一个有向图不存在(),则该图的全部顶点可以排列成一个拓扑序列。
【解答】回路⑽在一个有向图中,若存在弧、、,则在其拓扑序列中,顶点vi,vj,vk的相对次序为()。
【解答】vi,vj,vk【分析】对由顶点vi,vj,vk组成的图进行拓扑排序。
第六章数据结构基础习题及参考答案第六章数据结构基础一、选择题1.下列数据结构中,(C)不是数据逻辑结构。
A.树结构B.线性表结构C.存储器物理结构D.二叉树2.数据结构是(D)。
A.一种数据类型B.数据的存储结构C.一组性质相同的数据元素的结合D.相互之间存在一种或多种特定关系的数据元素的集合3.下列关于队列的叙述中,正确的是(C)。
A.在队列中只能入数据B.在队列中只能删除数据C.队列是先进先出的线性表D.队列是后进先出的线性表4.如果进栈序列为a1,a2,a3,a4,则可能的出栈序列是(B)A.a3,a1,a4,a2B.a2,a4,a3,a1C.a3,a4,a1,a2D.任意顺序5.链表不具备的特点是(A)A.可能随机访问任意一个节点B.插入和删除不需要移动任何元素C.不必事先估计存储空间D.所需空间与其长度成正比、6.已知某二叉树的后续遍历序列是DACBE,中序遍历序列是DEBAC,则它的前序遍历序列是(D)。
A.ACBEDB.DEABCC.DECABD.EDBCA7.某二叉树中度为2的结点有18个,则该二叉树中有(C)个叶子结点。
A.17B.18C.19D.20二、填空题1.数据元素是(数据)的基本单位,是对一个客观实体的数据描述。
2.简单地说,数据结构是指数据之间的(逻辑关系),即数据的逻辑结构。
3.数据的逻辑结构可用一个二元B=(K,R)来表示,其中K表示(数据元素集合),R表示(数据元素之间的前后关系)。
4.数据元素之间的关系有4种基本的存储表示方法,即(集合)、(线性结构)、(树)和(图)。
5.数据的运算中,(移位)是一个很重要的运算过程,插入、删除、修改和排序都包含着这种运算。
6.线性表是一种最简单、最常用的数据结构,通常一个线性表是由n 个性质相同的数据元素组成的(有限序列),其长度即线性表中元素的个数n,当n=0时,称为(空表)。
7.线性表是一种(线性)结构。
8.如果线性表中最常用的操作是存取第i个元素及其前驱的值,则采用(双向链表)存储方式节省时间。
第六章树和二叉树6.33int Is_Descendant_C(int u,int v)//在孩子存储结构上判断u是否v的子孙,是则返回1,否则返回0{if(u==v) return 1;else{if(L[v])if (Is_Descendant(u,L[v])) return 1;if(R[v])if (Is_Descendant(u,R[v])) return 1; //这是个递归算法}return 0;}//Is_Descendant_C6.34int Is_Descendant_P(int u,int v)//在双亲存储结构上判断u是否v的子孙,是则返回1,否则返回0{for(p=u;p!=v&&p;p=T[p]);if(p==v) return 1;else return 0;}//Is_Descendant_P6.35这一题根本不需要写什么算法,见书后注释:两个整数的值是相等的.6.36int Bitree_Sim(Bitree B1,Bitree B2)//判断两棵树是否相似的递归算法{if(!B1&&!B2) return 1;elseif(B1&&B2&&Bitree_Sim(B1->lchild,B2->lchild)&&Bitree_Sim(B1->rchild,B2->rc hild))return 1;else return 0;}//Bitree_Sim6.37void PreOrder_Nonrecursive(Bitree T)//先序遍历二叉树的非递归算法{InitStack(S);Push(S,T); //根指针进栈while(!StackEmpty(S)){while(Gettop(S,p)&&p){visit(p->data);push(S,p->lchild);} //向左走到尽头pop(S,p);if(!StackEmpty(S)){pop(S,p);push(S,p->rchild); //向右一步}}//while}//PreOrder_Nonrecursive6.38typedef struct {BTNode* ptr;enum {0,1,2} mark;} PMType; //有mark域的结点指针类型void PostOrder_Stack(BiTree T)//后续遍历二叉树的非递归算法,用栈{PMType a;InitStack(S); //S的元素为PMType类型Push (S,{T,0}); //根结点入栈while(!StackEmpty(S)){Pop(S,a);switch(a.mark){case 0:Push(S,{a.ptr,1}); //修改mark域if(a.ptr->lchild) Push(S,{a.ptr->lchild,0}); //访问左子树break;case 1:Push(S,{a.ptr,2}); //修改mark域if(a.ptr->rchild) Push(S,{a.ptr->rchild,0}); //访问右子树break;case 2:visit(a.ptr); //访问结点,返回}}//while}//PostOrder_Stack分析:为了区分两次过栈的不同处理方式,在堆栈中增加一个mark域,mark=0表示刚刚访问此结点,mark=1表示左子树处理结束返回,mark=2表示右子树处理结束返回.每次根据栈顶元素的mark域值决定做何种动作.6.39typedef struct {int data;EBTNode *lchild;EBTNode *rchild;EBTNode *parent;enum {0,1,2} mark;} EBTNode,EBitree; //有mark域和双亲指针域的二叉树结点类型void PostOrder_Nonrecursive(EBitree T)//后序遍历二叉树的非递归算法,不用栈{p=T;while(p)switch(p->mark){case 0:p->mark=1;if(p->lchild) p=p->lchild; //访问左子树break;case 1:p->mark=2;if(p->rchild) p=p->rchild; //访问右子树break;case 2:visit(p);p->mark=0; //恢复mark值p=p->parent; //返回双亲结点}}//PostOrder_Nonrecursive分析:本题思路与上一题完全相同,只不过结点的mark值是储存在结点中的,而不是暂存在堆栈中,所以访问完毕后要将mark域恢复为0,以备下一次遍历.6.40typedef struct {int data;PBTNode *lchild;PBTNode *rchild;PBTNode *parent;} PBTNode,PBitree; //有双亲指针域的二叉树结点类型void Inorder_Nonrecursive(PBitree T)//不设栈非递归遍历有双亲指针的二叉树{p=T;while(p->lchild) p=p->lchild; //向左走到尽头while(p){visit(p);if(p->rchild) //寻找中序后继:当有右子树时{p=p->rchild;while(p->lchild) p=p->lchild; //后继就是在右子树中向左走到尽头}else if(p->parent->lchild==p) p=p->parent; //当自己是双亲的左孩子时后继就是双亲else{p=p->parent;while(p->parent&&p->parent->rchild==p) p=p->parent;p=p->parent;} //当自己是双亲的右孩子时后继就是向上返回直到遇到自己是在其左子树中的祖先}//while}//Inorder_Nonrecursive6.41int c,k; //这里把k和计数器c作为全局变量处理void Get_PreSeq(Bitree T)//求先序序列为k的结点的值{if(T){c++; //每访问一个子树的根都会使前序序号计数器加1if(c==k){printf("Value is %d\n",T->data);exit (1);}else{Get_PreSeq(T->lchild); //在左子树中查找Get_PreSeq(T->rchild); //在右子树中查找}}//if}//Get_PreSeqmain(){...scanf("%d",&k);c=0; //在主函数中调用前,要给计数器赋初值0Get_PreSeq(T,k);...}//main6.42int LeafCount_BiTree(Bitree T)//求二叉树中叶子结点的数目{if(!T) return 0; //空树没有叶子else if(!T->lchild&&!T->rchild) return 1; //叶子结点else return Leaf_Count(T->lchild)+Leaf_Count(T->rchild);//左子树的叶子数加上右子树的叶子数}//LeafCount_BiTree6.43void Bitree_Revolute(Bitree T)//交换所有结点的左右子树{T->lchild<->T->rchild; //交换左右子树if(T->lchild) Bitree_Revolute(T->lchild);if(T->rchild) Bitree_Revolute(T->rchild); //左右子树再分别交换各自的左右子树}//Bitree_Revolute6.44int Get_Sub_Depth(Bitree T,int x)//求二叉树中以值为x的结点为根的子树深度{if(T->data==x){printf("%d\n",Get_Depth(T)); //找到了值为x的结点,求其深度exit 1;}else{if(T->lchild) Get_Sub_Depth(T->lchild,x);if(T->rchild) Get_Sub_Depth(T->rchild,x); //在左右子树中继续寻找}}//Get_Sub_Depthint Get_Depth(Bitree T)//求子树深度的递归算法{if(!T) return 0;else{m=Get_Depth(T->lchild);n=Get_Depth(T->rchild);return (m>n?m:n)+1;}//Get_Depth6.45void Del_Sub_x(Bitree T,int x)//删除所有以元素x为根的子树{if(T->data==x) Del_Sub(T); //删除该子树else{if(T->lchild) Del_Sub_x(T->lchild,x);if(T->rchild) Del_Sub_x(T->rchild,x); //在左右子树中继续查找}//else}//Del_Sub_xvoid Del_Sub(Bitree T)//删除子树T{if(T->lchild) Del_Sub(T->lchild);if(T->rchild) Del_Sub(T->rchild);free(T);}//Del_Sub6.46void Bitree_Copy_Nonrecursive(Bitree T,Bitree &U)//非递归复制二叉树{InitStack(S1);InitStack(S2);push(S1,T); //根指针进栈U=(BTNode*)malloc(sizeof(BTNode));U->data=T->data;q=U;push(S2,U);while(!StackEmpty(S)){while(Gettop(S1,p)&&p){q->lchild=(BTNode*)malloc(sizeof(BTNode));q=q->lchild;q->data=p->data;push(S1,p->lchild);push(S2,q);} //向左走到尽头pop(S1,p);pop(S2,q);if(!StackEmpty(S1)){pop(S1,p);pop(S2,q);q->rchild=(BTNode*)malloc(sizeof(BTNode));q=q->rchild;q->data=p->data;push(S1,p->rchild); //向右一步push(S2,q);}//while}//BiTree_Copy_Nonrecursive分析:本题的算法系从6.37改写而来.6.47void LayerOrder(Bitree T)//层序遍历二叉树{InitQueue(Q); //建立工作队列EnQueue(Q,T);while(!QueueEmpty(Q)){DeQueue(Q,p);visit(p);if(p->lchild) EnQueue(Q,p->lchild);if(p->rchild) EnQueue(Q,p->rchild);}}//LayerOrder6.48int found=FALSE;Bitree* Find_Near_Ancient(Bitree T,Bitree p,Bitree q)//求二叉树T中结点p和q的最近共同祖先{Bitree pathp[ 100 ],pathq[ 100 ] //设立两个辅助数组暂存从根到p,q的路径Findpath(T,p,pathp,0);found=FALSE;Findpath(T,q,pathq,0); //求从根到p,q的路径放在pathp和pathq中for(i=0;pathp[i]==pathq[i]&&pathp[i];i++); //查找两条路径上最后一个相同结点 return pathp[--i];}//Find_Near_Ancientvoid Findpath(Bitree T,Bitree p,Bitree path[ ],int i)//求从T到p路径的递归算法{if(T==p){found=TRUE;return; //找到}path[i]=T; //当前结点存入路径if(T->lchild) Findpath(T->lchild,p,path,i+1); //在左子树中继续寻找if(T->rchild&&!found) Findpath(T->rchild,p,path,i+1); //在右子树中继续寻找if(!found) path[i]=NULL; //回溯}//Findpathint IsFull_Bitree(Bitree T)//判断二叉树是否完全二叉树,是则返回1,否则返回0 {InitQueue(Q);flag=0;EnQueue(Q,T); //建立工作队列while(!QueueEmpty(Q)){DeQueue(Q,p);if(!p) flag=1;else if(flag) return 0;else{EnQueue(Q,p->lchild);EnQueue(Q,p->rchild); //不管孩子是否为空,都入队列}}//whilereturn 1;}//IsFull_Bitree分析:该问题可以通过层序遍历的方法来解决.与6.47相比,作了一个修改,不管当前结点是否有左右孩子,都入队列.这样当树为完全二叉树时,遍历时得到是一个连续的不包含空指针的序列.反之,则序列中会含有空指针.6.50Status CreateBitree_Triplet(Bitree &T)//输入三元组建立二叉树{if(getchar()!='^') return ERROR;T=(BTNode*)malloc(sizeof(BTNode));p=T;p->data=getchar();getchar(); //滤去多余字符InitQueue(Q);EnQueue(Q,T);while((parent=getchar())!='^'&&(child=getchar())&&(side=getchar())){while(QueueHead(Q)!=parent&&!QueueEmpty(Q)) DeQueue(Q,e);if(QueueEmpty(Q)) return ERROR; //未按层序输入p=QueueHead(Q);q=(BTNode*)malloc(sizeof(BTNode));if(side=='L') p->lchild=q;else if(side=='R') p->rchild=q;else return ERROR; //格式不正确q->data=child;EnQueue(Q,q);}return OK;}//CreateBitree_TripletStatus Print_Expression(Bitree T)//按标准形式输出以二叉树存储的表达式{if(T->data是字母) printf("%c",T->data);else if(T->data是操作符){if(!T->lchild||!T->rchild) return ERROR; //格式错误if(T->lchild->data是操作符&&T->lchild->data优先级低于T->data){printf("(");if(!Print_Expression(T->lchild)) return ERROR;printf(")");} //注意在什么情况下要加括号else if(!Print_Expression(T->lchild)) return ERROR;if(T->rchild->data是操作符&&T->rchild->data优先级低于T->data){printf("(");if(!Print_Expression(T->rchild)) return ERROR;printf(")");}else if(!Print_Expression(T->rchild)) return ERROR;}else return ERROR; //非法字符return OK;}//Print_Expression6.52typedef struct{BTNode node;int layer;} BTNRecord; //包含结点所在层次的记录类型int FanMao(Bitree T)//求一棵二叉树的"繁茂度"{int countd; //count数组存放每一层的结点数InitQueue(Q); //Q的元素为BTNRecord类型EnQueue(Q,{T,0});while(!QueueEmpty(Q)){DeQueue(Q,r);count[yer]++;if(r.node->lchild) EnQueue(Q,{r.node->lchild,yer+1});if(r.node->rchild) EnQueue(Q,{r.node->rchild,yer+1});} //利用层序遍历来统计各层的结点数h=yer; //最后一个队列元素所在层就是树的高度for(maxn=count[0],i=1;count[i];i++)if(count[i]>maxn) maxn=count[i]; //求层最大结点数return h*maxn;}//FanMao分析:如果不允许使用辅助数组,就必须在遍历的同时求出层最大结点数,形式上会复杂一些,你能写出来吗?6.53int maxh;Status Printpath_MaxdepthS1(Bitree T)//求深度等于树高度减一的最靠左的结点{Bitree pathd;maxh=Get_Depth(T); //Get_Depth函数见6.44if(maxh<2) return ERROR; //无符合条件结点Find_h(T,1);return OK;}//Printpath_MaxdepthS1void Find_h(Bitree T,int h)//寻找深度为maxh-1的结点{path[h]=T;if(h==maxh-1){for(i=1;path[i];i++) printf("%c",path[i]->data);exit; //打印输出路径}else{if(T->lchild) Find_h(T->lchild,h+1);if(T->rchild) Find_h(T->rchild,h+1);}path[h]=NULL; //回溯}//Find_h6.54Status CreateBitree_SqList(Bitree &T,SqList sa)//根据顺序存储结构建立二叉链表{Bitree ptr[st+1]; //该数组储存与sa中各结点对应的树指针if(!st){T=NULL; //空树return;}ptr[1]=(BTNode*)malloc(sizeof(BTNode));ptr[1]->data=sa.elem[1]; //建立树根T=ptr[1];for(i=2;i<=st;i++){if(!sa.elem[i]) return ERROR; //顺序错误ptr[i]=(BTNode*)malloc(sizeof(BTNode));ptr[i]->data=sa.elem[i];j=i/2; //找到结点i的双亲jif(i-j*2) ptr[j]->rchild=ptr[i]; //i是j的右孩子else ptr[j]->lchild=ptr[i]; //i是j的左孩子}return OK;}//CreateBitree_SqList6.55int DescNum(Bitree T)//求树结点T的子孙总数填入DescNum域中,并返回该数{if(!T) return -1;else d=(DescNum(T->lchild)+DescNum(T->rchild)+2); //计算公式T->DescNum=d;return d;}//DescNum分析:该算法时间复杂度为O(n),n为树结点总数.注意:为了能用一个统一的公式计算子孙数目,所以当T为空指针时,要返回-1而不是0.6.56BTNode *PreOrder_Next(BTNode *p)//在先序后继线索二叉树中查找结点p的先序后继,并返回指针{if(p->lchild) return p->lchild;else return p->rchild;}//PreOrder_Next分析:总觉得不会这么简单.是不是哪儿理解错了?6.57Bitree PostOrder_Next(Bitree p)//在后序后继线索二叉树中查找结点p的后序后继,并返回指针{if(p->rtag) return p->rchild; //p有后继线索else if(!p->parent) return NULL; //p是根结点else if(p==p->parent->rchild) return p->parent; //p是右孩子else if(p==p->parent->lchild&&p->parent->tag)return p->parent; //p是左孩子且双亲没有右孩子else //p是左孩子且双亲有右孩子{q=p->parent->rchild;while(!q->ltag||!q->rtag){if(!q->ltag) q=q->lchild;else q=q->rchild;} //从p的双亲的右孩子向下走到底return q;}//else}//PostOrder_Next6.58Status Insert_BiThrTree(BiThrTree &T,BiThrTree &p,BiThrTree &x)//在中序线索二叉树T的结点p下插入子树x{if(!p->ltag&&!p->rtag) return INFEASIBLE; //无法插入if(p->ltag) //x作为p的左子树{s=p->lchild; //s为p的前驱p->ltag=Link;p->lchild=x;q=x;while(q->lchild) q=q->lchild;q->lchild=s; //找到子树中的最左结点,并修改其前驱指向sq=x;while(q->rchild) q=q->rchild;q->rchild=p; //找到子树中的最右结点,并修改其前驱指向p}else //x作为p的右子树{s=p->rchild; //s为p的后继p->rtag=Link;p->rchild=x;q=x;while(q->rchild) q=q->rchild;q->rchild=s; //找到子树中的最右结点,并修改其前驱指向sq=x;while(q->lchild) q=q->lchild;q->lchild=p; //找到子树中的最左结点,并修改其前驱指向p}return OK;}//Insert_BiThrTree6.59void Print_CSTree(CSTree T)//输出孩子兄弟链表表示的树T的各边{for(child=T->firstchild;child;child=child->nextsib){printf("(%c,%c),",T->data,child->data);Print_CSTree(child);}}//Print_CSTree6.60int LeafCount_CSTree(CSTree T)//求孩子兄弟链表表示的树T的叶子数目{if(!T->firstchild) return 1; //叶子结点else{count=0;for(child=T->firstchild;child;child=child->nextsib)count+=LeafCount_CSTree(child);return count; //各子树的叶子数之和}}//LeafCount_CSTree6.61int GetDegree_CSTree(CSTree T)//求孩子兄弟链表表示的树T的度{if(!T->firstchild) return 0; //空树else{degree=0;for(p=T->firstchild;p;p=p->nextsib) degree++;//本结点的度for(p=T->firstchild;p;p=p->nextsib){d=GetDegree_CSTree(p);if(d>degree) degree=d; //孩子结点的度的最大值}return degree;}//else}//GetDegree_CSTree6.62int GetDepth_CSTree(CSTree T)//求孩子兄弟链表表示的树T的深度{if(!T) return 0; //空树else{for(maxd=0,p=T->firstchild;p;p=p->nextsib)if((d=GetDepth_CSTree(p))>maxd) maxd=d; //子树的最大深度return maxd+1;}}//GetDepth_CSTree6.63int GetDepth_CTree(CTree A)//求孩子链表表示的树A的深度{return SubDepth(A.r);}//GetDepth_CTreeint SubDepth(int T)//求子树T的深度{if(!A.nodes[T].firstchild) return 1;for(sd=1,p=A.nodes[T].firstchild;p;p=p->next)if((d=SubDepth(p->child))>sd) sd=d;return sd+1;}//SubDepth6.64int GetDepth_PTree(PTree T)//求双亲表表示的树T的深度{maxdep=0;for(i=0;i<T.n;i++){dep=0;for(j=i;j>=0;j=T.nodes[j].parent) dep++; //求每一个结点的深度if(dep>maxdep) maxdep=dep;}return maxdep;}//GetDepth_PTree6.65char Pred,Ind; //假设前序序列和中序序列已经分别储存在数组Pre和In中Bitree Build_Sub(int Pre_Start,int Pre_End,int In_Start,int In_End)//由子树的前序和中序序列建立其二叉链表{sroot=(BTNode*)malloc(sizeof(BTNode)); //建根sroot->data=Pre[Pre_Start];for(i=In_Start;In[i]!=sroot->data;i++); //在中序序列中查找子树根leftlen=i-In_Start;rightlen=In_End-i; //计算左右子树的大小if(leftlen){lroot=Build_Sub(Pre_Start+1,Pre_Start+leftlen,In_Start,In_Start+leftlen-1);sroot->lchild=lroot;} //建左子树,注意参数表的计算if(rightlen){rroot=Build_Sub(Pre_End-rightlen+1,Pre_End,In_End-rightlen+1,In_End);sroot->rchild=rroot;} //建右子树,注意参数表的计算return sroot; //返回子树根}//Build_Submain(){...Build_Sub(1,n,1,n); //初始调用参数,n为树结点总数...}分析:本算法利用了这样一个性质,即一棵子树在前序和中序序列中所占的位置总是连续的.因此,就可以用起始下标和终止下标来确定一棵子树.Pre_Start,Pre_End,In_Start和In_End分别指示子树在前序子序列里的起始下标,终止下标,和在中序子序列里的起始和终止下标.6.66typedef struct{CSNode *ptr;CSNode *lastchild;} NodeMsg; //结点的指针和其最后一个孩子的指针Status Bulid_CSTree_PTree(PTree T)//由树T的双亲表构造其孩子兄弟链表{NodeMsg Treed;for(i=0;i<T.n;i++){Tree[i].ptr=(CSNode*)malloc(sizeof(CSNode));Tree[i].ptr->data=T.node[i].data; //建结点if(T.nodes[i].parent>=0) //不是树根{j=T.nodes[i].parent; //本算法要求双亲表必须是按层序存储if(!(Tree[j].lastchild)) //双亲当前还没有孩子Tree[j].ptr->firstchild=Tree[i].ptr; //成为双亲的第一个孩子else //双亲已经有了孩子Tree[j].lastchild->nextsib=Tree[i].ptr; //成为双亲最后一个孩子的下一个兄弟 Tree[j].lastchild=Tree[i].ptr; //成为双亲的最后一个孩子}//if}//for}//Bulid_CSTree_PTree6.67typedef struct{char data;CSNode *ptr;CSNode *lastchild;} NodeInfo; //结点数据,结点指针和最后一个孩子的指针Status CreateCSTree_Duplet(CSTree &T)//输入二元组建立树的孩子兄弟链表{NodeInfo Treed;n=1;k=0;if(getchar()!='^') return ERROR; //未按格式输入if((c=getchar())=='^') T=NULL; //空树Tree[0].ptr=(CSNode*)malloc(sizeof(CSNode));Tree[0].data=c;Tree[0].ptr->data=c;while((p=getchar())!='^'&&(c=getchar())!='^'){Tree[n].ptr=(CSNode*)malloc(sizeof(CSNode));Tree[n].data=c;Tree[n].ptr->data=c;for(k=0;Tree[k].data!=p;k++); //查找当前边的双亲结点if(Tree[k].data!=p) return ERROR; //未找到:未按层序输入r=Tree[k].ptr;if(!r->firstchild)r->firstchild=Tree[n].ptr;else Tree[k].lastchild->nextsib=Tree[n].ptr;Tree[k].lastchild=Tree[n].ptr; //这一段含义同上一题n++;}//whilereturn OK;}//CreateCSTree_Duplet6.68Status CreateCSTree_Degree(char node[ ],int degree[ ])//由结点的层序序列和各结点的度构造树的孩子兄弟链表{CSNode * ptrd; //树结点指针的辅助存储ptr[0]=(CSNode*)malloc(sizeof(CSNode));i=0;k=1; //i为当前结点序号,k为当前孩子的序号while(node[i]){ptr[i]->data=node[i];d=degree[i];if(d){ptr[k++]=(CSNode*)malloc(sizeof(CSNode)); //k为当前孩子的序号ptr[i]->firstchild=ptr[k]; //建立i与第一个孩子k之间的联系for(j=2;j<=d;j++){ptr[k++]=(CSNode*)malloc(sizeof(CSNode));ptr[k-1]->nextsib=ptr[k]; //当结点的度大于1时,为其孩子建立兄弟链表}//for}//ifi++;}//while}//CreateCSTree_Degree6.69void Print_BiTree(BiTree T,int i)//按树状打印输出二叉树的元素,i表示结点所在层次,初次调用时i=0{if(T->rchild) Print_BiTree(T->rchild,i+1);for(j=1;j<=i;j++) printf(" "); //打印i个空格以表示出层次printf("%c\n",T->data); //打印T元素,换行if(T->lchild) Print_BiTree(T->rchild,i+1);}//Print_BiTree分析:该递归算法实际上是带层次信息的中序遍历,只不过按照题目要求,顺序为先右后左.6.70Status CreateBiTree_GList(BiTree &T)//由广义表形式的输入建立二叉链表{c=getchar();if(c=='#') T=NULL; //空子树else{T=(CSNode*)malloc(sizeof(CSNode));T->data=c;if(getchar()!='(') return ERROR;if(!CreateBiTree_GList(pl)) return ERROR;T->lchild=pl;if(getchar()!=',') return ERROR;if(!CreateBiTree_GList(pr)) return ERROR;T->rchild=pr;if(getchar()!=')') return ERROR; //这些语句是为了保证输入符合A(B,C)的格式 }return OK;}//CreateBiTree_GList6.71void Print_CSTree(CSTree T,int i)//按凹入表形式打印输出树的元素,i表示结点所在层次,初次调用时i=0{for(j=1;j<=i;j++) printf(" "); //留出i个空格以表现出层次printf("%c\n",T->data); //打印元素,换行for(p=T->firstchild;p;p=p->nextsib)Print_CSTree(p,i+1); //打印子树}//Print_CSTree6.72void Print_CTree(int e,int i)//按凹入表形式打印输出树的元素,i表示结点所在层次{for(j=1;j<=i;j++) printf(" "); //留出i个空格以表现出层次printf("%c\n",T.nodes[e].data); //打印元素,换行for(p=T.nodes[e].firstchild;p;p=p->next)Print_CSTree(p->child,i+1); //打印子树}//Print_CSTreemain(){...Print_CTree(T.r,0); //初次调用时i=0...}//main6.73char c; //全局变量,指示当前字符Status CreateCSTree_GList(CSTree &T)//由广义表形式的输入建立孩子兄弟链表{c=getchar();T=(CSNode*)malloc(sizeof(CSNode));T->data=c;if((c=getchar())=='(') //非叶结点{if(!CreateCSTree_GList(fc)) return ERROR; //建第一个孩子T->firstchild=fc;for(p=fc;c==',';p->nextsib=nc,p=nc) //建兄弟链if(!CreateCSTree_GList(nc)) return ERROR;p->nextsib=NULL;if((c=getchar())!=')') return ERROR; //括号不配对}else T->firtchild=NULL; //叶子结点return OK;}//CreateBiTree_GList分析:书后给出了两个间接递归的算法,事实上合成一个算法在形式上可能更好一些.本算法另一个改进之处在于加入了广义表格式是否合法的判断.6.74{printf("%c",T->data);if(T->firstchild) //非叶结点{printf("(");for(p=T->firstchild;p;p=p->nextsib){PrintGlist_CSTree(p);if(p->nextsib) printf(","); //最后一个孩子后面不需要加逗号}printf(")");}//if}//PrintGlist_CSTree6.75char c;int pos=0; //pos是全局变量,指示已经分配到了哪个结点Status CreateCTree_GList(CTree &T,int &i)//由广义表形式的输入建立孩子链表{c=getchar();T.nodes[pos].data=c;i=pos++; //i是局部变量,指示当前正在处理的子树根if((c=getchar())=='(') //非叶结点{CreateCTree_GList();p=(CTBox*)malloc(sizeof(CTBox));T.nodes[i].firstchild=p;p->child=pos; //建立孩子链的头for(;c==',';p=p->next) //建立孩子链{CreateCTree_GList(T,j); //用j返回分配得到的子树根位置p->child=j;p->next=(CTBox*)malloc(sizeof(CTBox));}p->next=NULL;if((c=getchar())!=')') return ERROR; //括号不配对}//ifelse T.nodes[i].firtchild=NULL; //叶子结点return OK;}//CreateBiTree_GList分析:该算法中,pos变量起着"分配"结点在表中的位置的作用,是按先序序列从上向下分配,因此树根T.r一定等于0,而最终的pos值就是结点数T.n.6.76{printf("%c",T.nodes[i].data);if(T.nodes[i].firstchild) //非叶结点{printf("(");for(p=T->firstchild;p;p=p->nextsib){PrintGlist_CSTree(T,p->child);if(p->nextsib) printf(","); //最后一个孩子后面不需要加逗号 }printf(")");}//if}//PrintGlist_CTree。
1.分画出具有3个点的和3个点的二叉的所有不同形。
2.1所得各种形的二叉,分写出前序、中序和后序遍的序列。
3.一棵度k的中有n1个度1的点,n2个度2的点,⋯⋯,nk个度k的点,中有多少个叶子点并明之。
假一棵二叉的先序序列EBADCFHGIKJ,中序序列ABCDEFGHIJK,画出二叉。
5.二叉有50个叶子点,二叉的点数至少有多少个?6.出足以下条件的所有二叉:①前序和后序相同②中序和后序相同③前序和后序相同7.n个点的K叉,假设用具有k个child 域的等点存的一个点,空的Child域有多少个?8.画出与以下序列的T:的先根次序序列GFKDAIEBCHJ;的后根次序序列DIAEKFCJHBG。
9.假用于通的文由8个字母成,字母在文中出的率分:,,,,,,,8个字母哈夫曼。
10.二叉采用二叉表存放,要求返回二叉T的后序序列中的第一个点指,是否可不用且不用来完成?述原因.11.画出和以下的二叉:12.二叉树按照二叉链表方式存储,编写算法,计算二叉树中叶子结点的数目。
13.编写递归算法:对于二叉树中每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间。
14.分别写函数完成:在先序线索二叉树T中,查找给定结点*p在先序序列中的后继。
在后序线索二叉树T中,查找给定结点*p在后序序列中的前驱。
15.分别写出算法,实现在中序线索二叉树中查找给定结点*p在中序序列中的前驱与后继。
16.编写算法,对一棵以孩子-兄弟链表表示的树统计其叶子的个数。
17.对以孩子-兄弟链表表示的树编写计算树的深度的算法。
18.二叉树按照二叉链表方式存储,利用栈的根本操作写出后序遍历非递归的算法。
19.设二叉树按二叉链表存放,写算法判别一棵二叉树是否是一棵正那么二叉树。
正那么二叉树是指:在二叉树中不存在子树个数为 1的结点。
20.计算二叉树最大宽度的算法。
二叉树的最大宽度是指:二叉树所有层中结点个数的最大值。
21.二叉树按照二叉链表方式存储,利用栈的根本操作写出先序遍历非递归形式的算法。
习题61.填空题(1)n个顶点的无向图,最多能有(___________)条边。
答案:[n*(n-1)]/2(2)有n个顶点的强连通图G最多有(___________)条弧。
答案:n*(n-1)(3)有n个顶点的强连通图G至少有(___________)条弧。
答案:n(4)G为无向图,如果从G的某个顶点出发,进行一次广度优先遍历,即可访问图的每个顶点,则该图一定是(___________)图。
答案:连通(5)若采用邻接矩阵结构存储具有n个顶点的图,则对该图进行广度优先遍历的算法时间复杂度为(___________)。
答案:O(n2)(6)n个顶点的连通图的生成树有(___________)条边。
答案:n-1(7)图的深度优先遍历类似于树的(___________)遍历;图的广度优先遍历类似于树的(___________)遍历。
答案:前序层序(8)对于含有n个顶点e条边的连通图,用普里姆算法求最小生成树的时间复杂度为(___________)。
答案:O(n2)(9)已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为(___________)。
答案:O(n+e)(10)一棵具有n个顶点的生成树有且仅有(___________)条边。
答案:n-12.单选题(1)在一个无向图中,所有顶点的度数之和等于所有边数的()倍。
A. 1/2B. 1C. 2D. 4(2)在一个具有n个顶点的有向图中,若所有顶点的出度数之和为S,则所有顶点的度数之和为()。
A. SB. S-1C. S+1D. 2S(3)具有n个顶点的有向图最多有()条边。
A. nB. n(n-1)C. n(n+1)D. 2n(4)若一个图中包含有k个连通分量,若按照深度优先搜索的方法访问所有顶点,则必须调用()次深度优先搜索遍历的算法。
A. kB. 1C. k-1D. k+1(5)若一个图的边集为{<1,2>,<1,4>,<2,5>,<3,1>,<3,5>,<4,3>},则从顶点1开始对该图进行深度优先遍历,得到的顶点序列可能为()。
第六章课后习题6、1、各层的结点数目是:K2、编号为n的结点的双亲结点是:<=(n-2)/k的最大整数3、编号为n的结点的第i个孩子结点编号是:k*(n-1)+1+i4、编号为n的结点有右兄弟的条件是:(n-1)能被k整除右兄弟的编号是:n+1.7、1、先序序列和中序序列相同:空二叉树或没有左子树的二叉树。
2、中序序列和后序序列相同:空二叉树或没有右子树的二叉树。
3、先序序列和后序序列相同:空二叉树或只有根的二叉树。
9、中序序列:BDCEAFHG和后序序列:DECBHGFA的二叉树为:AB FC GD E H先序序列:ABCDEFGH算法设计:3、typedef struct{int data[100];int top;}seqstack;seqstack *s;Perorder(char a[],int n){int i=1,count=1;s->top=-1;if(n==0)return(0);else{if(I<=n){s->top++;s->data[s->top]=a[I];}while(count<n){printf(“%c”,s->data[s->top]);count++;s->top--;if(s->data[s->top]);==a[i]){ printf(“%c”,s->data[s->top]);count++;s->top--;}if((2*i+1)<n){i=2*i;s->top++;s->data[s->top]=a[i+1];s->top++;s->data[s->top]=a[i];}else if(a*i<n){i=2*i;s->top++;s->data[s->top]=a[i];}else if(i/2%2==1)i=i/2/2+1;else i=i/2+1;}}}main(){char A[]=“kognwyuvb”;int n=strlen(A);s=(seqstack *)malloc(sizeof(seqstack)); printf(“\n”);Perorder(A,n);}。