收藏 分享(赏)

《c语言数据结构》第6章 树和二叉树 自测卷解答.doc

上传人:weiwoduzun 文档编号:2705161 上传时间:2018-09-25 格式:DOC 页数:15 大小:395.02KB
下载 相关 举报
《c语言数据结构》第6章   树和二叉树 自测卷解答.doc_第1页
第1页 / 共15页
《c语言数据结构》第6章   树和二叉树 自测卷解答.doc_第2页
第2页 / 共15页
《c语言数据结构》第6章   树和二叉树 自测卷解答.doc_第3页
第3页 / 共15页
《c语言数据结构》第6章   树和二叉树 自测卷解答.doc_第4页
第4页 / 共15页
《c语言数据结构》第6章   树和二叉树 自测卷解答.doc_第5页
第5页 / 共15页
点击查看更多>>
资源描述

1、第 6 章 树和二叉树 自测卷解答 姓名 班级 题号 一 二 三 四 五 六 总分题分 10 15 11 20 20 24 100得分一、下面是有关二叉树的叙述,请判断正误(每小题 1 分,共 10 分)( )1. 若二叉树用二叉链表作存贮结构,则在 n 个结点的二叉树链表中只有 n1 个非空指针域。( )2.二叉树中每个结点的两棵子树的高度差等于 1。 ( )3.二叉树中每个结点的两棵子树是有序的。 ( )4.二叉树中每个结点有两棵非空子树或有两棵空子树。 ( ) 5.二叉树中每个结点的关键字值大于其左非空子树(若存在的话)所有结点的关键字值,且小于其右非空子树(若存在的话)所有结点的关键字

2、值。 (应当是二叉排序树的特点)( )6.二叉树中所有结点个数是 2k-1-1,其中 k 是树的深度。 ( )7.二叉树中所有结点,如果不存在非空左子树,则不存在非空右子树。 ( )8.对于一棵非空二叉树,它的根结点作为第一层,则它的第 i 层上最多能有 2i1个结点。 (应 2i-1)( )9.用二叉链表法(link-rlink )存储包含 n 个结点的二叉树,结点的 2n 个指针区域中有 n+1 个为空指针。(正确。用二叉链表存储包含 n 个结点的二叉树,结点共有 2n 个链域。由于二叉树中,除根结点外,每一个结点有且仅有一个双亲,所以只有 n-1 个结点的链域存放指向非空子女结点的指针,

3、还有 n+1 个空指针。 )即有后继链接的指针仅 n-1 个。( )10. 01 年计算机系研题具有 12 个结点的完全二叉树有 5 个度为 2 的结点。最快方法:用叶子数n/26,再求 n2=n0-1=5 二、填空(每空 1 分,共 15 分)1 由个结点所构成的二叉树有 5 种形态。 2. 【计算机研 2000】 一棵深度为 6 的满二叉树有 n1=n2=2k-1-1=31 个分支结点和 26-1 =32 个叶子。注:满二叉树没有度为 1 的结点,所以分支结点数就是二度结点数。3 一棵具有个结点的完全二叉树,它的深度为 9 。( 注:用log 2n+1(2572 k-1)4. 【全国专升本

4、统考题】设一棵完全二叉树有 700 个结点,则共有 350 个叶子结点。答:最快方法:用叶子数n/2350 5. 设一棵完全二叉树具有 1000 个结点,则此完全二叉树有 500 个叶子结点,有 499 个度为 2 的结点,有 1 个结点只有非空左子树,有 0 个结点只有非空右子树。答:最快方法:用叶子数n/2500 ,n 2=n0-1=499。 另外,最后一结点为 2i 属于左叶子,右叶子是空的,所以有 1 个非空左子树。完全二叉树的特点决定不可能有左空右不空的情况,所以非空右子树数0.6. 【严题集 6.7】 一棵含有 n 个结点的 k 叉树,可能达到的最大深度为 n ,最小深度为 2 。

5、答:当 k=1(单叉树)时应该最深,深度 n(层) ;当 k=n-1(k-1 叉树)时应该最浅,深度2(层).(不可能只 1 层,那是只有根结点的情况。教材说是 “完全 k 叉树” ,指的是 kn 的情况。)7. 【96 程试题 1】 二叉树的基本组成部分是:根(N ) 、左子树(L)和右子树(R) 。因而二叉树的遍历次序有六种。最常用的是三种:前序法(即按 N L R 次序) ,后序法(即按 L R N 次序)和中序法(也称对称序法,即按 L N R 次序) 。这三种方法相互之间有关联。若已知一棵二叉树的前序序列是 BEFCGDH,中序序列是 FEBGCHD,则它的后序序列必是 F E G

6、H D C B 。 解:求 D 之法 1:画图(见右图) ,由前序先确定 root,由中序先确定左边的叶子,再慢慢推导) ,由图知,后序序列为 FEGH。 。求 D 之法 2:其实不画图也能快速得出后序序列,只要找到根的位置特征。请看,前序遍历 BEFCGDH 中,根结点在最前面,是 B;则后序遍历中 B 一定在最后面。小结:方法 1:由前序先确定 root,由中序先确定左子树方法 2:递归计算。如 B 在前序序列中第一,中序中在中间(可知左右子树上有哪些元素) ,则在后序中必为最后。如法对 B 的左右子树同样处理,则问题得解。8.【全国专升本统考题】中序遍历的递归算法平均空间复杂度为 O(树

7、的深度 k+1)或O(n) 。9. 【计算机研 2001】 用 5 个权值3, 2, 4, 5, 1 构造的哈夫曼( Huffman)树的带权路径长度是 33 。解:先构造哈夫曼树,得到各叶子的路径长度之后便可求出 WPL(453)2(12)3=33(15)(9) (6)4 5 3 (3)1 2(注:原题为选择题:32 33 34 15)三、单项选择题(每小题 1 分,共 11 分)( C )1 不含任何结点的空树 。()是一棵树; ()是一棵二叉树; ()是一棵树也是一棵二叉树; ()既不是树也不是二叉树( C )2二叉树是非线性数据结构,所以 。()它不能用顺序存储结构存储; ()它不能用

