第9章自测题答案.docx
《第9章自测题答案.docx》由会员分享,可在线阅读,更多相关《第9章自测题答案.docx(17页珍藏版)》请在冰豆网上搜索。
第9章自测题答案
第9章排序自测卷答案姓名班级
题号
一
二
三
四
五
总分
题分
24
18
36
8
14
100
得分
一、填空题(每空1分,共24分)
1.大多数排序算法都有两个基本的操作:
比较(两个关键字的大小)和移动(记录或改变指向记录的指针)。
2.在对一组记录(54,38,96,23,15,72,60,45,83)进行直接插入排序时,当把第7个记录60插入到有序表时,为寻找插入位置至少需比较3次。
(可约定为,从后向前比较)
3.在插入和选择排序中,若初始数据基本正序,则选用插入排序(到尾部);若初始数据基本反序,则选用选择排序。
4.在堆排序和快速排序中,若初始记录接近正序或反序,则选用堆排序;若初始记录基本无序,则最好选用快速排序。
5.对于n个记录的集合进行冒泡排序,在最坏的情况下所需要的时间是O(n2)。
若对其进行快速排序,在最坏的情况下所需要的时间是O(n2)。
6.对于n个记录的集合进行归并排序,所需要的平均时间是O(nlog2n),所需要的附加空间是O(n)。
7.【计研题2000】对于n个记录的表进行2路归并排序,整个归并排序需进行log2n趟(遍),共计移
动nlog2n次记录。
(即移动到新表中的总次数!
共log2n趟,每趟都要移动n个元素)
8.设要将序列(Q,H,C,Y,P,A,M,S,R,D,F,X)中的关键码按字母序的升序重新排列,则:
冒泡排序一趟扫描的结果是H,C,Q,P,A,M,S,R,D,F,X,Y;
初始步长为4的希尔(shell)排序一趟的结果是P,A,C,S,Q,D,F,X,R,H,M,Y;
二路归并排序一趟扫描的结果是H,Q,C,Y,A,P,M,S,D,R,F,X;
快速排序一趟扫描的结果是F,H,C,D,P,A,M,Q,R,S,Y,X;
堆排序初始建堆的结果是A,D,C,R,F,Q,M,S,Y,P,H,X。
9.在堆排序、快速排序和归并排序中,
若只从存储空间考虑,则应首先选取堆排序方法,其次选取快速排序方法,最后选取归并排序方法;
若只从排序结果的稳定性考虑,则应选取归并排序方法;
若只从平均情况下最快考虑,则应选取快速排序方法;
若只从最坏情况下最快并且要节省内存考虑,则应选取堆排序方法。
二、单项选择题(每小题1分,共18分)
(C)1.将5个不同的数据进行排序,至多需要比较次。
A.8B.9C.10D.25
(C)2.排序方法中,从未排序序列中依次取出元素与已排序序列(初始时为空)中的元素进行比较,将其放入已排序序列的正确位置上的方法,称为
A.希尔排序B.冒泡排序C.插入排序D.选择排序
(D)3.排序方法中,从未排序序列中挑选元素,并将其依次插入已排序序列(初始时为空)的一端的方法,称为
A.希尔排序B.归并排序C.插入排序D.选择排序
(C)4.对n个不同的排序码进行冒泡排序,在下列哪种情况下比较的次数最多。
A.从小到大排列好的B.从大到小排列好的C.元素无序D.元素基本有序
(D)5.对n个不同的排序码进行冒泡排序,在元素无序的情况下比较的次数为
A.n+1B.nC.n-1D.n(n-1)/2
(前3个答案都太小了)
(C)6.快速排序在下列哪种情况下最易发挥其长处。
A.被排序的数据中含有多个相同排序码B.被排序的数据已基本有序
C.被排序的数据完全无序D.被排序的数据中的最大值和最小值相差悬殊
(B)7.【计研题2001】对有n个记录的表作快速排序,在最坏情况下,算法的时间复杂度是
A.O(n)B.O(n2)C.O(nlog2n)D.O(n3)
(C)8.若一组记录的排序码为(46,79,56,38,40,84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为
A.38,40,46,56,79,84B.40,38,46,79,56,84
C.40,38,46,56,79,84D.40,38,46,84,56,79
(A&D)9.【计研题2001】在最好情况下,下列排序算法中排序算法所需比较关键字次数最少。
A.冒泡B.归并C.快速D.直接插入
(仅n—1次!
)
(C)10.【计研题2001】置换选择排序的功能是。
(置换选择排序=简单选择排序?
)
A.选出最大的元素B.产生初始归并段C.产生有序文件D.置换某个记录
(A)11.将5个不同的数据进行排序,至少需要比较次。
A.4B.5C.6D.7
(D)12.下列关键字序列中,是堆。
A.16,72,31,23,94,53B.94,23,31,72,16,53C.16,53,23,94,31,72D.16,23,53,31,94,72
(B)13.堆是一种排序。
A.插入B.选择C.交换D.归并
(C)14.堆的形状是一棵
A.二叉排序树B.满二叉树C.完全二叉树D.平衡二叉树
(B)15.若一组记录的排序码为(46,79,56,38,40,84),则利用堆排序的方法建立的初始堆为
A.79,46,56,38,40,84B.84,79,56,38,40,46
C.84,79,56,46,40,38D.84,56,79,40,46,38
(B)16.下述几种排序方法中,平均查找长度(ASL)最小的是
A.插入排序B.快速排序C.归并排序D.选择排序
(C)17.下述几种排序方法中,要求内存最大的是
A.插入排序B.快速排序C.归并排序D.选择排序
(B)18.目前以比较为基础的内部排序方法中,其比较次数与待排序的记录的初始排列状态无关的是
A.插入排序B.二分插入排序C.快速排序D.冒泡排序
三、简答题(每小题4分,共36分)
1.【全国专升本题】已知序列基本有序,问对此序列最快的排序方法是多少,此时平均复杂度是多少?
答:
插入排序和冒泡应该是最快的。
因为只有比较动作,无需移动元素。
此时平均时间复杂度为O(n)
2.设有1000个无序的元素,希望用最快的速度挑选出其中前10个最大的元素,最好采用哪种排序方法?
答:
用堆排序或锦标赛排序最合适,因为不必等全部元素排完就能得到所需结果,时间效率为O(nlog2n)
;若用冒泡排序则需时n!
/(n-10)!
3.用某种排序方法对线性表(25,84,21,47,15,27,68,35,20)进行排序时,元素序列的变化情况如下:
25,84,21,47,15,27,68,35,20→20,15,21,25,47,27,68,35,84→15,20,21,25,35,27,47,68,84→
15,20,21,25,27,35,47,68,84,问采用的是什么排序方法?
答:
用的是快速排序方法。
注意每一趟要振荡完全部元素才算一个中间结果。
4.对于整数序列100,99,98,…3,2,1,如果将它完全倒过来,分别用冒泡排序和快速排序法,它们的比较次数和交换次数各是多少?
答:
冒泡排序的比较和交换次数将最大,都是1+2+…+n-1=n(n-1)/2=50×99=4545次
快速排序则看按什么数据来分子表。
如果按100来分,则很惨,也会是n(n-1)/2!
若按中间数据50或51来分表,则:
第1轮能确定1个元素,即在1个子表中比较和交换了n-1个元素;n-(21-1)
第2轮能再确定2个元素,即在2个子表中比较和交换了n-3个元素;n-(22-1)
第3轮能再确定4个元素,即在4个子表中比较和交换了n-7个元素;n-(23-1)
第4轮能再确定8个元素,即在8个子表中比较和交换了n-15个元素;n-(24-1)
……
第6轮能再确定32个元素,即在32个子表中比较和交换了n-65个元素;n-(26-1)
第7轮则能全部确定,(因为27=128),在100个子表中比较和交换了n-(100-1)个元素;
比较和交换总次数为:
7n-(21-1+22-1+23-1……+26-1+100-1)=7n+7-(1+2+4+……+64+100)=7n-(8+16+32+164)=700-220=480次
若从中间选择初始元素,则ASL=(n+1)log2n-(21+22+23+……+2m)=nlog2n+log2n-(21+22+23+……+n)≈O(nlog2n)
5.【全国专升本试题】【严题集10.15④】设有n个值不同的元素存于顺序结构中,试问能否用比2n-3少的比较次数选出这n个元素中的最大值和最小值?
若能请说明如何实现(不需写算法)。
在最坏情况下至少需进行多少次比较。
(或问:
对含有n个互不相同元素的集合,同时找最大元和最小元至少需进行多少次比较?
)
答:
若用冒泡排序法,求最大值需n-1次比较;第二趟改为从n-1开始求最小值,需n-2次比较,合计2n-3次。
显然本题意图是放弃冒泡排序,寻找其他方法。
法1:
一个简单的办法是,在一趟比较时,将头两个元素分别作为最大和最小值的暂存内容,将其余n-2个元素与其相比,具体可设计为:
第1步:
a1用来设立max和min标志;无论Y/N都只比较1次;1次;
第2步:
a3>a2?
YES则直接替换a2,NO则再比较a1,1~2次;
第3步:
a4>a2?
YES则直接替换a2,NO则再比较a1,1~2次;
……
第n-1步:
an>a2?
YES则直接替换a2,NO则再比较a1,1~2次;
合计:
(n-2)×(1~2)+1=(n-1)~(2n-3)≤2n-3最好情况至少需要n-1次比较,最坏情况需2n-3次。
法2:
借用快速排序第一趟思想:
以a1为支点,将序列分成两个子表。
这一趟需要n-1次比较;
然后,在左边的子表中求最小值,冒泡一趟需要y-1次;
在右边的子表中求最大值,冒泡一趟需要z-1次;
合计需要(n-1)+(y-1)+(z-1)=n+y+z-3因为y+z+1=n,所以总次数=2n-4≤2n-3!
!
!
!
!
!
!
!
!
!
!
但最坏情况下仍为为2n-3次,即一趟完毕后仍为单子表的情况。
怎么办?
有无更好的办法?
法3:
能否用锦标赛排序思路?
求最大值等于求冠军,需要n—1次比较;但接着求最小值,等于在n/2个叶子中比较即可。
编程也不复杂:
可设计为,
第一趟:
n个数据两两比较(共n/2次),小者放偶数位,大者放奇数位;
第二趟:
对奇数位元素继续两两比较(n/4次);对偶数位元素也两两比较(n/4次);合计n/2次;
第三趟:
对奇数位元素继续两两比较(n/23次);对偶数位元素也两两比较(n/23次);合计n/22次;
第四趟:
对奇数位元素继续两两比较(n/24次);对偶数位元素也两两比较(n/24次);合计n/23次;
……
第log2n趟:
对奇数位元素继续两两比较(n/2log2n次=1);对偶数位元素也两两比较(1次);合计2次;
全部比较次数为:
2+4+8+……+n/2次≤2n-3(n>1)
用二进制性质即可证明?
因为20+21+…2k-2+2k-1<2k,即21+…2k-2+2k-1<2k—1<2k—1+2k—2
(n=2k,当k=1,即n=2时为极端情况,1=1;n=3时,1.5<3
k=2时,即n=4时,2<5
6.【成教考题】将两个长度为n的有序表归并为一个长度为2n的有序表,最小需要比较n次,最多需要比较2n-1次,请说明这两种情况发生时,两个被归并的表有何特征?
答:
最少的比较次数是这样一种情况:
若A表所有元素都小于(或大于)B表元素,则A1比较完B1~Bn之后,直接拼接即可。
最多比较次数的情况应该是A、B两表互相交错,此时需要穿插重排。
则A表的每个元素都要与B表元素相比,A1与B1相比,能确定其中一个元素的位置;剩下一个还要与另一表中下一元素再比较一次,
即:
在表A或表B的n个元素中,除了最后一个元素外,每个元素都要比较2次!
最坏情况总共为2n—1次。
7.【严题集10.11②】试问:
按锦标赛排序的思想,决出8名运动员之间的名次排列,至少需编排多少场次的比赛(应考虑最坏的情况)?
刘答:
不能简单地用(n-1)+(n-2)log2n来计算比赛场次。
要特别注意,随着n/2的叶子结点被调整完毕之后,树的深度会逐层减少!
分别n=8和n=7的情况推导并归纳,得到如下计算公式:
比赛场次=(n-1)+n/2(k-1)+(n/22)(k-2)+…+n/2(k-1),其中k=log2n
当n=8时,k=3,比赛场次=7+8/2
(2)+8/4=17场(这是最坏情况,即每次都先从叶子调整起)
8.【严题集10.19④】假设某大旅店共有5000个床位,每天需要根据住宿旅客的文件制造一份花名册,该名册要求按省(市)的次序排列,每一省(市)按县(区)排列,又同一县(区)的旅客按姓氏排列。
请你为旅店的管理人员设计一个制作这份花名册的方法。
(提示)这是一个多关键字的排序问题。
请思考对这个文件进行排序用哪一种方法更合适,是MSD法还是LSD法?
答:
采用哪种排序方法,关键要看记录的结构是如何定义的,如果旅客填表如下:
省(市)
县(区)
姓名
床位号
则按题意要求,应当采用MSD法,否则无法满足。
但若“姓名”项在前,则必须用LSD才符合题意要求。
9.【全国专升本题】【严题集10.6④】奇偶交换排序如下所述:
第一趟对所有奇数i,将a[i]和a[i+1]进行比较;第二趟对所有的偶数i,将a[i]和a[i+1]进行比较,若a[i]>a[i+1],则两者交换;第三趟对奇数i,第四趟对偶数i;……依次类推直至整个序列有序为止。
(1)试问这种排序方法的结束条件是什么?
是否为稳定排序?
(2)分析当初始序列为正序或逆序两种情况下,奇偶交换排序过程中所需进行的关键字比较的次数。
(3)分析此种排序方法的平均复杂度及最坏复杂度。
答:
(1)这种算法其实是两两比较,第一趟很像锦标赛的“初赛”,将胜者(大数)置于偶数单元;
第二趟对偶数单元操作,即第一组大者与第二组小者战,大者后移。
结果相当于冒泡排序的一趟;
所以结束条件应为偶数趟无交换。
结束条件是:
若n为偶数时,奇数循环时i>n-1,偶数循环时i>n,
若n为奇数时,奇数循环时i>n偶数循环时i>n+1
似乎不稳定?
因为交换没有依次进行。
四、【全国专升本类似题】【类严题集10.1①】以关键字序列(256,301,751,129,937,863,742,694,076,438)为例,分别写出执行以下算法的各趟排序结束时,关键字序列的状态,并说明这些排序方法中,哪些易于在链表(包括各种单、双、循环链表)上实现?
①直接插入排序②希尔排序③冒泡排序④快速排序
⑤直接选择排序⑥堆排序⑦归并排序⑧基数排序(8分)
解:
先回答第2问:
①⑤⑦⑧皆易于在链表上实现。
1直接插入排序的中间过程如下:
②希尔排序的中间过程如下:
3冒泡排序的中间过程如下:
④快速排序的中间过程如下:
5直接选择排序的中间过程如下:
⑥堆排序(大根堆)的中间过程如下:
7归并排序排序的中间过程如下:
8基数排序的中间过程如下:
五、算法设计题(4选2,每题7分,共14分)
1.【严题集10.25③】试编写教科书10.2.2节中所述链表插入排序的算法。
10.25
voidSLInsert_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].keyp=L.r[p].next;
q=L.r[p].next;
L.r[p].next=i;
L.r[i].next=q;
}//for
p=L.r[0].next;
for(i=1;i{
while(p
q=L.r[p].next;
if(p!
=i)
{
L.r[p]<->L.r[i];
L.r[i].next=p;
}
p=q;
}//for
}//SLInsert_Sort
2.【严题集10.30④】按下述原则编写快排的非递归算法:
(1)一趟排序之后,先对长度较短的子序列进行排序,且将另一子序列的上、下界入栈保存;
(2)若待排记录数≤3,则不再进行分割,而是直接进行比较排序。
10.30
typedefstruct{
intlow;
inthigh;
}boundary;//子序列的上下界类型
voidQSort_NotRecurve(intSQList&L)//快速排序的非递归算法
{
low=1;high=L.length;
InitStack(S);//S的元素为boundary类型
while(lowStackEmpty(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;
}
}//if
elseif(low{
Easy_Sort(L,low,high);//直接进行比较排序
low=high;//当前子序列标志为已排好序
}
else//如果当前子序列已排好序但栈中还有未排序的子序列
{
Pop(S,a);//从栈中取出一个子序列
low=a.low;
high=a.high;
}
}//while
}//QSort_NotRecurve
intPartition(SQList&L,intlow,inthigh)//一趟划分的算法,与书上相同
{
L.r[0]=L.r[low];
pivotkey=L.r[low].key;
while(low{
while(low=pivotkey)
high--;
L.r[low]=L.r[high];
while(lowlow++;
L.r[high]=L.r[low];
}//while
L.r[low]=L.r[0];
returnlow;
}//Partition
voidEasy_Sort(SQList&L,intlow,inthigh)//对长度小于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_Sort
3.【严题集10.41④】假设有1000个关键字为小于10000的整数的记录序列,请设计一种排序方法,要求以尽可能少的比较次数和移动次数实现排序,并按你的设计编出算法。
解:
可以用基数排序来实现,关键字位数d=4,数基radix=10(从0~9)
则基数排序的算法如下;
voidHash_Sort(inta[])//对1000个关键字为四位整数的记录进行排序
{
intb[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_Sort
4.【严题集10.42④】序列的“中值记录”指的是:
如果将此序列排序后,它是第[n/2]个记录。
试写一个求中值记录的算法。
10.42
typedefstruct{
intgt;//大于该记录的个数
intlt;//小于该记录的个数
}place;//整个序列中比某个关键字大或小的记录个数
intGet_Mid(inta[],intn)//求一个序列的中值记录的位置
{
placeb[MAXSIZE];
for(i=0;ifor(j=0;j{
if(a[j]>a[i])b[i].gt++;
elseif(a[j]}
mid=0;
min_dif=abs(b[0].gt-b[0].lt);
for(i=0;iif(abs(b[i].gt-b[i].lt)