文档库 最新最全的文档下载
当前位置:文档库 › 《数据结构》习题汇编09-第九章-排序-试题.doc

《数据结构》习题汇编09-第九章-排序-试题.doc

数据结构课程(本科)第九章试题

一、单项选择题

1. 若待排序对象序列在排序前已按其排序码递增顺序排列,则采用()方法比较次数最少。

A. 直接插入排序

B. 快速排序

C. 归并排序

D. 直接选择排序

2. 如果只想得到 1024 个元素组成的序列中的前 5 个最小元素,那么用()方法最快。

A. 起泡排序

B. 快速排序

C. 直接选择排序

D. 堆排序

3.对待排序的元素序列进行划分,将其分为左、右两个子序列,再对两个子序列施加同样的排序操作,

直到子序列为空或只剩一个元素为止。这样的排序方法是()。

A. 直接选择排序

B. 直接插入排序

C. 快速排序

D. 起泡排序

4. 对 5 个不同的数据元素进行直接插入排序,最多需要进行()次比较?

A. 8

B. 10

C. 15

D. 25

5. 如果输入序列是已经排好顺序的,则下列算法中()算法最快结束?

A. 起泡排序

B. 直接插入排序

C. 直接选择排序

D. 快速排序

6. 如果输入序列是已经排好顺序的,则下列算法中()算法最慢结束?

A. 起泡排序

B. 直接插入排序

C. 直接选择排序

D. 快速排序

7. 下列排序算法中()算法是不稳定的。

A. 起泡排序

B. 直接插入排序

C. 基数排序

D. 快速排序

8. 假设某文件经过内部排序得到100 个初始归并段,那么如果要求利用多路平衡归并在 3 趟内完成排序,

则应取的归并路数至少是()。

A. 3

B. 4

C. 5

D. 6

9. 采用任何基于排序码比较的算法,对 5 个互异的整数进行排序,至少需要()次比较。

A. 5

B. 6

C. 7

D. 8

10. 下列算法中()算法不具有这样的特性:对某些输入序列,可能不需要移动数据对象即可完成

排序。

A. 起泡排序

B. 希尔排序

C. 快速排序

D. 直接选择排序

11. 使用递归的归并排序算法时,为了保证排序过程的时间复杂度不超过O(nlog 2n),必须做到()。

A.每次序列的划分应该在线性时间内完成

B.每次归并的两个子序列长度接近

C.每次归并在线性时间内完成

D.以上全是

12. 在基于排序码比较的排序算法中,()算法的最坏情况下的时间复杂度不高于 O(nlog 2n)。

A. 起泡排序

B. 希尔排序

C. 归并排序

D. 快速排序

13. 在下列排序算法中,()算法使用的附加空间与输入序列的长度及初始排列无关。

A. 锦标赛排序

B. 快速排序

C. 基数排序

D. 归并排序

14.一个对象序列的排序码为 { 46, 79, 56, 38, 40, 84 } ,采用快速排序(以位于最左位置的对象为基准而)得

到的第一次划分结果为:

A. { 38, 46, 79, 56, 40, 84 }

B. { 38, 79, 56, 46, 40, 84 }

C. { 40, 38, 46, 79, 56, 84 }

D. { 38, 46, 56, 79, 40, 84 }

15. 如果将所有中国人按照生日(不考虑年份,只考虑月、日)来排序,那么使用下列排序算法中()

算法最快。

A. 归并排序

B. 希尔排序

C. 快速排序

D. 基数排序

参考答案:1. A 2. D 3. C 4. B 5. A

6. D

7. D

8. C

9. C 10. C

11. D 12. C 13. C 14. C 15. D

二、填空题

1. 第 i (i = 1, 2 ,, -n1) 趟从参加排序的序列中取出第i 个元素,把它插入到由第0 个~第 i - 1 个元素组

成的有序表中适当的位置,此种排序方法叫做________排序。

2. 第 i (i = 0, 1, - 2) ,趟n从参加排序的序列中

第i 个~第 n- 1 个元素中挑选出一个最小(大)元素,把

