数据结构树和二叉树习题及答案

数据结构树和二叉树习题及答案

文稿归稿存档编号:[KKUY-KKIO69-OTM243-OLUI129-G00I-FDQS58-习题六 树和二叉树 一、单项选择题 1.以下说法错误的是 ( ) A.树形结构的特点是一个结点可以有多个直接前趋 B.线性结构中的一个结点至多只有一个直接后继 C.树形结构可以表达(组织)更复杂的数据 D.树(及一切树形结构)是一种"分支层次"结构 E.任何只含一个结点的集合是一棵树 2.下列说法中正确的是 ( ) A.任何一棵二叉树中至少有一个结点的度为2 B.任何一棵二叉树中每个结点的度都为2 C.任何一棵二叉树中的度肯定等于2 D.任何一棵二叉树中的度可以小于2 3.讨论树、森林和二叉树的关系,目的是为了( ) A.借助二叉树上的运算方法去实现对树的一些运算 B.将树、森林按二叉树的存储方式进行存储 C.将树、森林转换成二叉树 D.体现一种技巧,没有什么实际意义 4.树最适合用来表示 ( ) A.有序数据元素 B.无序数据元素 C.元素之间具有分支层次关系的数据 D.元素之间无联系的数据 5.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是( ) A.9 B.11 C.15 D.不确定 6.设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3。与森林F对应的二叉树根结点的右子树上的结点个数是( )。 A.M1 B.M1+M2 C.M3 D.M2+M3 7.一棵完全二叉树上有1001个结点,其中叶子结点的个数是( ) A. 250 B. 500 C.254 D.505 E.以上答案都不对 8. 设给定权值总数有n 个,其哈夫曼树的结点总数为( ) A.不确定 B.2n C.2n+1 D.2n-1 9.二叉树的第I层上最多含有结点数为( ) A.2I B. 2I-1-1 C. 2I-1 D.2I -1 10.一棵二叉树高度为h,所有结点的度或为0,或为2,则这棵二叉树最少有( )结点 A.2h B.2h-1 C.2h+1 D.h+1 11. 利用二叉链表存储树,则根结点的右指针是( )。 A.指向最左孩子 B.指向最右孩子 C.空 D.非空 12.已知一棵二叉树的前序遍历结果为ABCDEF,中序遍历结果为CBAEDF,则后序遍历的结果为( )。 A.CBEFDA B. FEDCBA C. CBEDFA D.不定 13.已知某二叉树的后序遍历序列是dabec, 中序遍历序列是debac , 它的前序遍历是( )。 A.acbed B.decab C.deabc D.cedba 14.在二叉树结点的先序序列,中序序列和后序序列中,所有叶子结点的先后顺序( ) A.都不相同 B.完全相同 C.先序和中序相同,而与后序不同 D.中序和后序相同,而与先序不同 15.在完全二叉树中,若一个结点是叶结点,则它没( )。 A.左子结点 B.右子结点 C.左子结点和右子结点 D.左子结点,右子结点和兄弟结点 16.在下列情况中,可称为二叉树的是( ) A.每个结点至多有两棵子树的树 B. 哈夫曼树 C.每个结点至多有两棵子树的有序树 D. 每个结点只有一棵右子树 E.以上答案都不对 17. 一棵左右子树均不空的二叉树在先序线索化后,其中空的链域的个数是:( )。 A. 0 B. 1 C. 2 D. 不确定 18. 引入二叉线索树的目的是( ) A.加快查找结点的前驱或后继的速度 B.为了能在二叉树中方便的进行插入与删除 C.为了能方便的找到双亲 D.使二叉树的遍历结果唯一 19.n个结点的线索二叉树上含有的线索数为( ) A.2n B.n-l C.n+l D.n 20.由3 个结点可以构造出多少种不同的二叉树?( ) A.2 B.3 C.4 D.5 21.下面几个符号串编码集合中,不是前缀编码的是( )。 A.{0,10,110,1111} B.{11,10,001,101,0001} C.{00,010,0110,1000} D.{b,c,aa,ac,aba,abb,abc} 22. 一棵有n个结点的二叉树,按层次从上到下,同一层从左到右顺序存储在一维数组A[1..n]中,则二叉树中第i个结点(i从1开始用上述方法编号)的右孩子在数组A中的位置是( ) A.A[2i](2i<=n) B.A[2i+1](2i+1<=n) C.A[i-2] D.条件不充分,无法确定 23、以下说法错误的是 ( ) A.哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近。 B.若一个二叉树的树叶是某子树的中序遍历序列中的第一个结点,则它必是该子树的后序遍历序列中的第一个结点。 C.已知二叉树的前序遍历和后序遍历序列并不能惟一地确定这棵树,因为不知道树的根结点是哪一个。 D.在前序遍历二叉树的序列中,任何结点的子树的所有结点都是直接跟在该结点的之后。 二、判断题(在各题后填写“√”或“×”) 1. 完全二叉树一定存在度为1的结点。( ) 2.对于有N个结点的二叉树,其高度为log2n。( ) 3. 二叉树的遍历只是为了在应用中找到一种线性次序。( ) 4. 一棵一般树的结点的前序遍历和后序遍历分别与它相应二叉树的结点前序遍历和后序遍历是一致的。( ) 5. 用一维数组存储二叉树时,总是以前序遍历顺序存储结点。( ) 6.中序遍历一棵二叉排序树的结点就可得到排好序的结点序列。 ( ) 7.完全二叉树中,若一个结点没有左孩子,则它必是树叶。( ) 8. 二叉树只能用二叉链表表示。( ) 9. 给定一棵树,可以找到唯一的一棵二叉树与之对应。( ) 10. 用链表(llink-rlink)存储包含n个结点的二叉树,结点的2n个指针区域中有n-1个空指针。( ) 11.树形结构中元素之间存在一个对多个的关系。( ) 12.将一棵树转成二叉树,根结点没有左子树。( ) 13.度为二的树就是二叉树。( ) 14. 二叉树中序线索化后,不存在空指针域。( ) 15.霍夫曼树的结点个数不能是偶数。( ) 16.哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近。( ) 三、填空题 1.在二叉树中,指针p所指结点为叶子结点的条件是___ ___。 2.深度为k的完全二叉树至少有___ ____个结点,至多有___ ____个结点。 3.高度为8的完全二叉树至少有______个叶子结点。 4.具有n个结点的二叉树中,一共有________个指针域,其中只有________个用来指向结点的左右孩子,其余的________个指针域为NULL。 5.树的主要遍历方法有________、________、________等三种。 6.一个深度为k的,具有最少结点数的完全二叉树按层次,(同层次从左到右)用自然数依此对结点编号,则编号最小的叶子的序号是__ _;编号是i的结点所在的层次号是_ __(根所在的层次号规定为1层)。 7.如果结点A有 3个兄弟,而且B是A的双亲,则B的度是______。 8.二叉树的先序序列和中序序列相同的条件是___ ___。 9.一个无序序列可以通过构造一棵___ ___树而变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。 10.若一个二叉树的叶子结点是某子树的中序遍历序列中的最后一个结点,则它必是该子树的____ __序列中的最后一个结点。 11.若以{4,5,6,7,8}作为叶子结点的权值构造哈夫曼树,则其带权路径长度是______。 12.以下程序段采用先根遍历方法求二叉树的叶子数,请在横线处填充适当的语句。 Void countleaf(bitreptr t,int *count)/*根指针为t,假定叶子数count的初值为0*/ {if(t!=NULL) {if((t->lchild==NULL)&&(t->rchild==NULL))________; countleaf(t->lchild,&count); ________ } } 13.以下程序是二叉链表树中序遍历的非递归算法,请填空使之完善。二叉树链表的结点类型的定义如下: typedef struct node /*C语言/ {char data; struct node *lchild,*rchild;}*bitree; void vst(bitree bt) /*bt为根结点的指针*/ { bitree p; p=bt; initstack(s); /*初始化栈s为空栈*/ while(p || !empty(s)) /*栈s不为空*/ if(p) { push (s,p); (1)___ ; } /*P入栈*/ else { p=pop(s); printf(“%c”,p->data);(2)__ __; }/*栈顶元素出栈*/ } 14.二叉树存储结构同上题,以下程序为求二叉树深度的递归算法,请填空完善之。 int depth(bitree bt) /*bt为根结点的指针*/ {int hl,hr; if (bt==NULL) return((1)_ __); hl=depth(bt->lchild); hr=depth(bt->rchild);

合集下载

树和二叉树习题数据结构

树和二叉树习题数据结构

习题六树和二叉树一、单项选择题1.以下说法错误的是A.树形结构的特点是一个结点可以有多个直接前趋B.线性结构中的一个结点至多只有一个直接后继C.树形结构可以表达组织更复杂的数据D.树及一切树形结构是一种"分支层次"结构E.任何只含一个结点的集合是一棵树2.下列说法中正确的是A.任何一棵二叉树中至少有一个结点的度为2B.任何一棵二叉树中每个结点的度都为2C.任何一棵二叉树中的度肯定等于2D.任何一棵二叉树中的度可以小于23.讨论树、森林和二叉树的关系,目的是为了A.借助二叉树上的运算方法去实现对树的一些运算B.将树、森林按二叉树的存储方式进行存储C.将树、森林转换成二叉树D.体现一种技巧,没有什么实际意义4.树最适合用来表示A.有序数据元素 B.无序数据元素C.元素之间具有分支层次关系的数据 D.元素之间无联系的数据5.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是A.9 B.11 C.15 D.不确定6.设森林F中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3;与森林F对应的二叉树根结点的右子树上的结点个数是 ;A.M1 B.M1+M2 C.M3 D.M2+M37.一棵完全二叉树上有1001个结点,其中叶子结点的个数是A. 250 B. 500 C.254 D.505 E.以上答案都不对8. 设给定权值总数有n 个,其哈夫曼树的结点总数为A.不确定 B.2n C.2n+1 D.2n-19.二叉树的第I层上最多含有结点数为A.2I B. 2I-1-1 C. 2I-1 D.2I -110.一棵二叉树高度为h,所有结点的度或为0,或为2,则这棵二叉树最少有结点A.2h B.2h-1 C.2h+1 D.h+111. 利用二叉链表存储树,则根结点的右指针是 ;A.指向最左孩子 B.指向最右孩子 C.空 D.非空14.在二叉树结点的先序序列,中序序列和后序序列中,所有叶子结点的先后顺序A.都不相同 B.完全相同C.先序和中序相同,而与后序不同 D.中序和后序相同,而与先序不同15.在完全二叉树中,若一个结点是叶结点,则它没 ;A.左子结点 B.右子结点C.左子结点和右子结点 D.左子结点,右子结点和兄弟结点16.在下列情况中,可称为二叉树的是A.每个结点至多有两棵子树的树B. 哈夫曼树C.每个结点至多有两棵子树的有序树D. 每个结点只有一棵右子树E.以上答案都不对17. 一棵左右子树均不空的二叉树在先序线索化后,其中空的链域的个数是: ;A. 0B. 1C. 2D. 不确定18. 引入二叉线索树的目的是A.加快查找结点的前驱或后继的速度 B.为了能在二叉树中方便的进行插入与删除C.为了能方便的找到双亲 D.使二叉树的遍历结果唯一19.n个结点的线索二叉树上含有的线索数为A.2n B.n-l C.n+l D.n21.下面几个符号串编码集合中,不是前缀编码的是 ;A.{0,10,110,1111} B.{11,10,001,101,0001}C.{00,010,0110,1000} D.{b,c,aa,ac,aba,abb,abc}22. 一棵有n个结点的二叉树,按层次从上到下,同一层从左到右顺序存储在一维数组A1..n中,则二叉树中第i个结点i从1开始用上述方法编号的右孩子在数组A中的位置是A.A2i2i<=n B.A2i+12i+1<=nC.Ai-2 D.条件不充分,无法确定23、以下说法错误的是A.哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近;B.若一个二叉树的树叶是某子树的中序遍历序列中的第一个结点,则它必是该子树的后序遍历序列中的第一个结点;C.已知二叉树的前序遍历和后序遍历序列并不能惟一地确定这棵树,因为不知道树的根结点是哪一个;D.在前序遍历二叉树的序列中,任何结点的子树的所有结点都是直接跟在该结点的之后;二、判断题在各题后填写“√”或“×”1. 完全二叉树一定存在度为1的结点;2.对于有N个结点的二叉树,其高度为logn;23. 二叉树的遍历只是为了在应用中找到一种线性次序;4. 一棵一般树的结点的前序遍历和后序遍历分别与它相应二叉树的结点前序遍历和后序遍历是一致的;5. 用一维数组存储二叉树时,总是以前序遍历顺序存储结点;6.中序遍历一棵二叉排序树的结点就可得到排好序的结点序列;7.完全二叉树中,若一个结点没有左孩子,则它必是树叶;8. 二叉树只能用二叉链表表示;9. 给定一棵树,可以找到唯一的一棵二叉树与之对应;10. 用链表llink-rlink存储包含n个结点的二叉树,结点的2n个指针区域中有n-1个空指针;11.树形结构中元素之间存在一个对多个的关系;12.将一棵树转成二叉树,根结点没有左子树;13.度为二的树就是二叉树;14. 二叉树中序线索化后,不存在空指针域;15.霍夫曼树的结点个数不能是偶数;16.哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近;三、填空题1.在二叉树中,指针p所指结点为叶子结点的条件是___ ___;2.深度为k的完全二叉树至少有___ ____个结点,至多有___ ____个结点;3.高度为8的完全二叉树至少有______个叶子结点;4.具有n个结点的二叉树中,一共有________个指针域,其中只有________个用来指向结点的左右孩子,其余的________个指针域为NULL;5.树的主要遍历方法有________、________、________等三种;6.一个深度为k的,具有最少结点数的完全二叉树按层次,同层次从左到右用自然数依此对结点编号,则编号最小的叶子的序号是__ _;编号是i的结点所在的层次号是_ __根所在的层次号规定为1层;7.如果结点A有 3个兄弟,而且B是A的双亲,则B的度是______;8.二叉树的先序序列和中序序列相同的条件是___ ___;9.一个无序序列可以通过构造一棵___ ___树而变成一个有序序列,构造树的过程即为对无序序列进行排序的过程;10.若一个二叉树的叶子结点是某子树的中序遍历序列中的最后一个结点,则它必是该子树的____ __序列中的最后一个结点;11.若以{4,5,6,7,8}作为叶子结点的权值构造哈夫曼树,则其带权路径长度是______; 12.以下程序段采用先根遍历方法求二叉树的叶子数,请在横线处填充适当的语句;Void countleafbitreptr t,int count/根指针为t,假定叶子数count的初值为0/ {ift=NULL{ift->lchild==NULL&&t->rchild==NULL________;countleaft->lchild,&count;________}}13.以下程序是二叉链表树中序遍历的非递归算法,请填空使之完善;二叉树链表的结点类型的定义如下:typedef struct node /C语言/{char data; struct node lchild,rchild;}bitree;void vstbitree bt /bt为根结点的指针/{ bitree p; p=bt; initstacks; /初始化栈s为空栈/whilep || emptys /栈s不为空/ifp { push s,p; 1___ ; } /P入栈/else { p=pops; printf“%c”,p->data;2__ __; }/栈顶元素出栈/ }14.二叉树存储结构同上题,以下程序为求二叉树深度的递归算法,请填空完善之;int depthbitree bt /bt为根结点的指针/{int hl,hr;if bt==NULL return1_ __;hl=depthbt->lchild; hr=depthbt->rchild;if2_ __ 3_ ____;returnhr+1;}15.将二叉树bt中每一个结点的左右子树互换的C语言算法如下,其中ADD,bt,DEL,EMPTYQ 分别为进队,出队和判别队列是否为空的函数,请填写算法中得空白处,完成其功能;typedef struct node{int data ; struct node lchild, rchild; }btnode;void EXCHANGEbtnode bt{btnode p, q;if bt{ADD,bt;whileEMPTYQ{p=DEL; q=1_ __; p->rchild=2_ __; 3__ _=q;ifp->lchild 4_ __; ifp->rchild 5_ __;}D9.C10.B11. C12.A13.D14.B15.C16.B17. B18. A19.C20.D21.B22. D23.C二、判断题在各题后填写“√”或“×”1. 完全二叉树一定存在度为1的结点;×2. 对于有N个结点的二叉树,其高度为logn;×23. 二叉树的遍历只是为了在应用中找到一种线性次序;√4. 一棵一般树的结点的前序遍历和后序遍历分别与它相应二叉树的结点前序遍历和后序遍历是一致的;×5. 用一维数组存储二叉树时,总是以前序遍历顺序存储结点;×6.中序遍历一棵二叉排序树的结点就可得到排好序的结点序列√7.完全二叉树中,若一个结点没有左孩子,则它必是树叶;√8. 二叉树只能用二叉链表表示;×9. 给定一棵树,可以找到唯一的一棵二叉树与之对应;√10. 用链表llink-rlink存储包含n个结点的二叉树,结点的2n个指针区域中有n-1个空指针;×11.树形结构中元素之间存在一个对多个的关系;√12.将一棵树转成二叉树,根结点没有左子树;×13.度为二的树就是二叉树;×14. 二叉树中序线索化后,不存在空指针域;×15.霍夫曼树的结点个数不能是偶数;√16.哈夫曼树是带权路径长度最短的树,路径上权值较大的结点离根较近;√三、填空题1.p->lchild==null && p->rchlid==null2.12k-1 22k-13.644. 2n n-1 n+15. 先序遍历 后序遍历 中序遍历6..12k-2+1第k 层1个结点,总结点个数是2H-1,其双亲是2H-1/2=2k-22 log2i+17.48.任何结点至多只有右子女的二叉树;9.二叉排序树10.前序11.6912. count++, countleafl->rchile,count13.1 p=p->lchild 6.l 图略; 2前序序列:ABCEDFHGIJ中序序列: E C B H F D J I G A 后序序列: ECHFJIGDBA3图略; H G D ACJ I B F E M P ONKO L7.字符A,B,C,D出现的次数为9,1,5,3;其哈夫曼编码如下A:1,B:000,C:01,D:001五、算法设计题1;判定是否是完全二叉树,可以使用队列,在遍历中利用完全二叉树“若某结点无左子女就不应有右子女”的原则进行判断; BiTree Creat 题目分析后序遍历最后访问根结点,即在递归算法中,根是压在栈底的;采用后序非递归算法,栈中存放二叉树结点的指针,当访问到某结点时,栈中所有元素均为该结点的祖先;本题要找p和q 的最近共同祖先结点r ,不失一般性,设p在q的左边;后序遍历必然先遍历到结点p,栈中元素均为p的祖先;将栈拷入另一辅助栈中;再继续遍历到结点q时,将栈中元素从栈顶开始逐个到辅助栈中去匹配,第一个匹配即相等的元素就是结点p 和q的最近公共祖先;typedef struct{BiTree t;int tag;=bt; stop.tag=0; bt=bt->lchild;} ;for j=top1;j>0;j--if s1j.t==pp {printf“p 和q的最近共同的祖先已找到”;return pp;}}while top=0 && stop.tag==1 top--; ag=1;bt=stop.t->rchild;}题目分析叶子结点只有在遍历中才能知道,这里使用中序递归遍历;设置前驱结点指针pre,初始为空;第一个叶子结点由指针head指向,遍历到叶子结点时,就将它前驱的rchild指针指向它,最后叶子结点的rchild为空;LinkedList head,pre=null; 题目分析删除以元素值x为根的子树,只要能删除其左右子树,就可以释放值为x的根结点,因此宜采用后序遍历;删除值为x结点,意味着应将其父结点的左右子女指针置空,用层次遍历易于找到某结点的父结点;本题要求删除树中每一个元素值为 x的结点的子树,因此要遍历完整棵二叉树;void DeleteXTreeBiTree bt //删除以bt为根的子树{DeleteXTreebt->lchild; DeleteXTreebt->rchild;//删除bt的左子树、右子树freebt; }// DeleteXTree //释放被删结点所占的存储空间void SearchB:Tree bt,ElemType x//在二叉树上查找所有以x为元素值的结点,并删除以其为根的子树{BiTree Q;//Q是存放二叉树结点指针的队列,容量足够大if bt{if bt->data==x {DeleteXTreebt; exit0;}//若根结点的值为x,则删除整棵树 {QueueInitQ; QueueInQ,bt;while QueueEmptyQ{p=QueueOutQ;if p->lchild // 若左子女非空if p->lchild->data==x //左子女结点值为 x,应删除当前结点的左子树 {DeleteXTreep->lchild; p->lchild=null;} //父结点的左子女置空else Enqueue Q,p->lchild;// 左子女入队列if p->rchild // 若右子女非空if p->rchild->data==x //右子女结点值为 x,应删除当前结点的右子树{DeleteXTreep->rchild; p->rchild=null;} //父结点的右子女置空else Enqueue Q,p->rchild;// 右子女入队列}//while}//if bt }//search9.int BTLCBiTree T,int c//对二叉树T的结点计数{if T{c++;BTLCT->lchild,&c; //统计左子树结点BTLCT->rchild,&c; //统计右子树结点} }//结束Count,调用时c=010.1找结点的中序前驱结点BiTNode InPre BiTNode p/在中序线索二叉树中查找p的中序前驱结点,并用pre指针返回结果/ { if p->Ltag= =1 pre = p->LChild; /直接利用线索/else{/在p的左子树中查找“最右下端”结点/for q=p->LChild; q->Rtag= =0; q=q->RChild;pre = q;}return pre;}2找结点的中序后继结点BiTNode InSucc BiTNode p/在中序线索二叉树中查找p的中序后继结点,并用succ指针返回结果/ { if p->Rtag= =1 succ = p->RChild; /直接利用线索/else{/在p的右子树中查找“最左下端”结点/for q=p->RChild; q->Ltag= =0; q=q->LChild;succ= q;}return succ;}3 找结点的先序后继结点BiTNode PreSucc BiTNode p/在先序线索二叉树中查找p的先序后继结点,并用succ指针返回结果/ { if p->Ltag= =0 succ = p->LChild;else succ= p->RChild;return succ;}4 找结点的后序前驱结点BiTNode SuccPre BiTNode p/在后序线索二叉树中查找p的后序前驱结点,并用pre指针返回结果/ { if p->Ltag= =1 pre = p->LChild;else pre= p->RChild;return pre;}。

数据结构-6 树和二叉树

数据结构-6 树和二叉树

第六章树和二叉树一.选择题1. 以下说法错误的是。

A.树形结构的特点是一个结点可以有多个直接前趋B.线性结构中的一个结点至多只有一个直接后继C.树形结构可以表达(组织)更复杂的数据D.树(及一切树形结构)是一种"分支层次"结构2. 如图6-2所示的4 棵二叉树中,不是完全二叉树。

图6-2 4 棵二叉树3. 在线索化二叉树中,t 所指结点没有左子树的充要条件是。

A. t->left == NULLB. t->ltag==1C. t->ltag==1 且t->left==NULL D .以上都不对4. 以下说法错误的是。

A.二叉树可以是空集B.二叉树的任一结点最多有两棵子树C.二叉树不是一种树D.二叉树中任一结点的两棵子树有次序之分5. 以下说法错误的是。

A.完全二叉树上结点之间的父子关系可由它们编号之间的关系来表达B.在三叉链表上,二叉树的求双亲运算很容易实现C.在二叉链表上,求根,求左、右孩子等很容易实现D.在二叉链表上,求双亲运算的时间性能很好6. 如图6-3所示的4 棵二叉树,是平衡二叉树。

图6-3 4 棵二叉树7. 如图6-4所示二叉树的中序遍历序列是。

A. abcdgefB. dfebagcC. dbaefcgD. defbagc图6-4 1 棵二叉树8. 已知某二叉树的后序遍历序列是dabec,中序遍历序列是debac,它的前序遍历序列是。

A. acbedB. decabC. deabcD. cedba9. 如果T2 是由有序树T 转换而来的二叉树,那么T 中结点的前序就是T2 中结点的。

A. 前序B.中序C. 后序D. 层次序10. 某二叉树的前序遍历结点访问顺序是abdgcefh,中序遍历的结点访问顺序是dgbaechf,则其后序遍历的结点访问顺序是。

A. bdgcefhaB. gdbecfhaC. bdgaechfD. gdbehfca11. 将含有83个结点的完全二叉树从根结点开始编号,根为1号,后面按从上到下、从左到右的顺序对结点编号,那么编号为41的双亲结点编号为。

数据结构树和二叉树习题

数据结构树和二叉树习题

数据结构树和二叉树习题一、树的基本概念1.请简要描述树的基本概念及其特点。

答:树是由n(n≥0)个节点组成的有限集合。

其中:-若n=0,则为空树。

-若n>0,则树有且仅有一个称为根的节点,其他节点可以分为多个互不相交的有限集合,每个集合本身又是一棵树,称之为根的子树。

树的特点包括:-每个节点存放的数据可以是同种或不同种的数据类型。

-每个节点最多有一个父节点和多个子节点。

2.请列举树的应用场景。

答:树的应用场景包括但不限于以下几个方面:-文件系统:操作系统中的文件系统通常使用树来组织文件和目录。

-数据库:数据库中的索引通常使用树来存储和组织数据。

-编译原理:编译器使用语法树来解析源代码。

-社交网络:社交网络中的关注和粉丝关系可以表示为树。

二、二叉树3.请定义二叉树。

答:二叉树是一种特殊的树结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。

4.请画出以下二叉树的结构图:A/\BC/\/\DEFG答:以下是该二叉树的结构图:A/\BC/\/\DEFG5.请写出以下二叉树的前序遍历、中序遍历和后序遍历结果:/\23/\45答:-前序遍历结果:1,2,4,5,3-中序遍历结果:4,2,5,1,3-后序遍历结果:4,5,2,3,1三、二叉树的操作6.请实现二叉树的插入操作。

答:以下是二叉树的插入操作的示例代码:```class Node:def __init__(self, value):self.value = valueself.left = Noneself.right = Nonedef insert(root, value):if root is None:root = Node(value)else:if value < root.value:if root.left is None:root.left = Node(value)else:insert(root.left, value)else:if root.right is None:root.right = Node(value)else:insert(root.right, value)```7.请实现二叉树的查找操作。

数据结构二叉树习题含答案

数据结构二叉树习题含答案

第6章树与二叉树1.选择题(1)把一棵树转换为二叉树后,这棵二叉树得形态就是().A。

唯一得B.有多种C.有多种,但根结点都没有左孩子D.有多种,但根结点都没有右孩子(2)由3个结点可以构造出多少种不同得二叉树?()A。

2B.3 C。

4D。

5(3)一棵完全二叉树上有1001个结点,其中叶子结点得个数就是()。

A。

250 B.500 C.254 D.501(4)一个具有1025个结点得二叉树得高h为( ).A。

11 B。

10 C.11至1025之间 D。

10至1024之间(5)深度为h得满m叉树得第k层有( )个结点。

(1=〈k=<h)A。

m k-1 B。

mk-1 C.m h-1 D。

m h—1(6)利用二叉链表存储树,则根结点得右指针就是()。

A.指向最左孩子 B.指向最右孩子 C。

空D.非空(7)对二叉树得结点从1开始进行连续编号,要求每个结点得编号大于其左、右孩子得编号,同一结点得左右孩子中,其左孩子得编号小于其右孩子得编号,可采用( )遍历实现编号。

A。

先序B、中序 C、后序D、从根开始按层次遍历(8)若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树得位置,利用()遍历方法最合适。

A.前序 B.中序 C。

后序 D。

按层次(9)在下列存储形式中,()不就是树得存储形式?A.双亲表示法 B.孩子链表表示法 C.孩子兄弟表示法D.顺序存储表示法(10)一棵非空得二叉树得先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足( )。

A.所有得结点均无左孩子B.所有得结点均无右孩子C.只有一个叶子结点 D.就是任意一棵二叉树(11)某二叉树得前序序列与后序序列正好相反,则该二叉树一定就是( )得二叉树。

A。

空或只有一个结点 B.任一结点无左子树C.高度等于其结点数 D.任一结点无右子树(12)若X就是二叉中序线索树中一个有左孩子得结点,且X不为根,则X得前驱为( )。

A.X得双亲 B。

严蔚敏《数据结构(c语言版)习题集》标准答案树和二叉树文库

严蔚敏《数据结构(c语言版)习题集》标准答案树和二叉树文库

严蔚敏《数据结构(c语言版)习题集》标准答案树和二叉树文库————————————————————————————————作者:————————————————————————————————日期:第六章树和二叉树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->rchild)) 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; //回溯}//Findpath6.49int 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_Triplet6.51Status 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.74void PrintGlist_CSTree(CSTree T)//按广义表形式输出孩子兄弟链表表示的树{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.76void PrintGList_CTree(CTree T,int i)//按广义表形式输出孩子链表表示的树{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_CTree21。