8、链式存储结构存储; ()顺序存储结构和链式存储结构都能存储; ()顺序存储结构和链式存储结构都不能使用 ( A、C )3. 01 年计算机研题 具有 n(n0)个结点的完全二叉树的深度为 。() log 2(n) () log 2(n) () log 2(n) +1 () log 2(n)+1注:x 表示不小于 x 的最小整数; x表示不大于 x 的最大整数,它们与 含义不同!( A )4把一棵树转换为二叉树后,这棵二叉树的形态是 。()唯一的 ()有多种()有多种,但根结点都没有左孩子 ()有多种,但根结点都没有右孩子5. 【94 程 P11】 从供选择的答案中,选出应填入下面叙述 ? 内的

9、最确切的解答,把相应编号写在答卷的对应栏内。树是结点的有限集合,它 A 根结点,记为 T。其余的结点分成为 m(m 0)个 B 的集合 T1,T2,Tm,每个集合又都是树,此时结点 T 称为 Ti 的父结点,T i 称为 T的子结点(1im) 。一个结点的子结点个数为该结点的 C 。供选择的答案A: 有 0 个或 1 个 有 0 个或多个 有且只有 1 个 有 1 个或 1 个以上 B: 互不相交 允许相交 允许叶结点相交 允许树枝结点相交C: 权 维数 次数 序答案:ABC1,1,36. 【95 程 P13】 从供选择的答案中,选出应填入下面叙述 ? 内的最确切的解答,把相应编号写在答卷的对