它交换到第i 个位置,此种排序方法叫做________排序。

3.每次直接或通过基准元素间接比较两个元素,若出现逆序排列,就交换它们的位置,这种排序方法叫

做 ________排序。

4. 每次使两个相邻的有序表合并成一个有序表,这种排序方法叫做________排序。

5. 在直接选择排序中,排序码比较次数的时间复杂度为O(________) 。

6. 在直接选择排序中,数据对象移动次数的时间复杂度为O(________) 。

7. 在堆排序中,对 n 个对象建立初始堆需要调用________次调整算法。

8. 在堆排序中,如果 n 个对象的初始堆已经建好,那么到排序结束,还需要从堆顶结点出发调用 ________

次调整算法。

9. 在堆排序中,对任一个分支结点进行调整运算的时间复杂度为O(________) 。

10. 对 n 个数据对象进行堆排序,总的时间复杂度为O(________) 。

11. 给定一组数据对象的排序码为{ 46, 79, 56, 38, 40, 84 } ,则利用堆排序方法建立的初始堆(最大堆)为

________。

12.快速排序在平均情况下的时间复杂度为O(________) 。

13.快速排序在最坏情况下的时间复杂度为O(________) 。

14.快速排序在平均情况下的空间复杂度为O(________) 。

15.快速排序在最坏情况下的空间复杂度为O(________) 。

16. 给定一组数据对象的排序码为{ 46, 79, 56, 38, 40, 84} ,对其进行一趟快速排序,结果为________。

17. 在 n 个数据对象的二路归并排序中,每趟归并的时间复杂度为O(________) 。

18. 在 n 个数据对象的二路归并排序中,整个归并的时间复杂度为O(________) 。

参考答案: 1 . 插入 2. 直接选择 3. 交换

4. 两路归并

5. n 2

6. n

7. n/2 8. n-1 9. log 2 n

10. nlog 2n 11. 84, 79, 56, 38, 40, 46 12. nlog 2n

13. n 2 14. log 2n 15. n

16. [40 38] 46 [79 56 84] 17. n 18. nlog 2n

三、判断题

1.直接选择排序是一种稳定的排序方法。

2.若将一批杂乱无章的数据按堆结构组织起来, 则堆中各数据是否必然按自小到大的顺序排列起来。

3.当输入序列已经有序时,起泡排序需要的排序码比较次数比快速排序要少。

4.在任何情况下,快速排序需要进行的排序码比较的次数都是O(nlog 2n)。

5. 在 2048 个互不相同的排序码中选择最小的 5 个排序码,用堆排序比用锦标赛排序更快。

6. 若用 m 个初始归并段参加k 路平衡归并排序,则归并趟数应为log 2m 。

7.堆排序是一种稳定的排序算法。

8.对于某些输入序列,起泡排序算法可以通过线性次数的排序码比较且无需移动数据对象就可以完成排

序。

9.如果输入序列已经排好序,则快速排序算法无需移动任何数据对象就可以完成排序。

10.希尔排序的最后一趟就是起泡排序。

11. 任何基于排序码比较的算法,对n 个数据对象进行排序时,最坏情况下的时间复杂度不会低于

O(nlog 2n)。

12. 不存在这样一个基于排序码比较的算法:它只通过不超过9 次排序码的比较,就可以对任何 6 个排序

码互异的数据对象实现排序。

参考答案:1. 否 2. 否 3. 是 4. 否 5. 否

6. 否

7. 否

8. 是

9. 否10. 是

11. 是12. 是

四、运算题

1.判断以下序列是否是最小堆?如果不是, 将它调整为最小堆。

(1){ 100, 86, 48, 73, 35, 39, 42, 57, 66, 21 }

(2){ 12, 70, 33, 65, 24, 56, 48, 92, 86, 33 } 。

2.在不要求完全排序时,堆排序是一种高效的算法。这种算法的过程是:

( Heapification )把待排序序列看作一棵完全二叉树,通过反复筛选将其调整为

堆;( Re-heapification )依次取出堆顶,然后将剩余的记录重新调整为堆。

现考虑序列 A = { 23, 41, 7, 5, 56 } :

