(电信系本科2002级 2003年12月)
姓名 班级 题号 题分 得分
得 分 一 32 二 38 三 30 总分 100 一、回答下列问题 (每题4分,共32分)
1. 对于一个有10000个结点的二叉树,树叶最多有多少个?最少有多少个?
答: 最多是完全二叉树的形态,即5000个叶子;最少是单支树的形态,即1个叶子。
2. 已知一棵二叉树的中序序列和后序序列分别为: DBGEACHF和DGEBHFCA,则该二叉树的前序序列是什么?
答:是:ABDEGCFH
3. 设有1000个无序的元素,需排出前10个最大(小)的元素,你认为采用哪种排序方法最快?为什么? 答:用锦标赛排序或堆排序很合适,因为不必等全部元素排完就能得到所需结果, 时间效率为O(nlog2n); 即O(1000log21000)=O(10000)
锦标赛排序的准确比较次数为:n-1+9log2n=999+9log21000=999+9×10=1089 堆排序的准确比较次数为:n-1+9log2n=999+9log21000=999+9×10=1089
若用冒泡排序也较快,最多耗费比较次数为(n-1+n-2+……+n-10)=10n-55=10000-55=9945(次)
4. 在KMP算法中,已知模式串为ADABCADADA ,请写出模式串的next[j]函数值。 答:
5. 中序遍历的递归算法平均空间复杂度为多少?
答: 要考虑递归时占用了栈空间,但递归次数最多不超过树的高度,所以空间复杂度为O(log2n)
6. 欲将无序序列(24, 79, 13, 36, 70, 96, 12, 10, 36*, 49, 100, 27)中的关键码按
升序重新排列,请写出快速排序第一趟排序的结果序列。另外请画出堆排序(小根堆)的初始堆。
答:①快速排序第一趟排序的结果序列为:10, 12, 13, [24], 70, 96, 36, 79, 36*, 49, 100, 27 (注意要按振荡式逼近算法实现)
② 堆排序的初始堆如下,注意要从排无序堆开始,从最后一个非终端结点开始,自下而上调整,而且要排
24 79 13 36 70 96 12 10 36*49 100 27 成小根堆! 初始堆序列为: 10,24,12,79,49,27,13,36,36*, 70, 100, 96 无序堆 有序初始堆
10 24 12 7. 已知一组关键字为(10, 24, 32, 17, 31, 30, 46, 47, 6349) 79 40 ,49 , 27 ,设哈希函数 13 H(key)=key MOD 13。请写出用线性探测法处理冲突构造所得的哈希表。 36 36*70 100 96 答: 0 49
1 40 2 3 4 17 5 31 6 32 7 30 8 46 9 47 10 10 11 24 12 63 8. 算法复杂度O(1)的含义是什么?
答:它表示与输入的元素规模无关,是一个常数(但不一定是1)。
或:它表示该算法执行时耗费时间的长短或占用辅助空间的多少与元素个数n无关,若能达到这样的时间效率或空间效率,将是最理想的算法。
得 分 二、综合题(4小题,共38分)
1. 下图为某无向图的邻接表,按教材算法7.5和7.6分别写出深度优先搜索和广度优先搜索的结果,并
画出逻辑结构图。 (10分)
1 2 3 4 5 A C D ^ 5 3 2 ^ 7 6 ^ 7 2 ^ B 6 7 E F G H I J
1 3 2 9 8 8 ^ ^ ^ ^
3
^
10 ^ 答:深度优先搜索(DFS)结果为:AEBCFGDHIJ 广度优先搜索(BFS)结果为:AEBCGFDHIJ 这是有着4个连通分量的非连通图。
A E
B C F
G H I
D J
2. 设A~H 8个字符出现的概率为: ={0.10, 0.16, 0.01, 0.02, 0.29, 0.10, 0.07, 0.25},
设计最优二进制码并计算平均码长。如果设计最优三进制编码(即可用0,1,2三种符号进行编码),画出最优三叉树并计算平均码长。 (10分) 答:最优二进制编码不惟一,但WPL惟一。
0 1.00 0 0.45 0.55 0 0.20 0.25 0.26 0.29 0 0.10 0.10 0 0.03 0.07 A 0.10 0.16 0.01 0.02 若按教材算法,合并规律应当如下: A:001 B: 101 C: 00000 D: 00001 E: 11 F: 100 G: 0001 H: 01 平均码长为: ΣPiWi= =3×(0.1+0.16+0.1) +5×(0.01+0.02) +2×(0.29+0.25) +4×0.07 =2.59 3
对三进制编码,由于总共有8个字符,8%3=2,故第一次构建最优树只有2个结点,则最优三叉树为
1.00 0 1 2 0.29 0.51 0 0.20 2 0 0.03 0.07 0.10 0.10 0.16 0.25 0.01 0.02 1.00 0.55 0.45 平均码长为: 0.26 0.29 0.20 0.25 ΣPiWi=1×0.29+2×(0.1+0.16+0.10+0.07+0.25)+ 0.10 0.16 3×(0.01+0.02)=0.29+1.36+0.09=1.74 0.03 0.07 0.10 0.10 0.01 0.02 A:100 B: 001 C: 00000 D: 00001 E: 01 F: 101 G: 0001 H: 11 编码为: A:02 B: 21 C: 000 D: 001 E: 1 F: 20 G: 01 平均码长仍为: H: 22 ΣPiWi=2.59
3. 给定一个由n个关键字不同的记录构成的序列,你能否用2n-3次比较找出n个元素中的最大值和最小
值?如果有,请描述你的方法。最快需多少次比较?(无需写算法) (8分) 答:可以实现。选用锦标赛算法。两两元素比较,淘汰较小的,形如一棵二叉树。树根为最大值(此时用掉n-1次比较?)。而最小者一定位于首次被淘汰之列。故只有 n/2个。一共需n-1+ n/2次比较。
4. 分析下面算法中l和h变量表示什么含义?初始调用时,l和h应取什么值?其中p为指
向二叉树的根结点,如果去掉形参中的“&”符号,会得到什么结果? (10分)
Void ABC(Bitree p, int l, int &h) { if p≠NIL then {l=l+1; if l>h then h=l; ABC(p->Lchild, l,h); ABC(p->Rchild, l,h); } } 此题含义是:求树的深度(h) 但求解方法是从根开始计算层次。 反而比从叶子往上计算要简单。 解:依分析,l、h表示二叉树的层次数和深度。(l之前千万不能加&符号,否则不通) 开始调用时,应为ABC(p, 0, 0)
4
去掉形参中的“&”号,则上次计算的结果不能正确返回。故h不变,得不到正确结果。
这里的int &h应当理解为push形参,每次返回就要return 实参。所以l和h其实是每一层当前的状态。L代表当前结点所在的层数(从根结点计算起);而h代表当前结点所在的深度。 附:教材(习题集?)求深度的函数如下:
int BTreeDepth(Btree *BT) //*BT为二叉树某结点的指针 {int leftdep, rightdep; //设左右两个深度/层次计数器 if(BT==NULL) return(0); //当前结点指针为空则立即返回else { leftdep= BTreeDepth(BT->left); //遍历当前结点左子树 rightdep=BTreeDepth(BT->right); //遍历当前结点右子树 if( leftdep>rightdep)return(leftdep+1); //从叶子计数 else return(rightdep+1); }
} //BTreeDepth
得 分 三、 算法设计题(每题10分,共30分)
顺序表的存储结构为: typedef struct{ 1. 试用C或类C语言编写一高效算法,将一顺序存储的线性表(设元素均为整型量)中所Elemtype v[ ]; 有零元素向表尾集中,其他元素则顺序向表头方向集中。 int length; 解: void SortA(sqlist &L) }L; { int i=0, zerosum =0; 算法的核心部分为:void SortA(sqlist &L) if(L.length==0) return(0); //空表 { int i=0, zerosum =0; else { if(L.length==0) return(0); //空表 for( i=1; i<=L.length; i++) else { {if (L.v[i]<>0) L.v[i- zerosum]= L.v[i]; for( i=1; i<=L.length; i++) else ? zerosum++; {if (L.v[i]<>0) L.v[i- zerosum]= L.v[i]; } else zerosum++;} } for(i=i-zerosum+1; i<=L.length; i++)
5
2. 试编写一个算法,判断一给定的整型数组a[n]是不是一个堆。 解:提示:堆的定义是:ki return(minleap) }; else