10、应栏内。二叉树 A 。在完全的二叉树中,若一个结点没有 B ,则它必定是叶结点。每棵树都能惟一地转换成与它对应的二叉树。由树转换成的二叉树里,一个结点 N 的左子女是N 在原树里对应结点的 C ,而 N 的右子女是它在原树里对应结点的 D 。供选择的答案A: 是特殊的树 不是树的特殊形式 是两棵树的总称 有是只有二个根结点的树形结构 B: 左子结点 右子结点 左子结点或者没有右子结点 兄弟CD: 最左子结点 最右子结点 最邻近的右兄弟 最邻近的左兄弟 最左的兄弟 最右的兄弟答案:A= B= C= D 答案:ABCDE2,1,1,3四、简答题(每小题 4 分,共 20 分)1. 【严题集 6.2

11、】一棵度为 2 的树与一棵二叉树有何区别?答:度为 2 的树从形式上看与二叉树很相似,但它的子树是无序的,而二叉树是有序的。即,在一般树中若某结点只有一个孩子,就无需区分其左右次序,而在二叉树中即使是一个孩子也有左右之分。2.01 年计算机研题设如下图所示的二叉树 B 的存储结构为二叉链表,root 为根指针,结点结构为:(lchild,data,rchild) 。其中 lchild,rchild 分别为指向左右孩子的指针,data 为字符型,root 为根指针,试回答下列问题:1. 对下列二叉树 B,执行下列算法 traversal(root),试指出其输出结果;2. 假定二叉树 B 共有

12、n 个结点,试分析算法 traversal(root)的时间复杂度。 (共 8 分)二叉树 B解:这是“先根再左再根再右” ,比前序遍历多打印各结点一次,输出结果为:A B C C E E B A D F F D G G特点:每个结点肯定都会被打印两次;但出现的顺序不同,其规律是:凡是有左子树的结点,必间隔左子树的全部结点后再重复出现;如 A,B,D 等结点。反之马上就会重复出现。如 C,E,F,G 等结点。3. 01 年计算机研题【严题集 6.27】给定二叉树的两种遍历序列,分别是:前序遍历序列:D,A,C,E,B,H,F,G ,I ; 中序遍历序列:D,C,B ,E ,H,A,G,I,F

13、,试画出二叉树 B,并简述由任意二叉树 B 的前序遍历序列和中序遍历序列求二叉树 B 的思想方法。解:方法是:由前序先确定 root,由中序可确定 root 的左、右子树。然后由其左子树的元素集合和右子树的集合对应前序遍历序列中的元素集合,可继续确定 root 的左右孩子。将他们分别作为新的 root,不断递归,则所有元素都将被唯一确定,问题得解。DAC FE GB H IAB DC F GEC 的结点类型定义如下:struct nodechar data;struct node *lchild, rchild;C 算法如下:void traversal(struct node *root)i

14、f (root)printf(“%c”, root-data);traversal(root-lchild);printf(“%c”, root-data);traversal(root-rchild);4.【计算机研 2000】给定如图所示二叉树 T,请画出与其对应的中序线索二叉树。2825 3340 60 08 5455 解:要遵循中序遍历的轨迹来画出每个前驱和后继。中序遍历序列:55 40 25 60 28 08 33 54五、阅读分析题(每题 5 分,共 20 分)1. (P60 4-26 ) 试写出如图所示的二叉树分别按先序、中序、后序遍历时得到的结点序列。答:DLR:ABDFJGK

15、CEHILMLDR: BFJDGKACHELIMLRD:JFKGDBHLMIECA2. (P60 4-27 ) 把如图所示的树转化成二叉树。答:注意全部兄弟之间都要连线(包括度2 的兄弟),并注意原有连线结点一律归入左子树,新添连线结点一律归入右子树。ABE CK F H DL G IM J2825 3340 60 08 54 552825405560330854NILNIL3.【严题集 6.17】阅读下列算法,若有错,改正之。4.【严题集 6.21】画出和下列二叉树相应的森林。答案:注意根右边的子树肯定是森林,而孩子结点的右子树均为兄弟。六、算法设计题(前 5 题中任选 2 题,第 6 题必

16、做,每题 8 分,共 24 分)1.【严题集 6.42】编写递归算法,计算二叉树中叶子结点的数目。解:思路:输出叶子结点比较简单,用任何一种遍历递归算法,凡是左右指针均空者,则为叶子,将其打印出来。可作为实验二内容。BiTree InSucc(BiTree q)/已知 q 是指向中序线索二叉树上某个结点的指针,/本函数返回指向*q 的后继的指针。r=q-rchild; if(!q-rtag) /若 q 内装右孩子,r 不一定为后继结点,需要找到中序遍历 q 的右子树时第一个访问的结点 while(!r-rtag)r=r-rchild; return r; / /ISucc答:这是找结点后继的程