(1)给出对应于序列 A 的最小堆 H A(以线性数组表示);

(2) 给出第一次取出堆顶后,重新调整H A后的结果(以线性数组表示);

(3) 给出第二次取出堆顶后,重新调整H A后的结果(以线性数组表示)。

3. 希尔排序、直接选择排序、快速排序和堆排序是不稳定的排序方法, 试举例说明。

4. 给出 12 个初始归并段,其长度分别为19, 22, 17, 16, 11, 10, 12, 32, 26, 20, 28, 07。现要做4路外归并排序,

试画出表示归并过程的最佳归并树,并计算该归并树的带权路径长度WPL 。

5.设输入文件包含以下数据对象的排序码:14, 22, 7, 16, 11, 10, 12, 90, 26, 30, 28, 110 。现采用置换—选择

方法生成初始归并段,并假设内存工作区可同时容纳 5 个数据对象,请画出生成初始归并段的过程。

6.在利用置换—选择方法生成初始归并段时,可另开辟一个与工作区容量相同的辅助存储区(称为储备

库)。当输入对象排序码小于刚输出的门槛LastKey 对象的排序码时,不将它存入工作区,而暂存于

储备库中,接着输入下一对象的排序码,依次类推,直到储备库满时不再进行输入,而只是从工作区

中选择对象输出直至工作区空为止,由此得到一个初始归并段。然后再将储备库中的对象传送至工作

区,重新开始置换—选择。

若设输入文件包含对象的排序码为 19, 22, 17, 16, 11, 10, 12, 32, 26, 20, 28, 07 。采用上述方法生成初始归并段,并设工作区可容纳 5 个对象,请画出生成初始归并段的过程。

450 7. 假设文件有4500 个记录,在磁盘上每个页块可放75 个记录。计算机中用于排序的内存区可容纳

个记录。试问:

(1)可建立多少个初始归并段?每个初始归并段有多少记录?存放于多少个页块中?

(2)应采用几路归并?请写出归并过程及每趟需要读写磁盘的页块数。

8. 如果某个文件经内排序得到80 个初始归并段,试问

(1)若使用多路归并执行 3 趟完成排序,那么应取的归并路数至少应为多少?

(2) 如果操作系统要求一个程序同时可用的输入/输出文件的总数不超过15 个,则按多路归并至少需

要几趟可以完成排序?如果限定这个趟数,可取的最低路数是多少?

参考答案:

1.(1) { 100, 86, 48, 73, 35, 39, 42, 57, 66, 21 } 为最大堆。

调整为最小堆后为 { 21, 35, 39, 57, 86, 48, 42, 73, 66, 100 }

(2){ 12, 70, 33, 65, 24, 56, 48, 92, 86, 33 } 不是最小堆。调

整为最小堆后为 { 12, 24, 33, 65, 33, 56, 48, 92, 86, 70 }

2.(1) 建堆结果

H A= 5 23 7 41 56

(2)第一次取出堆顶,并重新调整后

H A=7 23 56 41

(3)第二次取出堆顶,并重新调整后

H A= 23 41 56

3. (1) 希尔排序{ 512 275 275* 061 } 增量为 2

{ 275* 061 512 275 } 增量为 1

{ 061 275* 275 512 }

(2) 直接选择排序{ 275 275* 512 061 } i = 1

{ 061 275* 512 275 } i = 2

{ 061 275* 512 275 } i = 3

{ 061 275* 275 512 }

(3) 快速排序{ 512 275 275* }

{ 275* 275 512 }

(4) 堆排序{ 275 275* 061 170 } 已经是最大堆,交换275 与 170

{ 170 275* 061 275 } 对前 3 个调整

{ 275* 170 061 275 } 前 3 个最大堆,交换275* 与 061

{ 061 170 275* 275 } 对前 2 个调整

{ 170 061 275* 275 } 前 2 个最大堆,交换170 与 061

{ 061 170 275* 275 }

4. 设初始归并段个数n = 12 ,外归并路数k = 4 ,计算 (n-1) % (k-1) = 11 % 3 = 2 ≠ 0,必须补 k-2-1 = 1