树和二叉树习题及答案

树和二叉树习题及答案

树和二叉树习题及答案一、填空题1、不相交的树的聚集称之为森林。

2、从概念上讲,树与二叉树就是两种不同的数据结构,将树转化为二叉树的基本目的就是_树可采用孩子-兄弟链表(二叉链表)做存储结构,目的就是利用二叉树的已有算法解决树的有关问题。

3、深度为k的完全二叉树至少有2 k-1个结点。

至多有2 k-1个结点,若按自上而下,从左到右次序给结点编号(从1开始),则编号最小的叶子结点的编号就是2 k-2+1。

4、在一棵二叉树中,度为零的结点的个数为n,度为2的结点的个数为n2,则有n= n2+1。

5、一棵二叉树的第i(i≥1)层最多有 2 i-1个结点;一棵有n(n>0)个结点的满二叉树共有(n+1)/2个叶子与(n-1) /2个非终端结点。

6.现有按中序遍历二叉树的结果为abc,问有5种不同形态的二叉树可以得到这一遍历结果。

7、哈夫曼树就是带权路径最小的二叉树。

8、前缀编码就是指任一个字符的编码都不就是另一个字符编码的前缀的一种编码方法,就是设计不等长编码的前提。

9、以给定的数据集合{4,5,6,7,10,12,18}为结点权值构造的Huffman树的加权路径长度就是 165 。