17、序。共有 3 处错误。注:当 rtag1 时说明内装后继指针,可直接返回,第一句无错。当 rtag 0 时说明内装右孩子指针,但孩子未必是后继,需要计算。中序遍历应当先左再根再右,所以应当找左子树直到叶子处。r=r-lchild; 直到 LTag=1; 应改为:while(!r-Ltag)r=r-L child;核心部分为:DLR(liuyu *root) /*中序遍历 递归函数*/if(root!=NULL)if(root-lchild=NULL) printf(“%dn“,root-data);DLR(root-lchild);DLR(root-rchild); return(0);法二:

18、int LeafCount_BiTree(Bitree T)/求二叉树中叶子结点的数目 if(!T) return 0; /空树没有叶子 else if(!T-lchild /叶子结点 else return Leaf_Count(T-lchild)+Leaf_Count(T-rchild);/左子树的叶子数加 上右子树的叶子数 /LeafCount_BiTree 但上机时要先建树! 打印叶子结点值(并求总数)思路:先建树,再从遍历过程中打印结点值并统计。步骤 1 键盘输入序列 12,8,17,11,16,2,13,9,21,4,构成一棵二叉排序树。叶子结点值应该是 4,9,13,21,总数应

19、该是 4.127 172 11 16 21 4 9 13编程: 生成二叉树排序树之后,再中序遍历排序查找结点的完整程序如下: 说明部分为:#include #include typedef struct liuyuint data;struct liuyu *lchild,*rchild;test;liuyu *root;int sum=0;int m=sizeof(test);void insert_data(int x) /*如何生成二叉排序树?参见教材 P43C 程序*/ liuyu *p,*q,*s;s=(test*)malloc(m);s-data=x;s-lchild=NULL;s

20、-rchild=NULL;if(!root)root=s; return;p=root; while(p) /*如何接入二叉排序树的适当位置*/q=p;if(p-data=x)printf(“data already exist! n“);return;else if(xdata)p=p-lchild; else p=p-rchild;if(xdata)q-lchild=s;else q-rchild=s;DLR(liuyu *root) /*中序遍历 递归函数*/if(root!=NULL)if(root-lchild=NULL) printf(“%dn“,root-data);DLR(ro

21、ot-lchild);DLR(root-rchild); return(0);main() /*先生成二叉排序树,再调用中序遍历递归函数进行排序输出*/int i,x;i=1; root=NULL; /*千万别忘了赋初值给 root!*/doprintf(“please input data%d:“,i);i+;scanf(“%d“, /*从键盘采集数据,以-9999 表示输入结束*/if(x=-9999) DLR(root);printf(“nNow output count value:%dn“,sum);return(0); else insert_data(x); /*调用插入数据元素

22、的函数 */while(x!=-9999); return(0);执行结果:若一开始运行就输入-9999,则无叶子输出, sum=0。2.【全国专升本统考题】写出求二叉树深度的算法,先定义二叉树的抽象数据类型。 (10 分)或【严题集 6.44】编写递归算法,求二叉树中以元素值为 x 的结点为根的子树的深度。答;设计思路:只查后继链表指针,若左或右孩子的左或右指针非空,则层次数加 1;否则函数返回。但注意,递归时应当从叶子开始向上计数,否则不易确定层数。 int depth(liuyu*root) /*统计层数*/int d,p; /*注意每一层的局部变量 d,p 都是各自独立的*/p=0;i

23、f(root=NULL)return(p); /*找到叶子之后才开始统计*/else d=depth(root-lchild);if(dp) p=d; /*向上回朔时,要挑出左右子树中的相对大的那个深度值 */d=depth(root-rchild);if(dp)p=d;p=p+1;return(p);法二:int Get_Sub_Depth(Bitree T,int x)/求二叉树中以值为 x 的结点为根的子树深度 if(T-data=x) printf(“%dn“,Get_Depth(T); /找到了值为 x 的结点,求其深度 exit 1; else if(T-lchild) Get_S

24、ub_Depth(T-lchild,x); if(T-rchild) Get_Sub_Depth(T-rchild,x); /在左右子树中继续寻找 /Get_Sub_Depth int Get_Depth(Bitree T)/求子树深度的递归算法 if(!T) return 0; else m=Get_Depth(T-lchild); n=Get_Depth(T-rchild); return (mn?m:n)+1; /Get_Depth 附:上机调试过程步骤 1 键盘输入序列 12,8,17,11,16,2,13,9,21,4,构成一棵二叉排序树。层数应当为 4步骤 2: 执行求深度的函数,

25、并打印统计出来的深度值。完整程序如下:#include #include typedef struct liuyuint data;struct liuyu *lchild,*rchild;test;liuyu *root;int sum=0;int m=sizeof(test);void insert_data(int x) /*如何生成二叉排序树?参见教材 P43C 程序*/ liuyu *p,*q,*s;s=(test*)malloc(m);s-data=x;s-lchild=NULL;s-rchild=NULL;if(!root)root=s; return;p=root; while

26、(p) /*如何接入二叉排序树的适当位置*/q=p;if(p-data=x)printf(“data already exist! n“);return;else if(xdata)p=p-lchild; else p=p-rchild;if(xdata)q-lchild=s;else q-rchild=s;int depth(liuyu*root) /*统计深度*/int d,p; /*注意每一层的局部变量 d,p 都是各自独立的*/p=0;if(root=NULL)return(p); /*找到叶子之后才开始统计*/128 172 11 16 21 4 9 13else d=depth(r

27、oot-lchild);if(dp) p=d; /*向上回朔时,要挑出左右子树中的相对大的那个深度值 */d=depth(root-rchild);if(dp)p=d;p=p+1;return(p);void main() /*先生成二叉排序树,再调用深度遍历递归函数进行统计并输出*/int i,x;i=1; root=NULL; /*千万别忘了赋初值给 root!*/doprintf(“please input data%d:“,i);i+;scanf(“%d“, /*从键盘采集数据,以-9999 表示输入结束*/if(x=-9999) printf(“nNow output depth v

28、alue=%dn“, depth (root); return; else insert_data(x); /*调用插入数据元素的函数 */while(x!=-9999); return;执行结果:3. 【严题集 6.47】编写按层次顺序(同一层自左至右)遍历二叉树的算法。或:按层次输出二叉树中所有结点;解:思路:既然要求从上到下,从左到右,则利用队列存放各子树结点的指针是个好办法。这是一个循环算法,用 while 语句不断循环,直到队空之后自然退出该函数。技巧之处:当根结点入队后,会自然使得左、右孩子结点入队,而左孩子出队时又会立即使得它的左右孩子结点入队,以此产生了按层次输出的效果。lev

29、el(liuyu*T)/* liuyu *T,*p,*q100; 假设 max 已知*/int f,r;f=0; r=0; /*置空队*/r=(r+1)%max;qr=T; /*根结点进队*/while(f!=r) /*队列不空*/f=(f+1%max);p=qf; /*出队*/printf(“%d“,p-data); /*打印根结点*/if(p-lchild)r=(r+1)%max; qr=p-lchild; /*若左子树不空,则左子树进队*/ if(p-rchild)r=(r+1)%max; qr=p-rchild; /*若右子树不空,则右子树进队*/ return(0);法二:void

30、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); /LayerOrder 可以用前面的函数建树,然后调用这个函数来输出。完整程序如下(已上机通过)#include #include #define max 50typedef struct liuyuint data;struct liuyu

31、*lchild,*rchild;test;liuyu *root,*p,*qmax;int sum=0;int m=sizeof(test);void insert_data(int x) /*如何生成二叉排序树?参见教材 P43C 程序*/ liuyu *p,*q,*s;s=(test*)malloc(m);s-data=x;s-lchild=NULL;s-rchild=NULL;if(!root)root=s; return;p=root; while(p) /*如何接入二叉排序树的适当位置*/q=p;if(p-data=x)printf(“data already exist! n“);

32、return;else if(xdata)p=p-lchild; else p=p-rchild;if(xdata)q-lchild=s;else q-rchild=s;level(liuyu*T)/* liuyu *T,*p,*q100; 假设 max 已知*/int f,r;f=0; r=0; /*置空队*/r=(r+1)%max;qr=T; /*根结点进队*/while(f!=r) /*队列不空*/f=(f+1%max);p=qf; /*出队*/printf(“%d“,p-data); /*打印根结点*/if(p-lchild)r=(r+1)%max; qr=p-lchild; /*若左

33、子树不空,则左子树进队*/ if(p-rchild)r=(r+1)%max; qr=p-rchild; /*若右子树不空,则右子树进队*/ return(0);void main() /*先生成二叉排序树,再调用深度遍历递归函数进行统计并输出*/int i,x;i=1; root=NULL; /*千万别忘了赋初值给 root!*/doprintf(“please input data%d:“,i);i+;scanf(“%d“, /*从键盘采集数据,以-9999 表示输入结束*/if(x=-9999) printf(“nNow output data value:n“, level(root);

34、 return; else insert_data(x); /*调用插入数据元素的函数 */while(x!=-9999); return;4. ( P60 4-25)已知一棵具有 n 个结点的完全二叉树被顺序存储于一维数组 A 中,试编写一个算法打印出编号为 i 的结点的双亲和所有的孩子。答:结点 i 的左孩子为 2i,右孩子为 2i+1; 用循环算法打印即可。由于是完全二叉树,不必担心中途会出现孩子为 null 的情况。5.【严题集 6.49】编写算法判别给定二叉树是否为完全二叉树。答:int IsFull_Bitree(Bitree T)/判断二叉树是否完全二叉树,是则返回 1,否则返回

35、 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); /不管孩子是否为空,都入队列 /while return 1; /IsFull_Bitree 分析:该问题可以通过层序遍历的方法来解决 .与 6.47 相比,作了一个修改,不管当前结点 是否有左右孩子,都入队列.这样当树为完全二叉树时,遍历时得到是一个连续的不包含

36、空 指针的序列.反之,则序列中会含有空指针. 6. 【严题集 6.26】假设用于通信的电文仅由 8 个字母组成,字母在电文中出现的频率分别为 0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10。试为这 8 个字母设计哈夫曼编码。使用 07 的二进制表示形式是另一种编码方案。对于上述实例,比较两种方案的优缺点。解:方案 1;哈夫曼编码先将概率放大 100 倍,以方便构造哈夫曼树。w=7,19,2,6,32,3,21,10,按哈夫曼规则:【(2,3) ,6, (7,10)】, 19, 21, 32(100)(40) (60)19 21 32 (28)(17) (11)0

37、 1 0 1 0 119 21 32 0 10 1 0 17 10 6 0 12 37 10 6 (5)2 3方案比较:方案 1 的 WPL2(0.19+0.32+0.21)+4(0.07+0.06+0.10)+5(0.02+0.03)=1.44+0.92+0.25=2.61方案 2 的 WPL3(0.19+0.32+0.21+0.07+0.06+0.10+0.02+0.03)=3结论:哈夫曼编码优于等长二进制编码字母编号对应编码 出现频率1 000 0.072 001 0.193 010 0.024 011 0.065 100 0.326 101 0.037 110 0.218 111 0.10字母编号对应编码 出现频率1 1100 0.072 00 0.193 11110 0.024 1110 0.065 10 0.326 11111 0.037 01 0.218 1101 0.10

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 经营企划

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报