个长度为 0 的空归并段,才能构造 k 路归并树。此时,归并树的内结点应有(n-1+1)/(k-1) = 12/3 = 4 个。

0 3 6 8 9 18 20 30 44 60 62 68 85

0 3 6 8

9 17 18 20 30 44 60 62 68 85

0 3 6 8

9 17 18 20 30 44 60 62

64 68 85 196

413

WPL = (3+6+8)*3+(9+18+20+30+44+60+62)*2+(68+85)*1 = 51+ 486+153 = 690

5.生成初始归并段的过程

输入文件 InFile 内存工作区输出文件 OutFile 动作

19, 22, 17, 16, 11, 10, 输入 5 个排序码

12, 32, 26, 20, 28, 07

10, 12, 32, 26, 20, 28, 19, 22, 17, 16, 11 选择 11, 输出 11,

07 门槛 11, 置换 10

12, 32, 26, 20, 28, 07 19, 22, 17, 16, 10 11 选择 16, 输出 16,

门槛 16, 置换 12

32, 26, 20, 28, 07 19, 22, 17, 12, 10 11, 16 选择 17, 输出 17,

门槛 17, 置换 32

26, 20, 28, 07 19, 22, 32, 12, 10 11, 16, 17 选择 19, 输出 19,

门槛 19, 置换 26

20, 28, 07 26, 22, 32, 12, 10 11, 16, 17, 19 选择 22, 输出 22,

门槛 22, 置换 20

28, 07 26, 20, 32, 12, 10 11, 16, 17, 19, 22 选择 26, 输出 26,

门槛 26, 置换 28

07 28, 20, 32, 12, 10 11, 16, 17, 19, 22, 26 选择 28, 输出 28,

门槛 28, 置换 07

07, 20, 32, 12, 10 11, 16, 17, 19, 22, 26, 28 选择 32, 输出 32,

门槛 32, 无输入

07, 20, ―, 12, 10 11, 16, 17, 19, 22, 26, 28, 无大于门槛的对象 ,

32 输出段结束符∞

07, 20, ―, 12, 10 11, 16, 17, 19, 22, 26, 28, 选择 07, 输出 07,

32, ∞门槛 07, 无输入

― , 20, ―, 12, 10 07

―, 20, ―, 12, ―07, 10

―, 20, ―, ―, ―07, 10, 12

―,―,―,―,―07, 10, 12, 20

07, 10, 12, 20, ∞6.生成初始归并段的过程选择 10, 输出 10, 门槛 10, 无输入

选择 12, 输出 12, 门槛 12, 无输入

选择 20, 输出 20, 门槛 20, 无输入

无大于门槛的对象, 输出段结束符∞

结束

输入文件InFile 19, 22, 17, 16, 11,10, 12, 32, 26, 20,28, 07 内存工作区储备库输出文件OutFile动作

输入 5 个排序码

10, 12, 32, 26, 20, 28, 07

12, 32, 26, 20, 28, 07 32, 26, 20, 28, 07 26, 20, 28, 07

20, 28, 07

28, 07

07

将暂存区内容传送到内存工作区19, 22, 17,

16, 11

19, 22, 17,

16,―

19, 22, 17,

― , ―

19, 22,

32, ― , ―

26, 22,

32, ― , ―

26, ― ,

32, ― , ―

28, ― ,

32, ― , ―

―, ―, 32,

―, ―

―,―,―,

―, ―

10, 12, 20,

07, ― 10,

12,

20, ― , ―

―, 12, 20,

―, ―

―, ―, 20,

―, ―

―,―,―,

―, ―

11

10 11

10, 12 11, 16

10, 12 11, 16, 17

10, 12 11, 16, 17, 19

10, 12, 20 11, 16, 17, 19, 22

10, 12, 20 11, 16, 17, 19, 22,

26

10, 12, 20, 11, 16, 17, 19, 22,

07 26, 28

10, 12, 20, 11, 16, 17, 19, 22,

07 26, 28, 32

11, 16, 17, 19, 22,