10、树被定义为连通而不具有回路的(无向)图。

11、若一棵根树的每个结点最多只有两个孩子,且孩子又有左、右之分,次序不能颠倒,则称此根树为二叉树。

12、高度为k,且有个结点的二叉树称为二叉树。

2k-1 满13、带权路径长度最小的二叉树称为最优二叉树,它又被称为树。

Huffman14、在一棵根树中,树根就是为零的结点,而为零的结点就是结点。

入度出度树叶15、Huffman树中,结点的带权路径长度就是指由到之间的路径长度与结点权值的乘积。

结点树根16、满二叉树就是指高度为k,且有个结点的二叉树。

二叉树的每一层i上,最多有个结点。

2k-1 2i-1二、单选题1、具有10个叶结点的二叉树中有 (B) 个度为2的结点。

(A)8 (B)9 (C)10 (D)112. 对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,则可采用_(3)次序的遍历实现编号。

数据结构课后习题(第6章)

【课后习题】第6章树和二叉树网络工程2010级()班学号:姓名:一、填空题(每空1分,共16分)1.从逻辑结构看,树是典型的。

2.设一棵完全二叉树具有999个结点,则此完全二叉树有个叶子结点,有个度为2的结点,有个度为1的结点。

3.由n个权值构成的哈夫曼树共有个结点。

