数据结构作业系统_第十章答案
- 格式:doc
- 大小:28.00 KB
- 文档页数:8
参考答案第一章、绪论一、选择题1 B;2 A; 3 B;4 C ;5 C; 6 B;7 C;8 C;9 D;10 B。
二、填空题1、存储;2、无,1,无,1;3、前驱,1,后继,任意多个;4、一对一,一对多,多对多;5、时间复杂度,空间复杂度;6、集合,线性结构,树形结构,图形结构;7、顺序结构,链式结构,索引结构,散列结构;8、顺序。
三、问答题与算法题1、3 ;2、T1 ( n ) = 5n 2 -O ( n ) ; T2 ( n ) = 3 n 2 + O ( n ) ; T3 ( n ) = 8 n 2 + O(log n) ;T4 ( n ) = 1.5 n 2 + O ( n ) 。
T4 ( n ) 较优,T3 ( n )较劣。
3、见课本。
第二章线性表一、选择题1C;2A;3D;4B;5D;6B;7C;8B;9A;10C;11D;12D;13C;14C.二、填空题1、O ( 1 ), O ( n );2、单链表,双链表;3、地址,指针;4、4,2;5、便于访问尾结点和头结点;6、前驱;7、L->next== L且L->prior== L;8、顺序。
三、问答题与算法题1、头指针:结点或头结点的指针变量。
其作用是存放第一个结点或头结点的地址,从头指针出发可以找到链表中所有结点的信息。
头结点:是附加在链表的第一个结点之前的一个特殊结点,其数据域一般不存放信息。
其作用是为了简化运算,将空表与非空表统一起来,将第一个结点与其他结点的处理统一起来。
首结点:是链表的第一个结点。
2、(1)基于空间的考虑。
当要求存储的线性表长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表;反之,当线性表长度变化大,难以估计其存储规模时,采用动态链表作为存储结构为好。
(2)基于时间的考虑。
若线性表的操作主要是进行查找,很少做插入和删除操作时,采用顺序表做存储结构为宜;反之,若需要对线性表进行频繁地插入或删除等的操作时,宜采用链表做存储结构。
题目:在一个图G中,所有顶点的度数之和等于所有边数之和的()倍。
选项A:2
选项B:4
选项C:1/2
选项D:1
答案:2
题目:邻接表是图的一种()。
选项A:链式存储结构
选项B:索引存储结构
选项C:顺序存储结构
选项D:散列存储结构
答案:链式存储结构
题目:如果从无向图的任一顶点出发进行一次深度优先搜索即可访问所有顶点,则该图一定是()。
选项A:完全图
选项B:有回路
选项C:连通图
选项D:一棵树
答案:连通图
题目:下列有关图遍历的说法不正确的是()。
选项A:非连通图不能用深度优先搜索法
选项B:连通图的深度优先搜索是一个递归过程
选项C:图的遍历要求每一顶点仅被访问一次
选项D:图的广度优先搜索中邻接点的寻找具有“先进先出”的特征
答案:非连通图不能用深度优先搜索法
题目:无向图的邻接矩阵是一个()。
选项A:零矩阵
选项B:上三角矩阵
选项C:对角矩阵
选项D:对称矩阵
答案:对称矩阵
题目:图的深度优先遍历算法类似于二叉树的()遍历。
选项A:中序
选项B:后序
选项C:层次
选项D:先序
答案:先序
题目:已知下图所示的一个图,若从顶点V1出发,按深度优先搜索法进行遍历,则可能得到的一种顶点序列为()。
)。
)。
)条边。
选项A:n(n+1)/2
选项B:n(n-1)/2
选项C:n(n-1)
选项D:n(n+1)
答案:n(n-1)/2。
数据结构(C语言版)9-12章练习答案清华大学出版社9-12章数据结构作业答案第九章查找选择题1、对n个元素的表做顺序查找时,若查找每个元素的概率相同,则平均查找长度为( A )A.(n+1)/2 B. n/2 C. n D. [(1+n)*n ]/2 2. 下面关于二分查找的叙述正确的是 ( D )A. 表必须有序,表可以顺序方式存储,也可以链表方式存储B. 表必须有序且表中数据必须是整型,实型或字符型 C. 表必须有序,而且只能从小到大排列 D. 表必须有序,且表只能以顺序方式存储3. 二叉查找树的查找效率与二叉树的( (1)C)有关, 在 ((2)C )时其查找效率最低 (1): A. 高度 B. 结点的多少 C. 树型 D. 结点的位置(2): A. 结点太多 B. 完全二叉树 C. 呈单枝树 D. 结点太复杂。
4. 若采用链地址法构造散列表,散列函数为H(key)=key MOD 17,则需 ((1)A)个链表。
这些链的链首指针构成一个指针数组,数组的下标范围为 ((2)C) (1) A.17 B. 13 C. 16 D. 任意(2) A.0至17 B. 1至17 C. 0至16 D. 1至16判断题1.Hash表的平均查找长度与处理冲突的方法无关。
(错) 2. 若散列表的负载因子α<1,则可避免碰撞的产生。
(错)3. 就平均查找长度而言,分块查找最小,折半查找次之,顺序查找最大。
(错)填空题1. 在顺序表(8,11,15,19,25,26,30,33,42,48,50)中,用二分(折半)法查找关键码值20,需做的关键码比较次数为 4 .算法应用题1. 设有一组关键字{9,01,23,14,55,20,84,27},采用哈希函数:H(key)=key mod7 ,表长为10,用开放地址法的二次探测再散列方法Hi=(H(key)+di) mod 10解决冲突。
要求:对该关键字序列构造哈希表,并计算查找成功的平均查找长度。
1.下列排序算法中,其中( D )是稳定的。
A. 堆排序,冒泡排序B. 快速排序,堆排序C. 直接选择排序,归并排序D. 归并排序,冒泡排序2.有一组数据(15,9,7,8,20,-1,7,4)用快速排序的划分方法进行一趟划分后数据的排序为 ( A )(按递增序)。
A.下面的B,C,D都不对。
B.9,7,8,4,-1,7,15,20C.20,15,8,9,7,-1,4,7 D. 9,4,7,8,7,-1,15,203.下列排序算法中,在每一趟都能选出一个元素放到其最终位置上,并且其时间性能受数据初始特性影响的是:( B )。
A. 直接插入排序B. 快速排序C. 直接选择排序D. 堆排序4.如果只想得到1000个元素组成的序列中第5个最小元素之前的部分排序的序列,用( D )方法最快。
A.起泡排序 B.快速排列 C.Shell排序 D.堆排序 E.简单选择排序5.从未排序序列中依次取出一个元素与已排序序列中的元素依次进行比较,然后将其放在已排序序列的合适位置,该排序方法称为( A )排序法。
A. 插入B. 选择C. 希尔D. 二路归并6. 在排序算法中,每次从未排序的记录中挑出最小(或最大)关键码字的记录,加入到已排序记录的末尾,该排序方法是( A )。
A. 选择B. 冒泡C. 插入D. 堆7. 若用冒泡排序方法对序列{10,14,26,29,41,52}从大到小排序,需进行( C )次比较。
A. 3B. 10C. 15D. 258. 对序列{15,9,7,8,20,-1,4,} 用希尔排序方法排序,经一趟后序列变为{15,-l,4,8,20,9,7}则该次采用的增量是 ( B )A. lB. 4C. 3D. 29. 堆排序是( E )类排序A. 插入B. 交换C. 归并D. 基数E. 选择10.排序方法有许多种,(1)法从未排序的序列中依次取出元素,与已排序序列(初始时为空)中的元素作比较,将其放入已排序序列的正确位置上;(2)法从未排序的序列中挑选元素,并将其依次放入已排序序列(初始时为空)的一端;交换排序方法是对序列中的元素进行一系列比较,当被比较的两元素逆序时,进行交换;(3)和(4)是基于这类方法的两种排序方法,而(4)是比(3)效率更高的方法;(5)法是基于选择排序的一种排序方法,是完全二叉树结构的一个重要应用。
第九章查找一、填空题1.在数据的存放无规律而言的线性表中进行检索的最佳方法是顺序查找(线性查找) 。
2.线性有序表(a i,a2,a3,…,a256)是从小到大排列的,对一个给定的值k,用二分法检索表中与k相等的元素,在查找不成功的情况下,最多需要检索_8 次。
设有100个结点,用二分法查找时,最大比较次数是_7_ ____________ 。
3•假设在有序线性表a[1..2O]上进行折半查找,则比较一次查找成功的结点数为1;比较两次查找成功的结点数为_2 ___________ ;比较四次查找成功的结点数为8 ,其下标从小到大依次是1,3,6,8,11,13,16,19 _ ,平均查找长度为 3.7 。
解:显然,平均查找长度二0( log 2n) <5次(25)。
但具体是多少次,则不应当按照公式ASL =U|°g2(n⑴来计算(即(21 X log 221) /20 = 4.6次并不正确!)。
因为这是在假设n = 2m-1 n 的情况下推导出来的公式。
应当用穷举法罗列:全部元素的查找次数为=(1 + 2X 2+ 4X 3+ 8X 4+ 5X 5)= 74; ASL= 74/20=3.7 !!! 4•折半查找有序表(4, 6,12,20, 28, 38,50,70, 88,100),若查找表中元素20,它将依次与表中元素28 , 6, 12, 20 比较大小。
5. 在各种查找方法中,平均查找长度与结点个数n无关的查找方法是散列查找。
6. 散列法存储的基本思想是由关键字的值决定数据的存储地址。
7. 有一个表长为m的散列表,初始状态为空,现将n (n<m)个不同的关键码插入到散列表中,解决冲突的方法是用线性探测法。
如果这n个关键码的散列地址都相同,贝U探测的总次数是n(n-1)/2= ( 1 土2+…+ n-1 )。
(而任一元素查找次数 < n-1)&设一哈希表表长M为100,用除留余数法构造哈希函数,即H( K) =K MOIP ( P<=M ,为使函数具有较好性能,P应选(97 )9、在各种查找方法中,平均查找长度与结点个数无关的是哈_______10、对线性表进行二分查找时,要求线性表必须以顺序方式存储,且结点按关键字有序排列。
数据结构严蔚敏版第十章答案第十章:图一、概述图是一种非常重要的数据结构,它由节点(顶点)和边组成,用于描述事物之间的关系。
在本章中,我们将学习图的基本概念、表示方法和常用算法。
二、基本概念1. 顶点(节点):图中的一个元素,用于表示一个实体,如人、地点等。
2. 边:连接两个顶点的关系,可以是有向的(箭头指向一个方向)或无向的(没有箭头)。
3. 路径:由一系列顶点和边组成的序列,表示从一个顶点到另一个顶点的通路。
4. 无环图:不存在回路(从一个顶点出发,经过若干边又回到该顶点)的图。
5. 有环图:存在回路的图。
三、表示方法1. 邻接矩阵:使用二维数组来表示图的连接关系,数组的行和列分别对应图中的顶点,数组元素表示边的权重或连接状态。
2. 邻接表:使用链表来表示图的连接关系,每个顶点对应一个链表,链表中存储与该顶点相连的其他顶点。
四、图的遍历1. 深度优先搜索(DFS):从一个顶点开始,沿着一条路径尽可能深入地访问顶点,直到无法继续为止,然后回溯到上一个顶点,继续访问其他路径。
使用栈来实现。
2. 广度优先搜索(BFS):从一个顶点开始,先访问其所有相邻顶点,然后再访问相邻顶点的相邻顶点,以此类推,直到所有顶点都被访问到。
使用队列来实现。
五、最小生成树最小生成树是指在一个连通图中,选择其中的一些边,使得这些边构成一棵树,并且树上所有边的权重之和最小。
常用的算法有Prim算法和Kruskal算法。
六、最短路径最短路径是指从一个顶点到另一个顶点的路径中,路径上所有边的权重之和最小。
常用的算法有Dijkstra算法和Floyd算法。
七、拓扑排序拓扑排序是对有向无环图进行排序的一种算法。
它将图中的顶点按照一定的顺序排列,使得所有的有向边都从前面的顶点指向后面的顶点。
八、关键路径关键路径是指在一个有向无环图中,从开始顶点到结束顶点的最长路径。
关键路径上的活动不能延误,否则将影响整个工程的进度。
九、其他图算法除了上述提到的算法,还有许多其他的图算法,如最大流问题、二分图匹配等。
第九章 查找一、填空题1. 在数据的存放无规律而言的线性表中进行检索的最佳方法是 顺序查找(线性查找) 。
2. 线性有序表(a 1,a 2,a 3,…,a 256)是从小到大排列的,对一个给定的值k ,用二分法检索表中与k 相等的元素,在查找不成功的情况下,最多需要检索 8 次。
设有100个结点,用二分法查找时,最大比较次数是 7 。
3. 假设在有序线性表a[1..20]上进行折半查找,则比较一次查找成功的结点数为1;比较两次查找成功的结点数为 2 ;比较四次查找成功的结点数为 8 ,其下标从小到大依次是1,3,6,8,11,13,16,19______,平均查找长度为 3.7 。
解:显然,平均查找长度=O (log 2n )<5次(25)。
但具体是多少次,则不应当按照公式)1(log 12++=n nn ASL 来计算(即(21×log 221)/20=4.6次并不正确!)。
因为这是在假设n =2m -1的情况下推导出来的公式。
应当用穷举法罗列:全部元素的查找次数为=(1+2×2+4×3+8×4+5×5)=74; ASL =74/20=3.7 !!! 4.折半查找有序表(4,6,12,20,28,38,50,70,88,100),若查找表中元素20,它将依次与表中元素 28,6,12,20 比较大小。
5. 在各种查找方法中,平均查找长度与结点个数n 无关的查找方法是 散列查找 。
6. 散列法存储的基本思想是由 关键字的值 决定数据的存储地址。
7. 有一个表长为m 的散列表,初始状态为空,现将n (n<m )个不同的关键码插入到散列表中,解决冲突的方法是用线性探测法。
如果这n 个关键码的散列地址都相同,则探测的总次数是 n(n-1)/2=( 1+2+…+n-1) 。
(而任一元素查找次数 ≤n-1)8、设一哈希表表长M 为100 ,用除留余数法构造哈希函数,即H (K )=K MOD P (P<=M ), 为使函数具有较好性能,P 应选( 97 )9、在各种查找方法中,平均查找长度与结点个数无关的是哈希查找法 10、对线性表进行二分查找时,要求线性表必须以 顺序 方式存储,且结点按关键字有序排列。
第九章 查找一、填空题1. 在数据的存放无规律而言的线性表中进行检索的最佳方法是 顺序查找(线性查找) 。
2. 线性有序表(a 1,a 2,a 3,…,a 256)是从小到大排列的,对一个给定的值k ,用二分法检索表中与k 相等的元素,在查找不成功的情况下,最多需要检索 8 次。
设有100个结点,用二分法查找时,最大比较次数是 7 。
3. 假设在有序线性表a[1..20]上进行折半查找,则比较一次查找成功的结点数为1;比较两次查找成功的结点数为 2 ;比较四次查找成功的结点数为 8 ,其下标从小到大依次是1,3,6,8,11,13,16,19______,平均查找长度为 3.7 。
解:显然,平均查找长度=O (log 2n )<5次(25)。
但具体是多少次,则不应当按照公式)1(log 12++=n n n ASL 来计算(即(21×log 221)/20=4.6次并不正确!)。
因为这是在假设n =2m -1的情况下推导出来的公式。
应当用穷举法罗列:全部元素的查找次数为=(1+2×2+4×3+8×4+5×5)=74; ASL =74/20=3.7 !!!4.折半查找有序表(4,6,12,20,28,38,50,70,88,100),若查找表中元素20,它将依次与表中元素 28,6,12,20 比较大小。
5. 在各种查找方法中,平均查找长度与结点个数n 无关的查找方法是 散列查找 。
6. 散列法存储的基本思想是由 关键字的值 决定数据的存储地址。
7. 有一个表长为m 的散列表,初始状态为空,现将n (n<m )个不同的关键码插入到散列表中,解决冲突的方法是用线性探测法。
如果这n 个关键码的散列地址都相同,则探测的总次数是 n(n-1)/2=( 1+2+…+n-1) 。
(而任一元素查找次数 ≤n-1)8、设一哈希表表长M 为100 ,用除留余数法构造哈希函数,即H (K )=K MOD P (P<=M ), 为使函数具有较好性能,P 应选( 97 )9、在各种查找方法中,平均查找长度与结点个数无关的是哈希查找法10、对线性表进行二分查找时,要求线性表必须以 顺序 方式存储,且结点按关键字有序排列。
数据结构习题及解答第1章 概述【例1-1】分析以下程序段的时间复杂度。
for(i=0;i<n;i++) for(j=0;j<m;j++) A[i][j]=0;解:该程序段的时间复杂度为O (m*n )。
【例1-2】分析以下程序段的时间复杂度。
i=s=0; ① while(s<n) { i++; ② s+=i; ③ }解:语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O (1)。
语句②和语句③构成while 循环语句的循环体,它们的执行次数由循环控制条件中s 与n 的值确定。
假定循环重复执行x 次后结束, 则语句②和语句③各重复执行了x 次。
其时间复杂度按线性累加规则为O (x )。
此时s 与n 满足关系式:s ≥n ,而s=1+2+3+…+x 。
所以有:1+2+3+…+x ≥n ,可以推出:x=nn 241212811+±-=+±-x 与n 之间满足x=f(n ),所以循环体的时间复杂度为O (n ),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O (n )。
【例1-3】分析以下程序段的时间复杂度。
i=1; ① while(i<=n) i=2*i; ②解:其中语句①的执行次数是1,设语句②的执行次数为f (n ),则有:n n f ≤)(2。
log)得:T(n)=O(n2【例1-4】有如下递归函数fact(n),分析其时间复杂度。
fact(int n){ if(n<=1)return(1);①elsereturn(n*fact(n-1));②}解:设fact(n)的运行时间函数是T(n)。
该函数中语句①的运行时间是O(1),语句②的运行时间是T(n-1)+ O(1),其中O(1)为常量运行时间。
由此可得fact(n)的时间复杂度为O(n)。
习题1一、单项选择题1.数据结构是指(1. A )。
A.数据元素的组织形式B.数据类型C.数据存储结构D.数据定义2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2. C )。
第十章内部排序一、择题1.用直接插入排序法对下面四个表进行(由小到大)排序,比较次数最少的是(B)。
A.(94,32,40,90,80,46,21,69)插32,比2次插40,比2次插90,比2次插80,比3次插46,比4次插21,比7次插69,比4次B.(21,32,46,40,80,69,90,94)插32,比1次插46,比1次插40,比2次插80,比1次插69,比2次插90,比1次插94,比1次C.(32,40,21,46,69,94,90,80)插40,比1次插21,比3次插46,比1次插69,比1次插94,比1次插90,比2次插80,比3次D.(90,69,80,46,21,32,94,40)插69,比2次插80,比2次插46,比4次插21,比5次插32,比5次插94,比1次插40,比6次2.下列排序方法中,哪一个是稳定的排序方法(BD)。
A.希尔排序B.直接选择排序C.堆排序D.冒泡排序下列3题基于如下代码:for(i=2;i<=n;i++){ x=A[i];j=i-1;while(j>0&&A[j]>x){ A[j+1]=A[j];j--;}A[j+1]=x}3.这一段代码所描述的排序方法称作(A)。
A.插入排序B.冒泡排序C.选择排序D.快速排序4.这一段代码所描述的排序方法的平均执行时间为(D)A.O(log2n) B.O(n) C.O(nlog2n) D.O(n2)5.假设这段代码开始执行时,数组A中的元素已经按值的递增次序排好了序,则这段代码的执行时间为(B)。
A.O(log2n) B.O(n) C.O(nlog2n) D.O(n2)6.在快速排序过程中,每次被划分的表(或了表)分成左、右两个子表,考虑这两个子表,下列结论一定正确是(B)。
A.左、右两个子表都已各自排好序B.左边子表中的元素都不大于右边子表中的元素C.左边子表的长度小于右边子表的长度D.左、右两个子表中元素的平均值相等7.对n个记录进行堆排序,最坏情况下的执行时间为(C)。
单选题1.从原理上讲,折半查找法要求查找表中各元素的键值必须是____• A 递增或递减• B 递增• C 递减• D 无序单选题2.关于判定树,下列说法不正确的是____• A 判定树是对有序序列进行二分查找得到的树• B n个结点的判定树的深度为[log2n]+1• C 判定树的叶子结点都在同一层• D 判定树除去最后一层结点以后是满二叉树或空二叉树单选题3.在顺序表{2、5、7、10、14、15、18、23、35、41、52}中,用二分法查找关键码12需做____次关键码比较• A 2• B 3• C 4• D 5单选题4.对线性表进行二分查找时,要求线性表必须____• A 以顺序方式存储• B 以顺序方式存储且元素有序• C 以链式方式存储• D 以链式方式存储且元素有序单选题5.折半查找算法的时间复杂度是____• A O(n2)• B O(n)• C O(log2n)• D O(nlog2n)单选题6.若用二分查找法取得的中间位置元素键值大于被查找值,说明被查找值位于中间值的前面,下次的查找区间为从原开始位置至____• A 该中间位置• B 该中间位置-1• C 该中间位置+1• D 该中间位置/2单选题7.对包含N个元素的散列表进行查找,平均查找长度____• A 为O(log2N)• B 为O(N)• C 不直接依赖于N• D 上述三者都不是单选题8.若构造一棵具有n个结点的二叉排序树,最坏的情况下其深度不会超过____• A n/2• B n• C (n+1)/2• D n+1单选题9.分别以下列序列构造二叉排序树,则与其它几个序列构造的结果不同的是____• A (80,70,60,75,90,85,100,10)• B (80,90,85,70,60,10,75,100)• C (80,90,70,85,10,60,75,100)• D (80,90,100,70,85,60,10,75)单选题10.如果某二叉树的左右子树的高度差的绝对值不大于1,则一定是平衡二叉树• A 正确• B 不正确单选题11.AVL树的任何子树都是AVL树。
单元练习1一.判断题(下列各题,正确的请在前面的括号内打√;错误的打╳)(√)(1)数据的逻辑结构与数据元素本身的内容和形式无关。
(√)(2)一个数据结构是由一个逻辑结构和这个逻辑结构上的一个基本运算集构成的整体。
(ㄨ)(3)数据元素是数据的最小单位。
(ㄨ)(4)数据的逻辑结构和数据的存储结构是相同的。
(ㄨ)(5)程序和算法原则上没有区别,所以在讨论数据结构时可以通用。
(√)(6)从逻辑关系上讲,数据结构主要分为线性结构和非线性结构两类。
(√)(7)数据的存储结构是数据的逻辑结构的存储映像。
(√)(8)数据的物理结构是指数据在计算机内实际的存储形式。
(ㄨ)(9)数据的逻辑结构是依赖于计算机的。
(√)(10)算法是对解题方法和步骤的描述。
二.填空题(1)数据有逻辑结构和存储结构两种结构。
(2)数据逻辑结构除了集合以外,还包括:线性结构、树形结构和图形结构。
(3)数据结构按逻辑结构可分为两大类,它们是线性结构和非线性结构。
(4)树形结构和图形结构合称为非线性结构。
(5)在树形结构中,除了树根结点以外,其余每个结点只有 1 个前趋结点。
(6)在图形结构中,每个结点的前趋结点数和后续结点数可以任意多个。
(7)数据的存储结构又叫物理结构。
(8)数据的存储结构形式包括:顺序存储、链式存储、索引存储和散列存储。
(9)线性结构中的元素之间存在一对一的关系。
(10)树形结构结构中的元素之间存在一对多的关系,(11)图形结构的元素之间存在多对多的关系。
(12)数据结构主要研究数据的逻辑结构、存储结构和算法(或运算)三个方面的内容。
(13)数据结构被定义为(D,R),其中D是数据的有限集合,R是D上的关系的有限集合。
(14)算法是一个有穷指令的集合。
(15)算法效率的度量可以分为事先估算法和事后统计法。
(16)一个算法的时间复杂性是算法输入规模的函数。
(17)算法的空间复杂度是指该算法所耗费的存储空间,它是该算法求解问题规模n 的函数。
② 试以[k+1] 作为监视哨改写教材节中给出的直接插入排序算法。
其中,[1..k] 为待排序记录且k<MAXSIZE。
实现下列函数:void InsertSort(SqList &L);顺序表的类型SqList 定义如下:typedef struct {KeyType key;} RedType;typedef struct {RedType r[MAXSIZE+1]; .} RedType;typedef struct {RedType r[MAXSIZE+1]; .,kp) 是堆,则可以写一个时间复杂度为O(log(n)) 的算法将(k1,k2,...,kp,kp+1) 调整为堆。
试编写"从p=1 起,逐个插入建堆" 的算法,并讨论由此方法建堆的时间复杂度。
实现下列函数:void CreateHeap(HeapType &h, char *s);堆(顺序表)的类型HeapType 定义如下:typedef char KeyType;typedef struct {KeyType key;} RedType;typedef struct {RedType r[MAXSIZE+1];int length;} SqList, HeapType;void CreateHeap(HeapType &h, char *s){int i,j,locate,k;KeyType e;=0;for(i=0;s[i]!='\0';i++){++;[].key=s[i];e=[].key;locate=;k=2;for(j=;k>0;j=j/2,k=j/2){if(e<[k].key){[j].key=[k].key; locate=k;}}[locate].key=e;}}③ 假设定义堆为满足如下性质的完全三叉树:(1) 空树为堆;(2) 根结点的值不小于所有子树根的值,且所有子树均为堆。
1.3计算下列程序中x=x+1的语句频度for(i=1;i<=n;i++)for(j=1;j<=i;j++)for(k=1;k<=j;k++)x=x+1;【解答】x=x+1的语句频度为:T(n)=1+(1+2)+(1+2+3)+……+(1+2+……+n)=n(n+1)(n+2)/61. 4试编写算法,求p n(x)=a0+a1x+a2x2+…….+a n x n的值p n(x0),并确定算法中每一语句的执行次数和整个算法的时间复杂度,要求时间复杂度尽可能小,规定算法中不能使用求幂函数。
注意:本题中的输入为a i(i=0,1,…n)、x和n,输出为P n(x0)。
算法的输入和输出采用下列方法(1)通过参数表中的参数显式传递(2)通过全局变量隐式传递。
讨论两种方法的优缺点,并在算法中以你认为较好的一种实现输入输出。
【解答】(1)通过参数表中的参数显式传递优点:当没有调用函数时,不占用内存,调用结束后形参被释放,实参维持,函数通用性强,移置性强。
缺点:形参须与实参对应,且返回值数量有限。
(2)通过全局变量隐式传递优点:减少实参与形参的个数,从而减少内存空间以及传递数据时的时间消耗缺点:函数通用性降低,移植性差算法如下:通过全局变量隐式传递参数PolyValue(){ int i,n;float x,a[],p;printf(“\nn=”);scanf(“%f”,&n);printf(“\nx=”);scanf(“%f”,&x);for(i=0;i<n;i++)scanf(“%f ”,&a[i]); /*执行次数:n次*/p=a[0];for(i=1;i<=n;i++){ p=p+a[i]*x; /*执行次数:n次*/x=x*x;}printf(“%f”,p);}算法的时间复杂度:T(n)=O(n)通过参数表中的参数显式传递float PolyValue(float a[ ], float x, int n){float p,s;int i;p=x;s=a[0];for(i=1;i<=n;i++){s=s+a[i]*p; /*执行次数:n次*/p=p*x;}return(p);}算法的时间复杂度:T(n)=O(n)2.7试分别以不同的存储结构实现单线表的就地逆置算法,即在原表的存储空间将线性表(a1,a2,…,a n)逆置为(a n,a n-1,…,a1)。
第九章 查找一、填空题1. 在数据的存放无规律而言的线性表中进行检索的最佳方法是 顺序查找(线性查找) 。
2. 线性有序表(a 1,a 2,a 3,…,a 256)是从小到大排列的,对一个给定的值k ,用二分法检索表中与k 相等的元素,在查找不成功的情况下,最多需要检索 8 次。
设有100个结点,用二分法查找时,最大比较次数是 7 。
3. 假设在有序线性表a[1..20]上进行折半查找,则比较一次查找成功的结点数为1;比较两次查找成功的结点数为 2 ;比较四次查找成功的结点数为 8 ,其下标从小到大依次是1,3,6,8,11,13,16,19______,平均查找长度为 3.7 。
解:显然,平均查找长度=O (log 2n )<5次(25)。
但具体是多少次,则不应当按照公式)1(log 12++=n n n ASL 来计算(即(21×log 221)/20=4.6次并不正确!)。
因为这是在假设n =2m -1的情况下推导出来的公式。
应当用穷举法罗列:全部元素的查找次数为=(1+2×2+4×3+8×4+5×5)=74; ASL =74/20=3.7 !!!4.折半查找有序表(4,6,12,20,28,38,50,70,88,100),若查找表中元素20,它将依次与表中元素 28,6,12,20 比较大小。
5. 在各种查找方法中,平均查找长度与结点个数n 无关的查找方法是 散列查找 。
6. 散列法存储的基本思想是由 关键字的值 决定数据的存储地址。
7. 有一个表长为m 的散列表,初始状态为空,现将n (n<m )个不同的关键码插入到散列表中,解决冲突的方法是用线性探测法。
如果这n 个关键码的散列地址都相同,则探测的总次数是 n(n-1)/2=( 1+2+…+n-1) 。
(而任一元素查找次数 ≤n-1)8、设一哈希表表长M 为100 ,用除留余数法构造哈希函数,即H (K )=K MOD P (P<=M ), 为使函数具有较好性能,P 应选( 97 )9、在各种查找方法中,平均查找长度与结点个数无关的是哈希查找法10、对线性表进行二分查找时,要求线性表必须以 顺序 方式存储,且结点按关键字有序排列。
第十章内部排序10.23void Insert_Sort1(SqList &L)//监视哨设在高下标端的插入排序算法{k=L.length;for(i=k-1;i;--i) //从后向前逐个插入排序if(L.r[i].key>L.r[i+1].key){L.r[k+1].key=L.r[i].key; //监视哨for(j=i+1;L.r[j].key>L.r[i].key;++j)L.r[j-1].key=L.r[j].key; //前移L.r[j-1].key=L.r[k+1].key; //插入}}//Insert_Sort110.24void BiInsert_Sort(SqList &L)//二路插入排序的算法{int d[MAXSIZE]; //辅助存储x=L.r.key;d=x;first=1;final=1;for(i=2;i<=L.length;i++){if(L.r[i].key>=x) //插入前部{for(j=final;d[j]>L.r[i].key;j--)d[j+1]=d[j];d[j+1]=L.r[i].key;final++;}else //插入后部{for(j=first;d[j]<L.r[i].key;j++)d[j-1]=d[j];d[(j-2)%MAXSIZE+1]=L.r[i].key;first=(first-2)%MAXSIZE+1; //这种形式的表达式是为了兼顾first=1的情况 }}//forfor(i=first,j=1;d[i];i=i%MAXSIZE+1,j++)//将序列复制回去L.r[j].key=d[i];}//BiInsert_Sortvoid SLInsert_Sort(SLList &L)//静态链表的插入排序算法{L.r[0].key=0;L.r[0].next=1;L.r[1].next=0; //建初始循环链表for(i=2;i<=L.length;i++) //逐个插入{p=0;x=L.r[i].key;while(L.r[L.r[p].next].key<x&&L.r[p].next)p=L.r[p].next;q=L.r[p].next;L.r[p].next=i;L.r[i].next=q;}//forp=L.r[0].next;for(i=1;i<L.length;i++) //重排记录的位置{while(p<i) p=L.r[p].next;q=L.r[p].next;if(p!=i){L.r[p]<->L.r[i];L.r[i].next=p;}p=q;}//for}//SLInsert_Sort10.26void Bubble_Sort1(int a[ ],int n)//对包含n个元素的数组a进行改进的冒泡排序{change=n-1; //change指示上一趟冒泡中最后发生交换的元素while(change){for(c=0,i=0;i<change;i++)if(a[i]>a[i+1]){a[i]<->a[i+1];c=i+1; //c指示这一趟冒泡中发生交换的元素}change=c;}//while}//Bubble_Sort1void Bubble_Sort2(int a[ ],int n)//相邻两趟是反方向起泡的冒泡排序算法{low=0;high=n-1; //冒泡的上下界change=1;while(low<high&&change){change=0;for(i=low;i<high;i++) //从上向下起泡if(a[i]>a[i+1]){a[i]<->a[i+1];change=1;}high--; //修改上界for(i=high;i>low;i--) //从下向上起泡if(a[i]<a[i-1]){a[i]<->a[i-1];change=1;}low++; //修改下界}//while}//Bubble_Sort210.28void Bubble_Sort3(int a[ ],int n)//对上一题的算法进行化简,循环体中只包含一次冒泡{int b[ 3 ]; //b[0]为冒泡的下界,b[ 2 ]为上界,b[1]无用d=1;b[0]=0;b[ 2 ]=n-1; //d为冒泡方向的标识,1为向上,-1为向下change=1;while(b[0]<b[ 2 ]&&change){change=0;for(i=b[1-d];i!=b[1+d];i+=d) //统一的冒泡算法if((a[i]-a[i+d])*d>0) //注意这个交换条件{a[i]<->a[i+d];change=1;}b[1+d]-=d; //修改边界d*=-1; //换个方向}//Bubble_Sort310.29void OE_Sort(int a[ ],int n)//奇偶交换排序的算法{change=1;while(change){change=0;for(i=1;i<n-1;i+=2) //对所有奇数进行一趟比较if(a[i]>a[i+1]){a[i]<->a[i+1];change=1;}for(i=0;i<n-1;i+=2) //对所有偶数进行一趟比较if(a[i]>a[i+1]){a[i]<->a[i+1];change=1;}}//while}//OE_Sort分析:本算法的结束条件是连续两趟比较无交换发生10.30typedef struct {int low;int high;} boundary; //子序列的上下界类型void QSort_NotRecurve(int SQList &L)//快速排序的非递归算法{low=1;high=L.length;InitStack(S); //S的元素为boundary类型while(low<high&&!StackEmpty(S)) //注意排序结束的条件{if(high-low>2) //如果当前子序列长度大于3且尚未排好序 {pivot=Partition(L,low,high); //进行一趟划分if(high-pivot>pivot-low){Push(S,{pivot+1,high}); //把长的子序列边界入栈high=pivot-1; //短的子序列留待下次排序}else{Push(S,{low,pivot-1});low=pivot+1;}}//ifelse if(low<high&&high-low<3)//如果当前子序列长度小于3且尚未排好序{Easy_Sort(L,low,high); //直接进行比较排序low=high; //当前子序列标志为已排好序}else //如果当前子序列已排好序但栈中还有未排序的子序列{Pop(S,a); //从栈中取出一个子序列low=a.low;high=a.high;}}//while}//QSort_NotRecurveint Partition(SQList &L,int low,int high)//一趟划分的算法,与书上相同{L.r[0]=L.r[low];pivotkey=L.r[low].key;while(low<high){while(low<high&&L.r[high].key>=pivotkey)high--;L.r[low]=L.r[high];while(low<high&&L.r[low].key<=pivotkey)low++;L.r[high]=L.r[low];}//whileL.r[low]=L.r[0];return low;}//Partitionvoid Easy_Sort(SQList &L,int low,int high)//对长度小于3的子序列进行比较排序{if(high-low==1) //子序列只含两个元素if(L.r[low].key>L.r[high].key) L.r[low]<->L.r[high];else //子序列含有三个元素{if(L.r[low].key>L.r[low+1].key) L.r[low]<->L.r[low+1];if(L.r[low+1].key>L.r[high].key) L.r[low+1]<->L.r[high];if(L.r[low].key>L.r[low+1].key) L.r[low]<->L.r[low+1];}}//Easy_Sort10.31void Divide(int a[ ],int n)//把数组a中所有值为负的记录调到非负的记录之前{low=0;high=n-1;while(low<high){while(low<high&&a[high]>=0) high--; //以0作为虚拟的枢轴记录a[low]<->a[high];while(low<high&&a[low]<0) low++;a[low]<->a[high];}}//Divide10.32typedef enum {RED,WHITE,BLUE} color; //三种颜色void Flag_Arrange(color a[ ],int n)//把由三种颜色组成的序列重排为按照红,白,蓝的顺序排列{i=0;j=0;k=n-1;while(j<=k)switch(a[j]){case RED:a[i]<->a[j];i++;j++;break;case WHITE:j++;break;case BLUE:a[j]<->a[k];k--; //这里没有j++;语句是为了防止交换后a[j]仍为蓝色的情况}}//Flag_Arrange分析:这个算法中设立了三个指针.其中,j表示当前元素;i以前的元素全部为红色;k以后的元素全部为蓝色.这样,就可以根据j的颜色,把其交换到序列的前部或者后部.10.33void LinkedList_Select_Sort(LinkedList &L)//单链表上的简单选择排序算法{for(p=L;p->next->next;p=p->next){q=p->next;x=q->data;for(r=q,s=q;r->next;r=r->next) //在q后面寻找元素值最小的结点if(r->next->data<x){x=r->next->data;s=r;}if(s!=q) //找到了值比q->data更小的最小结点s->next{p->next=s->next;s->next=q;t=q->next;q->next=p->next->next;p->next->next=t;} //交换q和s->next两个结点}//for}//LinkedList_Select_Sort10.34void Build_Heap(Heap &H,int n)//从低下标到高下标逐个插入建堆的算法{for(i=2;i<n;i++){ //此时从H.r[1]到H.r[i-1]已经是大顶堆j=i;while(j!=1) //把H.r[i]插入{k=j/2;if(H.r[j].key>H.r[k].key)H.r[j]<->H.r[k];j=k;}}//for}//Build_Heap10.35void TriHeap_Sort(Heap &H)//利用三叉树形式的堆进行排序的算法{for(i=H.length/3;i>0;i--)Heap_Adjust(H,i,H.length);for(i=H.length;i>1;i--){H.r[1]<->H.r[i];Heap_Adjust(H,1,i-1);}}//TriHeap_Sortvoid Heap_Adjust(Heap &H,int s,int m)//顺序表H中,H.r[s+1]到H.r[m]已经是堆,把H.r[s]插入并调整成堆{rc=H.r[s];for(j=3*s-1;j<=m;j=3*j-1){if(j<m&&H.r[j].key<H.r[j+1].key) j++;if(j<m&&H.r[j].key<H.r[j+1].key) j++;H.r[s]=H.r[j];s=j;}H.r[s]=rc;}//Heap_Adjust分析:本算法与课本上的堆排序算法相比,只有两处改动:1.建初始堆时,i的上限从H.length/3开始(为什么?) 2.调整堆的时候,要从结点的三个孩子结点中选择最大的那一个,最左边的孩子的序号的计算公式为j=3*s-1(为什么?)10.36void Merge_Sort(int a[ ],int n)//归并排序的非递归算法{for(l=1;l<n;l*=2) //l为一趟归并段的段长for(i=0;(2*i-1)*l<n;i++) //i为本趟的归并段序号{start1=2*l*i; //求出待归并的两段的上下界end1=start1+l-1;start2=end1+1;end2=(start2+l-1)>(n-1)?(n-1):(start2+l-1);//注意end2可能超出边界Merge(a,start1,end1,start2,end2); //归并}}//Merge_Sortvoid Merge(int a[ ],int s1,int e1,int s2,int e2)//将有序子序列a[s1]到a[e1]和a[s2]到a[e2]归并为有序序列a[s1]到a[e2]{int b[MAXSIZE]; //设立辅助存储数组bfor(i=s1,j=s2,k=s1;i<=e1&&j<=e2;k++){if(a[i]<a[j]) b[k]=a[i++];else b[k]=a[j++];}while(i<=e1) b[k++]=a[i++];while(j<=e2) b[k++]=a[j++]; //归并到b中for(i=s1;i<=e2;i++) //复制回去a[i]=b[i];}//Merge10.37void LinkedList_Merge_Sort1(LinkedList &L)//链表结构上的归并排序非递归算法{for(l=1;l<L.length;l*=2) //l为一趟归并段的段长for(p=L->next,e2=p;p->next;p=e2){for(i=1,q=p;i<=l&&q->next;i++,q=q->next);e1=q;for(i=1;i<=l&&q->next;i++,q=q->next);e2=q; //求出两个待归并子序列的尾指针if(e1!=e2) LinkedList_Merge(L,p,e1,e2); //归并}}//LinkedList_Merge_Sort1void LinkedList_Merge(LinkedList &L,LNode *p,LNode *e1,LNode *e2)//对链表上的子序列进行归并,第一个子序列是从p->next到e1,第二个是从e1->next到e2 {q=p->next;r=e1->next; //q和r为两个子序列的起始位置while(q!=e1->next&&r!=e2->next){if(q->data<r->data) //选择关键字较小的那个结点接在p的后面{p->next=q;p=q;q=q->next;}else{p->next=r;p=r;r=r->next;}}//whilewhile(q!=e1->next) //接上剩余部分{p->next=q;p=q;q=q->next;}while(r!=e2->next){p->next=r;p=r;r=r->next;}}//LinkedList_Merge10.38void LinkedList_Merge_Sort2(LinkedList &L)//初始归并段为最大有序子序列的归并排序,采用链表存储结构{LNode *end[MAXSIZE]; //设立一个数组来存储各有序子序列的尾指针for(p=L->next->next,i=0;p;p=p->next) //求各有序子序列的尾指针if(!p->next||p->data>p->next->data) end[i++]=p;while(end[0]->next) //当不止一个子序列时进行两两归并{j=0;k=0; //j:当前子序列尾指针存储位置;k:归并后的子序列尾指针存储位置for(p=L->next,e2=p;p->next;p=e2) //两两归并所有子序列{e1=end[j];e2=end[j+1]; //确定两个子序列if(e1->next) LinkedList_Merge(L,p,e1,e2); //归并end[k++]=e2; //用新序列的尾指针取代原来的尾指针j+=2; //转到后面两个子序列}}//while}//LinkedList_Merge_Sort2void LinkedList_Merge(LinkedList &L,LNode *p,LNode *e1,LNode *e2)//对链表上的子序列进行归并,第一个子序列是从p->next到e1,第二个是从e1->next到e2 {q=p->next;r=e1->next;while(q!=e1->next&&r!=e2->next){if(q->data<r->data){p->next=q;p=q;q=q->next;}else{p->next=r;p=r;r=r->next;}}//whilewhile(q!=e1->next){p->next=q;p=q;q=q->next;}while(r!=e2->next){p->next=r;p=r;r=r->next;}}//LinkedList_Merge,与上一题完全相同10.39void SL_Merge(int a[ ],int l1,int l2)//把长度分别为l1,l2且l1^2<(l1+l2)的两个有序子序列归并为有序序列{start1=0;start2=l1; //分别表示序列1和序列2的剩余未归并部分的起始位置for(i=0;i<l1;i++) //插入第i个元素{for(j=start2;j<l1+l2&&a[j]<a[start1+i];j++); //寻找插入位置k=j-start2; //k为要向右循环移动的位数RSh(a,start1,j-1,k);//将a[start1]到a[j-1]之间的子序列循环右移k位start1+=k+1;start2=j; //修改两序列尚未归并部分的起始位置}}//SL_Mergevoid RSh(int a[ ],int start,int end,int k)//将a[start]到a[end]之间的子序列循环右移k 位,算法原理参见5.18{len=end-start+1;for(i=1;i<=k;i++)if(len%i==0&&k%i==0) p=i; //求len和k的最大公约数pfor(i=0;i<p;i++) //对p个循环链分别进行右移{j=start+i;l=start+(i+k)%len;temp=a[j];while(l!=start+i){a[j]=temp;temp=a[l];a[l]=a[j];j=l;l=start+(j-start+k)%len; //依次向右移}a[start+i]=temp;}//for}//RSh10.40书后给出的解题思路在表述上存在问题,无法理解.比如说,"把第一个序列划分为两个子序列,使其中的第一个子序列含有s1个记录,0<=s1<s,第二个子序列有s个记录."可是题目中并没有说明,第一个序列的长度<2s.请会做的朋友提供解法.10.41void Hash_Sort(int a[ ])//对1000个关键字为四位整数的记录进行排序{int b[10000];for(i=0;i<1000;i++) //直接按关键字散列{for(j=a[i];b[j];j=(j+1)%10000);b[j]=a[i];}for(i=0,j=0;i<1000;j++) //将散列收回a中if(b[j]){for(x=b[j],k=j;b[k];k=(k+1)%10000)if(b[k]==x){a[i++]=x;b[k]=0;}}//if}//Hash_Sort10.42typedef struct {int gt; //大于该记录的个数int lt; //小于该记录的个数} place; //整个序列中比某个关键字大或小的记录个数int Get_Mid(int a[ ],int n)//求一个序列的中值记录的位置{place b[MAXSIZE];for(i=0;i<n;i++) //对每一个元素统计比它大和比它小的元素个数gt和ltfor(j=0;j<n;j++){if(a[j]>a[i]) b[i].gt++;else if(a[j]<a[i]) b[i].lt++;}mid=0;min_dif=abs(b[0].gt-b[0].lt);for(i=0;i<n;i++) //找出gt值与lt值最接近的元素,即为中值记录if(abs(b[i].gt-b[i].lt)<min_dif) mid=i;return mid;}//Get_Mid10.43void Count_Sort(int a[ ],int n)//计数排序算法{int c[MAXSIZE];for(i=0;i<n;i++) //对每一个元素{for(j=0,count=0;j<n;j++) //统计关键字比它小的元素个数if(a[j]<a[i]) count++:c[i]=count;}for(i=0;i<n;i++) //依次求出关键字最小,第二小,...,最大的记录{min=0;for(j=0;j<n;j++)if(c[j]<c[min]) min=j; //求出最小记录的下标mina[i]<->a[min]; //与第i个记录交换c[min]=INFINITY; //修改该记录的c值为无穷大以便下一次选取}}//Count_Sort10.44void Enum_Sort(int a[ ],int n)//对关键字只能取v到w之间任意整数的序列进行排序{int number[w+1],pos[w+1];for(i=0;i<n;i++) number[a[i]]++; //计数for(pos[0]=0,i=1;i<n;i++)pos[i]=pos[i-1]+num[i]; //pos数组可以把关键字的值映射为元素在排好的序列中的位置for(i=0;i<n;i++) //构造有序数组cc[pos[a[i]]++]=a[i];for(i=0;i<n;i++)a[i]=c[i];}//Enum_Sort分析:本算法参考了第五章三元组稀疏矩阵转置的算法思想,其中的pos数组和那里的cpot数组起的是相类似的作用.10.45typedef enum {0,1,2,3,4,5,6,7,8,9} digit; //个位数类型typedef digit[3] num; //3位自然数类型,假设低位存储在低下标,高位存储在高下标void Enum_Radix_Sort(num a[ ],int n)//利用计数实现基数排序,其中关键字为3位自然数,共有n个自然数{int number ,pos ;num c[MAXSIZE];for(j=0;j<3;j++) //依次对个位,十位和百位排序{for(i=0;i<n;i++) number[a[i][j]]++; //计数for(pos[0]=0,i=1;i<n;i++)pos[i]=pos[i-1]+num[i]; //把关键字的值映射为元素在排好的序列中的位置for(i=0;i<n;i++) //构造有序数组cc[pos[a[i][j]]++]=a[i];for(i=0;i<n;i++)a[i]=c[i];}//for}//Enum_Radix_Sort分析:计数排序是一种稳定的排序方法.正因为如此,它才能够被用来实现基数排序.10.46typedef struct {int key;int pos;} Shadow; //影子序列的记录类型void Shadow_Sort(Rectype b[ ],Rectype &a[ ],int n)//对元素很大的记录序列b进行排序,结果放入a中,不移动元素{Shadow d[MAXSIZE];for(i=0;i<n;i++) //生成影子序列{d[i].key=b[i].key;d[i].pos=i;}for(i=n-1,change=1;i>1&&change;i--) //对影子序列执行冒泡排序 {change=0;for(j=0;j<i;j++)if(d[j].key>d[j+1].key){d[j]<->d[j+1];change=1;}}//forfor(i=0;i<n;i++) //按照影子序列里记录的原来位置复制原序列 a[i]=b[d[i].pos];}//Shadow_Sort。
第10章排序一、选择题1.某内排序方法的稳定性是指( )。
【南京理工大学 1997 一、10(2分)】A.该排序算法不允许有相同的关键字记录 B.该排序算法允许有相同的关键字记录C.平均时间为0(n log n)的排序方法 D.以上都不对2.下面给出的四种排序法中( )排序法是不稳定性排序法。
【北京航空航天大学 1999 一、10 (2分)】 A. 插入 B. 冒泡 C. 二路归并 D. 堆积3.下列排序算法中,其中()是稳定的。
【福州大学 1998 一、3 (2分)】A. 堆排序,冒泡排序B. 快速排序,堆排序C. 直接选择排序,归并排序D. 归并排序,冒泡排序4.稳定的排序方法是()【北方交通大学 2000 二、3(2分)】A.直接插入排序和快速排序 B.折半插入排序和起泡排序C.简单选择排序和四路归并排序 D.树形选择排序和shell排序5.下列排序方法中,哪一个是稳定的排序方法?()【北方交通大学 2001 一、8(2分)】A.直接选择排序 B.二分法插入排序 C.希尔排序 D.快速排序6.若要求尽可能快地对序列进行稳定的排序,则应选(A.快速排序 B.归并排序 C.冒泡排序)。
【北京邮电大学 2001 一、5(2分)】7.如果待排序序列中两个数据元素具有相同的值,在排序前后它们的相互位置发生颠倒,则称该排序算法是不稳定的。
()就是不稳定的排序方法。
【清华大学 1998 一、3 (2分)】A.起泡排序 B.归并排序 C.Shell排序 D.直接插入排序 E.简单选择排序8.若要求排序是稳定的,且关键字为实数,则在下列排序方法中应选()排序为宜。
A.直接插入 B.直接选择 C.堆 D.快速 E.基数【中科院计算所 2000 一、5(2分)】9.若需在O(nlog2n)的时间内完成对数组的排序,且要求排序是稳定的,则可选择的排序方法是()。
A. 快速排序B. 堆排序C. 归并排序D. 直接插入排序【中国科技大学 1998 二、4(2分)】【中科院计算所 1998 二、4(2分)】10.下面的排序算法中,不稳定的是()【北京工业大学 1999 一、2 (2分)】序 D.希尔排序 E.基数排序 F.堆排序。
10.23②试以L.r[k+1]作为监视哨改写教材10.2.1节中给出的直接插入排序算法。
其中,L.r[1..k]为待排序记录且k<MAXSIZE。
实现下列函数:void InsertSort(SqList &L);顺序表的类型SqList定义如下:typedef struct {KeyType key;...} RedType;typedef struct {RedType r[MAXSIZE+1]; // r[0]闲置或用作哨兵单元int length;} SqList;void InsertSort(SqList &L){int i,j;for(i=L.length-1;i>0;i--){L.r[L.length+1]=L.r[i+1];if(GT(L.r[i],L.r[i+1])){L.r[L.length+1]=L.r[i];L.r[i]=L.r[i+1];}for(j=i+2;LT(L.r[j],L.r[L.length+1]);j++)L.r[j-1]=L.r[j];L.r[j-1]=L.r[L.length+1];}}10.26②如下所述改写教科书1.4.3节中的起泡排序算法:将算法中用以起控制作用的布尔变量change改为一个整型变量,指示每一趟排序中进行交换的最后一个记录的位置,并以它作为下一趟起泡排序循环终止的控制值。
实现下列函数:void BubbleSort(SqList &L);/* 元素比较和交换必须调用以下比较函数和交换函数:*/ /* Status LT(RedType a, RedType b); 比较:"<" *//* Status GT(RedType a, RedType b); 比较:">" *//* void Swap(RedType &a, RedType &b); 交换*/顺序表的类型SqList定义如下:typedef struct {KeyType key;...} RedType;typedef struct {RedType r[MAXSIZE+1]; // r[0]闲置或用作哨兵单元int length;} SqList;比较函数和交换函数:Status LT(RedType a, RedType b); // 比较函数:"<"Status GT(RedType a, RedType b); // 比较函数:">"void Swap(RedType &a, RedType &b); // 交换函数void BubbleSort(SqList &L)/* 元素比较和交换必须调用如下定义的比较函数和交换函数:*/ /* Status LT(RedType a, RedType b); 比较:"<" *//* Status GT(RedType a, RedType b); 比较:">" *//* void Swap(RedType &a, RedType &b); 交换*/ {int i,j,change=1;for(i=L.length;i>1;i=change){change=1;for(j=1;j<i;j++){if(GT(L.r[j],L.r[j+1])){Swap(L.r[j],L.r[j+1]);change=j;}}}}10.32⑤荷兰国旗问题:设有一个仅由红、白、兰这三种颜色的条块组成的条块序列。
请编写一个时间复杂度为O(n)的算法,使得这些条块按红、白、兰的顺序排好,即排成荷兰国旗图案。
实现下列函数:void HFlag(FlagList &f)/* "荷兰国旗"的元素为red,white和blue,*/ /* 分别用字符'0','1'和'2'表示*/"荷兰国旗"的顺序表的类型FlagList定义如下:#define red '0'#define white '1'#define blue '2'typedef char ColorType;typedef struct {ColorType r[MAX_LENGTH+1];int length;} FlagList;void swap(ColorType &a,ColorType &b){ColorType temp;temp=a;a=b;b=temp;}void HFlag(FlagList &f){int i,j,k;char c;for(i=1,j=1,k=f.length;j<=k;){c=f.r[j];if(c==red)swap(f.r[i++],f.r[j++]);if(c==white)j++;if(c==blue)swap(f.r[j],f.r[k--]);}}10.34③已知(k1,k2,...,kp)是堆,则可以写一个时间复杂度为O(log(n))的算法将(k1,k2,...,kp,kp+1)调整为堆。
试编写"从p=1起,逐个插入建堆"的算法,并讨论由此方法建堆的时间复杂度。
实现下列函数:void CreateHeap(HeapType &h, char *s);堆(顺序表)的类型HeapType定义如下:typedef char KeyType;typedef struct {KeyType key;... ...} RedType;typedef struct {RedType r[MAXSIZE+1];int length;} SqList, HeapType;void CreateHeap(HeapType &h, char *s){int i,j,locate,k;KeyType e;h.length=0;for(i=0;s[i]!='\0';i++){h.length++;h.r[h.length].key=s[i];e=h.r[h.length].key;locate=h.length;k=h.length/2;for(j=h.length;k>0;j=j/2,k=j/2){if(e<h.r[k].key){h.r[j].key=h.r[k].key;locate=k;}}h.r[locate].key=e;}}10.35③假设定义堆为满足如下性质的完全三叉树:(1) 空树为堆;(2) 根结点的值不小于所有子树根的值,且所有子树均为堆。
编写利用上述定义的堆进行排序的算法,并分析推导算法的时间复杂度。
实现下列函数:void HeapSort(HeapType &h);堆(顺序表)的类型HeapType定义如下:typedef char KeyType;typedef struct {KeyType key;... ...} RedType;typedef struct {RedType r[MAXSIZE+1];int length;} SqList, HeapType;比较函数和交换函数:Status LT(RedType a, RedType b){ return a.key<b.key ? TRUE : FALSE; }Status GT(RedType a, RedType b){ return a.key>b.key ? TRUE : FALSE; }void Swap(RedType &a, RedType &b){ RedType c; c=a; a=b; b=c; }void HeapAdjust(HeapType &H,int s,int m){int j,flag;RedType rc;rc=H.r[s];for(j=3*s-1;j<=m;j=3*j-1){flag=0; printf("Do %d\n ",j);if(j<m&<(H.r[j],H.r[j+1])){ j++;flag=1;printf("");} if(flag){if(j<m&<(H.r[j],H.r[j+1])) j++;}else if(j+1<m&<(H.r[j],H.r[j+2]))j=j+2;if(!LT(rc,H.r[j]))break;H.r[s]=H.r[j];s=j;}H.r[s]=rc;}void HeapSort(HeapType &h)/* 元素比较和交换必须调用以下比较函数和交换函数:*/ /* Status LT(RedType a, RedType b); 比较:"<" *//* Status GT(RedType a, RedType b); 比较:">" *//* void Swap(RedType &a, RedType &b); 交换*/ {int i;//printf("%d",h.length);for(i=(h.length+1)/3;i>0;i--){HeapAdjust(h,i,h.length);printf("%d,OK \n",i);}for(i=h.length;i>1;i--){Swap(h.r[1],h.r[i]);HeapAdjust(h,1,i-1);}}10.42④序列的"中值记录"指的是:如果将此序列排序后,它是第n/2个记录。
试写一个求中值记录的算法。
实现下列函数:KeyType MidElement(SqList &L);顺序表的类型SqList定义如下:typedef struct {KeyType key;...} RedType;typedef struct {RedType r[MAXSIZE+1]; // r[0]闲置或用作哨兵单元int length;} SqList;KeyType MidElement(SqList &L){int i,j,k,n;RedType temp;if(L.length==0)return '#';for(i=1;i<L.length;i++){k=i;temp=L.r[i];for(j=i+1;j<=L.length;j++)if(temp.key>L.r[j].key){temp=L.r[j];k=j;}temp=L.r[i];L.r[i]=L.r[k];L.r[k]=temp;}if(L.length%2==0)n=L.length/2;else n=L.length/2+1;return L.r[n].key;}10.43③已知记录序列a[1..n] 中的关键字各不相同,可按如下所述实现计数排序:另设数组c[1..n],对每个记录a[i],统计序列中关键字比它小的记录个数存于c[i],则c[i]=0的记录必为关键字最小的记录,然后依c[i]值的大小对a中记录进行重新排列,试编写算法实现上述排序方法。