26, 28, 32, ∞

07

07, 10

07, 10, 12

07, 10, 12, 20

07, 10, 12, 20, ∞

选择 11, 输出 11,

门槛 11, 暂存 10

选择 16,输出16,

门槛 16,暂存12

选择 17,输出17,

门槛 17,置换32

选择 19,输出19,

门槛 19,置换26

选择 22,输出22,

门槛 22,暂存20

选择 26,输出26,

门槛 26,置换28

选择 28,输出28,

门槛 28,暂存07

选择 32,输出32,

门槛 32,无输入

无大于门槛的对象,

输出段结束符∞

选择 07, 输出 07,

门槛 07, 无输入

选择 10, 输出 10,

门槛 10, 无输入

选择 12, 输出 12,

门槛 12, 无输入

选择 20, 输出 20,

门槛 20, 无输入

无大于门槛的对象,

输出段结束符∞

结束

7. (1) 文件有 4500 个记录,计算机中用于排序的内存区可容纳450 个记录,可建立的初始归并段有4500

∕ 450 = 10 个。每个初始归并段中有450 个记录,存于450∕ 75 = 6 个页块中。

(2) 内存区可容纳 6 个页块,可建立 此,可采用 5 路归并。归并过程如下:

6 个缓冲区,其中 5 个缓冲区用于输入,

1 个缓冲区用于输出,因 450 450 450 450

450 450

450 450

450

450

2250 2250

4500

共做了

2 趟归并,每趟需要读

60 个磁盘页块,写出

60 个磁盘页块。

8. (1) 设归并路数为 k 3≥ 80。由此解得

k ,初始归并段个数

m = 80 ,根据归并趟数计算公式

k ≥5,即应取的归并路数至少为

5。

S =

log k m = log k 80 = 3 得:

(2) 设多路归并的归并路数为 k ,需要 k 个输入缓冲区和 1 个输出缓冲区。 1 个缓冲区对应 1 个文件,

有 k +1 = 15 ,因此 k = 14 ,可做

14 路归并。由 S = log k

m = 14

= 2。即至少需 2 趟归并可完成

log 80 排序。

若限定这个趟数,由 S = log k 80 = 2 ,有 80≤ k 2,可取的最低路数为

9。即要在 2 趟内完成排序,进

行 9 路排序即可。

五、算法分析题

1. 给出下面 main () 函数的执行结果:

//------------------------------------------------------------

// Sorry, no comments available:

// Try to read & understand following lines by yourself //------------------------------------------------------------ #include

void Exchange ( int s[ ], int i, int j ) {

int temp = s[i] ; s[i] = s[j] ; s[j] = temp ; }

int Partition ( int seq[ ], int low , int high ) {

int pivotpos = low ; int pivot = seq[low];

for ( int i = low+1 ; i <= high ; i++ ) if ( seq[i] < pivot ) { pivotpos++ ;

if ( pivotpos != i ) Exchange ( seq, pivotpos, i) ; }

Exchange ( seq, low, pivotpos ) ;

for ( i = 0 ; i < low ; i++ ) printf ( "\t" );

for ( i = low ; i < pivotpos ; i++ ) printf ( "\t%d", seq[i] ) ;

printf ( "\t[%d]", seq[pivotpos] ) ;

for ( i = pivotpos+1 ; i <= high ; i++ ) printf ( "\t%d", seq[i] ) ;

printf ( "\n" ) ;

return pivotpos ;

}

void main ( ) {

int testSeq[12] = { 57, 37, 17, 42, 61, 27, 84, 06, 19, 59, 93, 23 };

Partition ( testSeq, 0, 11) ;

Partition ( testSeq, 0, 6);

Partition ( testSeq, 8, 11) ;

}

2.本题给出一个施加于链表的选择排序的算法。

表头结点,每次从first 链上摘下值最大的结点算法中用到一个临时的表头结点 head,作为结果链表的current 链入 head 之后。算法结束前,将 head 删除。

template