4.在线索化二叉树中,T所指结点没有左子树的充要条件是。

5.在非空树上,_____没有直接前趋。

6.深度为k的二叉树最多有结点,最少有个结点。

7.若按层次顺序将一棵有n个结点的完全二叉树的所有结点从1到n编号,那么当i为且小于n时,结点i的右兄弟是结点,否则结点i没有右兄弟。

8.N个结点的二叉树采用二叉链表存放,共有空链域个数为。

9.一棵深度为7的满二叉树有___ ___个非终端结点。

10.将一棵树转换为二叉树表示后,该二叉树的根结点没有。

11.采用二叉树来表示树时,树的先根次序遍历结果与其对应的二叉树的遍历结果是一样的。

12.一棵Huffman树是带权路径长度最短的二叉树,权值的外结点离根较远。

二、判断题(如果正确,在对应位置打“√”,否则打“⨯”。

每题0.5分,共5分)1.对于一棵非空二叉树,它的根结点作为第一层,则它的第i层上最多能有2i-1个结点。

2.二叉树的前序遍历并不能唯一确定这棵树,但是,如果我们还知道该二叉树的根结点是那一个,则可以确定这棵二叉树。

3.一棵树中的叶子结点数一定等于与其对应的二叉树中的叶子结点数。

4.度≤2的树就是二叉树。