void LinkList :: ListSelectSort ( ) {

LinkNode * head = new ListNode , * current, * pre, * p, * q

int i = 0 ;

while (①) {

p = current = first ; q = NULL ;

while ( p != NULL ){

;

if ( p-> data > ②)

{ pre = q; current = p ; }

q = p; p = p-> link ;

}

if (current == first ) ③;

else pre-> link = current -> link ;

if ( !i ) last = current ;

i++ ;

current-> link = head -> link ;④;

}

first = head -> link ; delete head;

}

(1)请将缺失的语句部分补上 ;

(2) 设待排序的对象个数n = 7, 当排序前各对象排序码的初始链接顺序为40, 20, 60, 30, 70, 50, 80 ,试

根据上述算法,画出每一趟排序时各结点指针的变化。

currentSize 是数据表实例的当前长度,3.下面给出一个排序算法,它属于数据表类的成员函数,其中

Vector[ ]是存放数据表元素的一维数组。

template

void dataList :: unknown ( ) {

T temp; int i, j, n = currentSize ;

for ( i = 1 ; i < n ; i++ )

if ( Vector[i] .key < Vector[i - 1].key ) {

temp = Vector[i] ; Vector[i] = Vector[i - 1];

for ( j = i - 2; j >= 0 ; j -- )

if ( temp.key < Vector[j].key ) Vector[j+1] = V

ector[j] ;

else break;

Vector[j+1] = temp ;

}

}

(1)该算法执行什么功能?

(2)针对有 n 个数据对象的待排序的数据表,算法的排序码比较次数和对象移动次数最好是多少?最

坏是多少?

currentSize 是数据表实例的当前长度,4. 下面给出一个排序算法,它属于数据表类的成员函数,其中

Vector[ ]是存放数据表元素的一维数组。

template

void dataList :: unknown ( ) {

T temp;int i , j , d, n = currentSize ;

for ( d = n/2 ; d >= 1; d /= 2 )//按不同增量划分子序列

for ( i = d ; i < n ; i++ ) {//对子序列执行直接插入排序

temp = Vector[i];

for ( j = i - d; j >= 0 ; j - = d )

;

if ( temp.key < Vector[j].key ) Vector[j+d] = Vector[j]

else break;

Vector[j+d] = temp ;

}

}

(1)该算法执行什么功能?

(2)针对一组输入实例 {35, 67, 18, 29, 53, 44, 09, 21 } ,画出每一趟排序过程。

currentSize 是数据表实例的当前长度,5.下面给出一个排序算法,它属于数据表类的成员函数,其中

Vector[ ]是存放数据表元素的一维数组。

template

void dataList :: unknown ( int left , int right ) {

// 对当前排序区间[left, right] 进行排序

int i = left, j = right +1 ;

T pivot = Vector[left]; // 把基准元素的值暂存于temp 中do {

do { i++ ; } while ( Vector[i].key < pivot.key );

do { j -- ; } while ( Vector[j].key > pivot.key );

if ( i < j ) {// 交换 Vector[i] 和 Vector[j] 的值T temp = Vector[i] ; Vector[i] = Vector[j] ; Vector[j] = temp ;

}

} while( i < j ) ;

Vector[left] = Vector[j] ; Vector[j] = pivot ;

if ( left < j - 1 ) unknown ( left , j - 1 );

if ( j+1 < right ) unknown ( j+1, right ); // 递归处理左区间// 递归处理右区间

}

(1)该算法的功能是什么?

(2)以下面给出的待排序的数据序列为例,画出每次递归执行时的结果序列。

{ 45 48 18 36 72 30 53 15 29}

6.下面给出一个排序算法,它属于数据表类的成员函数,其中

Vector[ ]是存放数据表元素的一维数组。

currentSize 是数据表实例的当前长度,

template

void dataList :: unknown ( ) {

int low = 0, high = CurrentSize - 1, i, j ; int exchange;

while ( low < high ) {//当比较范围多于一个对象时排序

j = low ;//记忆元素交换位置

for ( i = low ; i < high ; i++ )

if ( Vector[i].key > Vector[i+1].key ){

T temp = Vector[i];

Vector[i] = Vector[i+1];

Vector[i+1] = temp;

j = i ;//记忆右边最后发生交换的位置j

}

high = j ; //比较范围上界缩小到j

}

}

(0)该算法的功能是什么?

(1)给出待排序数据序列为 {10, 20, 30, 40, 50, 60 } 和 { 60, 50,40, 30, 20, 10 } ,画出每次执行时的结果序

列。

7.下面的程序是一个的两路归并算法merge,只需要一个附加存储。设算法中参加归并的两个归并段是

A[left] A[mid] 和 A[mid] A[right] ,归并后结果归并段放在原地。

template

void dataList :: merge ( int left, int mid, int right ) {

int i, j; T temp;

for ( i = left ; i <= mid ; i++ ) {

if ( A[i] > A[mid+1] ){

temp = A[mid] ;

for ( j = mid - 1; j >= i ; j-- ) A[j+1] = A[j];

A[i] = A[mid+1];

for ( j = mid+2 ; j <= right ; j++ )

if ( temp > A[j] ) A[j - 1] = A[j] ;

else break;

A[j - 1] = temp ;

}

}

}

若 A = { 12, 28, 35, 42, 67, 9, 31, 70 }, left = 0 , mid = 4 , right = 7 。写出每次执行算法最外层循环后数组的变化,并给出每次执行算法最外层循环时的数据记录移动次数。

参考答案:

1.输出结果:

23 37 17 42 27 6 19 [57] 84 59 93 61

19 17 6 [23] 27 37 42

61 59 [84] 93

2.链接表上的直接选择排序方法

(1)缺失语句

①first != NULL

②current -> data

③first = first -> link

④head-> link = current

(2)变化过程

first40206030705080head

pre cureent

first402060307050head80

pre cureent

first4020603050head7080

pre cureent

first40203050head607080

pre cureent

first 40 20 30 head 50 60 70 80

pre cureent

first 20 30 head 40 50 60 70 80

pre cureent

first 20 head 30 40 50 60 70 80

pre cureent

first head 20 30 40 50 60 70 80

first 20 30 40 50 60 70 80

3.算法功能及执行效率

(1)该算法的功能是直接插入排序。

(2)在最好情况下,即所有待排序数据对象已经有序排序时,排序码比较次数为 n- 1,数据移动次数为0。

在最坏情况下,即所有待排序数据对象全部逆序排序,排序码比较次数和数据移动次数分别为

n 1 n n 1 ,数据移动次数排序码比较次数i

i 1 2 n 1

n 4 n 1

i 2

i 1 2

4.算法功能及执行实例的结果

(0)该算法的功能是希尔排序。

(2) 输入实例为{35, 67, 18, 29, 53, 44, 09, 21 } 时,每一趟排序过程如下:

初始排列35 67 18 29 53 44 09 21 增量

i = 1 35 44 09 21 53 67 18 29 4

i = 2 09 21 18 29 35 44 53 67 2

i = 3 09 18 21 29 35 44 53 67 1

5.算法功能及执行实例的结果

(1)该算法的功能是递归的快速排序。

(2)输入实例为 { 45 48 18 36 72 30 53 15 29 } 时,递归执行的结果如下:

初始排列[ 45 48 18 36 72 30 53 15 29 ]

i = 1 [ 29 15 18 36 30 ] 45 [ 53 72 48 ]

i = 2 [ 18 15 ] 29 [ 36 30 ] 45 [ 53 72 48 ]

i = 3 15 [18] 29 [ 36 30 ] 45 [ 53 72 48 ]

i = 4 15 18 29 30 [36] 45 [ 53 72 48 ]

i = 5 15 18 29 30 36 45 [48] 53 [72]

6.算法功能及执行实例的结果

(1)该算法的功能是起泡排序。

(2)给出待排序数据序列为{10, 20, 30, 40, 50, 60 } 时的执行结果

初始排列10 20 30 40 50 60 low high

i = 1 ↑ j 0 5

0 0

对于给定待排序数据序列{ 60, 50,40, 30, 20, 10} 时每次执行时的结果

初始排列60 50 40 30 20 10 low high

↑ j 0 5