5.一棵Huffman树是带权路径长度最短的二叉树,权值较大的外结点离根较远。

6.采用二叉树来表示树时,树的先根次序遍历结果与其对应的二叉树的前序遍历结果是一样的。

7.不存在有偶数个结点的满二叉树。

8.满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树。

9.已知二叉树的前序遍历顺序和中序遍历顺序,可以惟一确定一棵二叉树;10.已知二叉树的前序遍历顺序和后序遍历顺序,不能惟一确定一棵二叉树;三、单项选择(请将正确答案的代号填写在下表对应题号下面。

树和二叉树习题及答案

一、填空题1. 不相交的树的聚集称之为森林。

2. 从概念上讲,树与二叉树是两种不同的数据结构,将树转化为二叉树的基本目的是_树可采用孩子-兄弟链表(二叉链表)做存储结构,目的是利用二叉树的已有算法解决树的有关问题。

3. 深度为k的完全二叉树至少有2 k-1个结点。

至多有2 k-1个结点,若按自上而下,从左到右次序给结点编号(从1开始),则编号最小的叶子结点的编号是2 k-2+1。

4. 在一棵二叉树中,度为零的结点的个数为n,度为2的结点的个数为n2,则有n= n2+1。

5. 一棵二叉树的第i(i≥1)层最多有2 i-1个结点;一棵有n(n>0)个结点的满二叉树共有(n+1)/2个叶子和(n-1) /2个非终端结点。

6.现有按中序遍历二叉树的结果为abc,问有5种不同形态的二叉树可以得到这一遍历结果。

7. 哈夫曼树是带权路径最小的二叉树。

8. 前缀编码是指任一个字符的编码都不是另一个字符编码的前缀的一种编码方法,是设计不等长编码的前提。

9. 以给定的数据集合{4,5,6,7,10,12,18}为结点权值构造的Huffman树的加权路径长度是 165 。

10. 树被定义为连通而不具有回路的(无向)图。

11. 若一棵根树的每个结点最多只有两个孩子,且孩子又有左、右之分,次序不能颠倒,则称此根树为二叉树。

12. 高度为k,且有个结点的二叉树称为二叉树。

2k-1 满13. 带权路径长度最小的二叉树称为最优二叉树,它又被称为树。

Huffman14. 在一棵根树中,树根是为零的结点,而为零的结点是结点。

入度出度树叶15. Huffman树中,结点的带权路径长度是指由到之间的路径长度与结点权值的乘积。

结点树根16. 满二叉树是指高度为k,且有个结点的二叉树。

二叉树的每一层i上,最多有个结点。

2k-1 2i-1二、单选题1. 具有10个叶结点的二叉树中有 (B) 个度为2的结点。

(A)8 (B)9 (C)10 (D)112.对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,则可采用_(3)次序的遍历实现编号。

数据结构二叉树习题含答案

第6章树和二叉树1.选择题(1)把一棵树转换为二叉树后,这棵二叉树的形态是()。

A.唯一的B.有多种C.有多种,但根结点都没有左孩子D.有多种,但根结点都没有右孩子(2)由3 个结点可以构造出多少种不同的二叉树()A.2 B.3 C.4 D.5(3)一棵完全二叉树上有1001个结点,其中叶子结点的个数是()。

A.250 B.500 C.254 D.501(4)一个具有1025个结点的二叉树的高h为()。

…A.11 B.10 C.11至1025之间D.10至1024之间(5)深度为h的满m叉树的第k层有()个结点。

(1=<k=<h)A.m k-1 B.m k-1 C.m h-1D.m h-1(6)利用二叉链表存储树,则根结点的右指针是()。

A.指向最左孩子B.指向最右孩子C.空D.非空(7)对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用()遍历实现编号。

A.先序 B. 中序 C. 后序 D. 从根开始按层次遍历(8)若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,利用()遍历方法最合适。

A.前序B.中序C.后序D.按层次(9)在下列存储形式中,()不是树的存储形式…A.双亲表示法B.孩子链表表示法C.孩子兄弟表示法D.顺序存储表示法(10)一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足()。

A.所有的结点均无左孩子B.所有的结点均无右孩子C.只有一个叶子结点D.是任意一棵二叉树(11)某二叉树的前序序列和后序序列正好相反,则该二叉树一定是()的二叉树。

A.空或只有一个结点B.任一结点无左子树C.高度等于其结点数D.任一结点无右子树(12)若X是二叉中序线索树中一个有左孩子的结点,且X不为根,则X的前驱为()。

A.X的双亲B.X的右子树中最左的结点C.X的左子树中最右结点D.X的左子树中最右叶结点:(13)引入二叉线索树的目的是()。

计算机专业基础综合数据结构树和二叉树历年真题试卷汇编6_真题(含答案与解析)-交互

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

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

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

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

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

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

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

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

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

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

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

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

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