i = 1 50 40 30 20 10 60

↑ j ↑ j 0 4

i = 2 40 30 20 10 50 60

↑ j ↑ j 0 3

i = 3 30 20 10 40 50 60

↑ j ↑ j 0 2

i = 4 20 10 30 40 50 60

↑ j ↑ j 0 1

i = 5 10 20 30 40 50 60 0 0

↑ j

数组 A 每次执行最外层循环后数组的变化如下:

left mid mid+1 right

A 0 1 2 3 4 temp 5 6 7

i=0 12 28 35 42 67 09 31 70 A[i] > A[mid+1]

记录移动8 次i=1 09 12 35 42 67 31 67 70 A[i] ≤A[mid+1]

28

记录移动0 次i=2 09 12 35 42 31 67 70 A[i] ≤A[mid+1]

28

记录移动0 次i=3 09 12 28 35 42 31 67 70 A[i] > A[mid+1]

记录移动 4 次i=4 09 12 28 31 35 42 42 67 70 A[i] ≤A[mid+1]

记录移动0 次

六、算法设计题

1.有一种简单的排序算法,叫做计数排序( count Sorting )。这种排序算法对一个待排序的表(用数组表

示)进行排序,并将排序结果存放到另一个新的表中。必须注意的是,表中所有待排序的关键码互不

相同。计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比

该记录的关键码小。假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序表中的合适的存放位置即为c。

(1) 给出适用于计数排序的数据表定义;

(2) 使用C++ 语言编写实现计数排序的算法;

2. 试设计一个算法, 使得在O(n) 的时间内重排待排序表(用数组表示)中的数据对象, 将所有取负值的

排序码排在所有取正值(非负值)的排序码之前。(在写算法之前首先用C++ 类定义数据表的结构)。参考答案:

1.计数排序

(1) 数据表定义

const int DefaultSize = 100 ;

template class datalist;

template class Element {

private:

T Key ;

Field otherdata ;

Public:

T getKey() { return key; }

void setKey ( const T x ) { key = x; }

}

template class datalist {

public:

datalist ( int MaxSz = DefaultSize ) : MaxSize (MaxSz) , CurrentSize(0)

{ Vector = new Element [MaxSz] ; }

int Length ( ) { return CurrentSize; }

void SetLength ( int n ) { CurrentSize = n ; }

Element & operator [ ] ( int i ) { return Vector[i] ; }

void SetObject ( Element & x, int i ) { Vector[i] = x ; }

private:

Element * Vector ;

int MaxSize , CurrentSize;

}

(2) 计数排序算法

template

void countsort ( datalist & iniList , datalist & resultList )

{ int i, j, c, n = iniList.Length( ) ; T refer;

for ( i = 0 ; i < n ; i++ ) {

c = 0;

refer = initList[i].getKey( );

for ( j = 0 ; j < n ; j++ )

if ( initList[j].getKey( ) < refer ) c++;

resultList.SetObject ( initList[i], c );

}

resultList.SetLength (n) ;

}

2.(1) 数据表定义

const int DefaultSize = 100 ;

template class datalist;

template class Element

{ private:

T Key ;

Field otherdata ;

Public:

T getKey() { return key; }

void setKey ( const T x ) { key = x; }

}

template class datalist {

public:

datalist ( int MaxSz = DefaultSize ) : MaxSize (MaxSz) , CurrentSize(0) { Vector = new Element [MaxSz] ; }

int Length ( ) { return CurrentSize; }

void SetLength ( int n ) { CurrentSize = n ; }

Element & operator [ ] ( int i ) { return Vector[i] ; }

void SetObject ( Element & x, int i ) { Vector[i] = x ; }

private:

Element * Vector ;

int MaxSize , CurrentSize;

}

(2) 重排算法

template

void reArrange ( dataList< Type>& L ) {

int i = 0, j = L.length ( )–1;

while ( i < j ) {

while ( L[i].getKey( ) < 0 ) i++;

while ( L[j].getKey( ) >= 0 ) j-- ;

swap ( L[i], L[j] );

i++ ;j -- ;

}

}

相关文档