版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第 10 章内部排序 习题练习答案1.以关键字序列 (265,301,751,129,937,863 ,742,694,076,438)为例,分别写出执行以下排序算法 的各趟排序结束时,关键字序列的状态。(1) 直接插入排序 (2)希尔排序 (3)冒泡排序 (4) 快速排序(5) 直接选择排序 (6) 堆排序 (7) 归并排序 (8) 基数排序 上述方法中,哪些是稳定的排序 ?哪些是非稳定的排序 ?对不稳定的排序试举出一个不稳定的实例。答:(1)直接插入排序 :(方括号表示无序区 )初始态 : 265301 751 129 937 863 742 694 076 438第一趟:265 3017
2、51 129 937 863 742 694 076 438第二趟:265 301 751129 937 863 742 694 076 438第三趟:129 265 301 751937 863 742 694 076 438第四趟:129 265 301 751 937863 742 694 076 438第五趟:129 265 301 751 863 937742 694 076 438第六趟:129 265 301 742 751 863 937694 076 438第七趟:129 265 301 694 742 751 863 937076 438第八趟:076 129 265 30
3、1 694 742 751 863 937438第九趟: 076 129 265 301 438 694 742 751 863 937(2) 希尔排序 (增量为 5,3, 1)初始态 :265 301 751 129 937 863 742 694 076 438第一趟:265 301 694 076 438 863 742 751 129 937第二趟:076 301 129 265 438 694 742 751 863 937第三趟:076 129 265 301 438 694 742 751 863 937(3) 冒泡排序 (方括号为无序区 )初始态 265 301 751 129
4、 937 863 742 694 076 438第一趟:076 265 301 751 129 937 863 742 694 438第二趟:076 129 265 301 751 438 937 863 742 694第三趟:076 129 265 301 438 694 751 937 863 742第四趟:076 129 265 301 438 694 742 751 937 863第五趟:076 129 265 301 438 694 742 751 863 937第六趟:076 129 265 301 438 694 742 751 863 937(4) 快速排序:(方括号表示无序区
5、,层表示对应的递归树的层数)初始态: 265 301 751 129 937 863 742 694 076 438第二层:076 129 265 751 937 863 742 694 301 438第三层:076 129 265 438 301 694 742 751 863 937第四层:076 129 265 301 438 694 742 751 863 937第五层:076 129 265 301 438 694 742 751 863 937第六层:076 129 265 301 438 694 742 751 863 937(5) 直接选择排序: ( 方括号为无序区 )初始态2
6、65 301 751 129 937 863 742 694 076 438第一趟:076 301 751 129 937 863 742 694 265 438第二趟:076 129 751 301 937 863 742 694 265 438第三趟:076 129 265 301 937 863 742 694 751 438第四趟:076 129 265 301 937 863 742 694 751 438第五趟:076 129 265 301 438 863 742 694 751 937第六趟:076 129 265 301 438 694 742 751 863 937第七趟:
7、076 129 265 301 438 694 742 751 863 937第八趟: 076 129 265 301 438 694 742 751 937 863第九趟:076 129 265 301 438 694 742 751 863 937(6)堆排序:(通过画二叉树可以一步步得出排序结果)初始态265 301 751 129 937 863 742 694 076 438建立初始堆:937 694 863 265 438 751 742 129 075 301第一次排序重建堆:863 694 751 765 438 301 742 129 075 937第二次排序重建堆:751
8、694 742 265 438 301 075 129 863 937第三次排序重建堆:742 694 301 265 438 129 075 751 863 937第四次排序重建堆:694 438 301 265 075 129 742 751 863 937第五次排序重建堆:438 265 301 129 075 694 742 751 863 937第六次排序重建堆:301 265 075 129 438 694 742 751 863 937第七次排序重建堆:265 129 075 301 438 694 742 751 863 937第八次排序重建堆:129 075265 301 4
9、38 694 742 751 863 937第九次排序重建堆:075 129 265 301 438 694 742 751 863 937(7)归并排序(为了表示方便,采用自底向上的归并,方括号为有序区)初始态: 265 301 751 129 937 863 742 694 076 438第一趟:265 301 129 751 863 937 694 742 076 438第二趟:129 265 301 751 694 742 863 937 076 438第三趟:129 265 301 694 742 751 863 937 076 438第四趟:076 129 265 301 438
10、694 742 751 863 937(8) 基数排序(方括号内表示一个箱子共有10 个箱子,箱号从 0 到 9)初始态: 265 301 751 129 937 863 742 694 076 438第一趟: 301 751 742 863 694 265 076 937 438 129第二趟:301 129 937 438 742 751 863 265 076 694第三趟:075 129 265 301 438 694 742 751 863 937在上面的排序方法中,直接插入排序、冒泡排序、归并排序和基数排序是稳定的,其他排序算法均是 不稳定的,现举实例如下:以带 * 号的表示区别。
11、希尔排序: 8,1,10,5,6,*8快速排序:2,*2,1直接选择排序: 2,*2,1堆排序:2,*2,12.上题的排序方法中,哪些易于在链表(包括各种单、双、循环链表 )上实现 ?答: 上题的排序方法中,直接插入排序、冒泡排序、直接选择排序、基数排序和归并排序等方法易于在链 表上实现。?能否修改RecType3. 当 Rlow.high 中的关键字均相同时, Partion 返回值是什么 ?此时快速排序的的运行时间是多少Partion,使得划分结果是平衡的(即划分后左右区间的长度大致相等)?答:此时 Partion 返回值是 low. 此时快速排序的运行时间是(high-low)(high
12、-low-1)/2=O(high-low)A2),可以修改 Partion ,将其中 RecType pivot=Ri;句改为:pivot=R(j+i)/2 ;也就是取中间的关键字为基准,这样就能使划分的结果是平衡的。4. 若文件初态是反序的,则直接插入,直接选择和冒泡排序哪一个更好?答:应选直接选择排序为更好。分析如下:(1) 在直接插入排序算法中,反序输入时是最坏情况,此时:关键字的比较次数: Cmax=(n+2)(n-2)/2;记录移动次数为: Mmax=(n-1)(n+4)/2;Tmax=nA2-4n-3 (以上二者相加)(2) 在冒泡排序算法中,反序也是最坏情况,此时:Cmax=n(
13、n-1)/2; Mmax=3n(n-1)/2Tmax=2nA2-2n(3) 在选择排序算法中,Cmax=n(n-1)/2 Mmax=3(n-1)Tmax=nA2/2-5n/2-3由此可见,虽然它们的时间复杂度都是O(nT),但是选择排序的常数因子为1/2,因此选择排序最省时间。5. 若文件初态是反序的,且要求输入稳定,则在直接插入、直接选择、冒泡和快速排序中就选选哪种方法 为宜?答: 这四种排序算法中,直接选择、快速排序均是不稳定的,因此先予以排除,剩下两种算法中,由于直接 插入算法所费时间比冒泡法更少 (见上题分析 ),因此选择直接排序算法为宜。6. 有序数组是堆吗 ?答: 有序数组是堆。因
14、为有序数组中的关键字序列满足堆的性质。若数组为降序,则此堆为大根堆,反之为小根堆。7. 高度为 h 的堆中, 最多有多少个元素 ?最少有多少个元素 ?在大根堆中, 关键字最小的元素可能存放在堆的 哪些地方 ?答:高度为 h 的堆实际上为一棵高度为 h 的完全二叉树, 因此根据二叉树的性质可以算出, 它最少应有 2h-1 个元素;最多可有 2h-1 个元素 (注意一个有括号,一个没有 )。在大根堆中,关键字最小的元素可能存放在 堆的任一叶子结点上。8. 判别下列序列是否为堆 (小根堆或大根堆 ),若不是,则将其调整为堆:(1) (100,86,73,35,39,42,57,66,21);(2)
15、(12,70,33,65,24,56,48,92,86,33);(3) (103,97,56,38,66,23,42,12,30,52,06,20);(4) (05,56,20,23,40,38,29,61,35,76,28,100).答:堆的性质是:任一非叶结点上的关键字均不大于(或不小于 )其孩子结点上的关键字。据此我们可以通过画二叉树来进行判断和调整:(1) 此序列是大根堆。(2) 此序列不是堆,经调整后成为小根堆:(12 , 24, 33, 65, 33, 56, 48, 92, 86, 70)(3) 此序列是一大根堆。(4) 此序列不是堆,经调整后成为小根堆:(01 , 05, 20
16、, 23, 28, 38, 29, 56, 35, 76, 40, 100)9将两个长度为n的有序表归并为一个长度为 2n的有序表,最小需要比较n次,最多需要比较2n-1次,请 说明这两种情况发生时,两个被归并的表有何特征 ?答:前一种情况下,这两个被归并的表中其中一个表的最大关键字不大于另一表中最小的关键字,也就是 说,两个有序表是直接可以连接为有序的,因此,只需比较 n 次就可将一个表中元素转移完毕,另一个表 全部照搬就行了。另一种情况下,是两个被归并的有序表中关键字序列完全一样,这时就要按次序轮流取其元素归并, 因此比较次数达到 2n-1.10.设关键字序列为 (0.79, 0.13,
17、0.16, 0.64, 0.39, 0.20, 0.89, 0.53, 0.71, 0.42),给出桶排序的结果。 答:桶排序的结果如图:B0.90 I A II11 I 0.13 t0.16 t AI12I t0.20t AI13It0.39 t AI14 I 0.42 AI15I0.53 AI16I0.64 AI17 I 0.71 0.79 AI18 I 0.89 AI19 I A I丨 丨结果为: 0. 1 3 0.16 0.20 0.39 0.42 0.53 0.64 0.71 0.79 0.891 1 .若关键字是非负整数、快速排序、归并、堆和基数排序啊一个最快?若要求辅助空间为 O
18、( 1 ),则应选择谁? 若要求排序是稳定的,且关键字是实数,则应选择谁?答:若关键字是非负整数,则基数排序最快;若要求辅助空间为0(1),则应选堆排序;若要求排序是稳定的, 且关键字是实数,则应选归并排序,因为基数排序不适用于实数,虽然它也是稳定的12. 对于 8.7 节的表 8.2,解释下述问题:(1) 当待排序的关键字序列的初始态分别为正序和反序时, 为什么直接选择排序的时间基本相同?若采用本书 8.4.1 节的算法,这两种情况下的排序时间是否基本相同 ?(2) 为什么数组的初态为正序时,冒泡和直接插入排序的执行时间最少 ?(3) 若采用 8.3.2 节的快速排序,则数组初态为正序和反序
19、时,能得到与表 8.2 类似的结果吗 ?答:(1) 由于在直接选择排序中,主要的操作是比较操作和移动操作。无论文件的初始状态如何,若文件有 n 个记录,则都要进行 n-1 趟直接选择排序,第 i 趟直接选择排序中都要做 n-i 次比较才能选出最小关键字的 记录。所以总的比较次数都为0(n2)。至于记录的移动次数,初始文件为正序时,移动次数为0,当文件初始时为反序,总的移动次数为3(n-1)。因此当待排序的关键字序列的初始态分别为正序和反序时,直接选择排序的时间基本相同,为O(n2)。若采用本书8.4.1节的算法,这两种情况下的排序时间基本相同。(2) 当冒泡排序是正序时,只需做一趟冒泡排序就可
20、完成,共做n-1 次比较,移动次数为 0,所以执行时间最少。而直接插入排序时,若初始为正序,则做了 n-1 趟直接插入排序,但每趟排序只做了一次比较,共做 n-1 次比较。移动次数为 0。所以当数组初态为正序,直接插入排序时间也最少。(3) 不能,其中辅助空间不同13. 将哨兵放在Rn中,被排序的记录放在R0.n-1中,重写直接插入排序算法。解:重写的算法如下:void InsertSort(SeqList R)/对顺序表中记录R0.n-1按递增序进行插入排序int i,j;for(i=n-2;i=0;i-) / 在有序区中依次插入 Rn-2.R0if(Ri.keyRi+1.key)/若不是这
21、样则Ri原位不动Rn=Ri;j=i+1; /Rn 是哨兵do / 从左向右在有序区中查找插入位置Rj-1=Rj; / 将关键字小于 Ri.key 的记录向右移 j+;while(Rj.keynext)&(head-next-next)/ 当表中含有结点数大于 1 p=head-next-next;/p 指向第二个节点 head-next=NULL;q=head;指向插入位置的前驱节点 while(p)&(q-next)&(p-keynext-key) q=q-next;if (p)s=p;p=p-next;/ 将要插入结点摘下s-next=q-next;/ 插入合适位置: q 结点后q-nex
22、t=s;15. 设计一算法, 使得在尽可能少的时间内重排数组,将所有取负值的关键字放在所有取非负值的关键字之前。请分析算法的时间复杂度。解:因为只需将负数关键字排在前面而无需进行精确排列顺序,因此本算法采用两端扫描的方法,就象快 速排序采用的方法一样,左边扫描到正数时停止,开始扫描右边,遇到负数时与左边的当前记录交换,如 此交替进行,一趟下来就可以完成排序。void ReSort(SeqList R)/ 重排数组,使负值关键字在前int i=1,j=n; / 数组存放在 R1.n 中while (ij) /ij 表示尚未扫描完毕 while(ij&Ri.key0) / 遇到负数则继续扫描i+;
23、R0=Ri; /R0 为辅助空间while(i=0)/ 遇到正数则继续向左扫描j-;Ri+=Rj;Rj-=R0;/交换当前两个元素并移动指针/endwhile/ReSort本算法在任何情况下的比较次数均为n(每个元素和0)相比,交换次数少于n/2,总的来说,时间复杂度为 O(n).*16.写一个双向冒泡排序的算法,即在排序过程中交替改变扫描方向。 解:算法如下:void BubbleSort(SeqList R)/R1.n 是待排序文件,双向扫描冒泡排序int i,j,k;Boolean exchange; / 交换标记i=n;j=1;exchange=TRUE;while (ij)&(exc
24、hange)k=i-1;exchange=FALSE;while (k=j)/ 由下往上扫描交换交换if (rkrk+1)r0=rk;rk=rk+1;rk+1=rk;exchange=TRUE;/endifk-;/endwhileif (exchange)exchange=FALSE;j+;k=j+1;while(k=i)/ 由上往下扫描if (rk0)lastExchange=0;for(j=0;ji;j+)/ 从上往下扫描 A0.iif(Aj+1Aj)交换 Aj 和 Aj+1;lastExchange=j;i=lastExchange;/ 将 i 置为最后交换的位置/endwhile/Bu
25、bbleSort解:算法如下:void BubbleSort(int A,int n)/ 不妨设 A0.n-1 是整型向量int lastExchange,j,i=0;while (ii;j-)/ 从下往上扫描 A0.iif(Aj-1Aj)交换 Aj 和 Aj-1;lastExchange=j;i=lastExchange;/ 将 i 置为最后交换的位置/endwhile若当前被排序的区间长度小于等于/BubbleSort18. 改写快速排序算法, 要求采用三者取中的方式选择划分的基准记录;3 时,无须划分而是直接采用直接插入方式对其排序。解:改写后的算法如下:void QuickSort(S
26、eqList R,int low ,int high)/对 Rlow.high 快速排序int pivotpos;if(high-lowRi.key) 交换 R(i+j)/2 和 Ri;if(Ri.keyRj.key) 交换 Ri 和 Rj;if(Ri.key)R(i+j)/2.key) 交换 Ri 和 R(i+j)/2;/以上三个 if 语句就使区间的第一个记录的 key 值为三个 key 的中间值return Partion(R,i,j);/ 这样我们就可以仍使用原来的划分算法了19. 对给定的j(1 j 要求在无序的记录区R1.n中找到按关键字自小到大排在第j个位置上的记录(即在无序集合
27、中找到第 j 个最小元 ),试利用快速排序的划分思想编写算法实现上述的查找操作。答:int QuickSort(SeqList R,int j,int low,int high) / 对 Rlow.high 快速排序int pivotpos ; /划分后的基准记录的位置if(lowj) return(R,j,low,pivotpos-1);else return quicksort(R,j,pivotpos+1,high); /QuickSort20. 以单链表为存储结构,写一个直接选择排序算法。答:#define int KeyType / 定义 KeyType 为 int 型typedef
28、 struct nodeKeyType key; / 关键字域OtherInfoType info; / 其它信息域,struct node * next; / 链表中指针域RecNode; / 记录结点类型typedef RecNode * LinkList ; / 单链表用 LinkList 表示void selectsort(linklist head)RecNode *p,*q,*s;if(head-next)&(head-next-next)p=head-next;/p 指向当前已排好序最大元素的前趋while (p-next)q=p-next;s=p;while(q)if (q-k
29、eykey) s=q;q=q-next;/endwhile交换 s 结点和 p 结点的数据;p=p-next;/endwhile/endif/endsort21. 写一个 heapInsert(R,key) 算法,将关键字插入到堆 R 中去,并保证插入 R 后仍是堆。提示:应为堆 R 增加一个长度属性描述 ( 即改写本章定义的 SeqList 类型描述,使其含有长度域 );将 key 先插入 R 中已有 元素的尾部 (即原堆的长度加 1的位置, 插入后堆的长度加 1),然后从下往上调整, 使插入的关键字满足性 质。请分析算法的时间。答:#define n 100/ 假设文件的最长可能长度typ
30、edef int KeyType; / 定义 KeyType 为 int 型typedef struct nodeKeyType key; / 关键字域OtherInfoType info; / 其它信息域,Rectype; / 记录结点类型typedef structRectype datan ; / 存放记录的空间int length;/ 文件长度seqlist;void heapInsert(seqlist *R,KeyType key)/ 原有堆元素在 R-data1R-dataR-length,/ 将新的关键字 key 插入到 R-dataR-length+1 位置后,/ 以 R-d
31、ata0 为辅助空间,调整为堆 (此处设为大根堆 )int large;/large 指向调整结点的左右孩子中关键字较大者int low,high;/low 和 high 分别指向待调整堆的第一个和最后一个记录 int i;R-length+ ; R-dataR-length.key=key;/ 插入新的记录 for(i=R-length/2;i0;i-)/ 建堆low=i;high=R-length;R-data0.key=R-datalow.key;/R-datalow 是当前调整的结点 for(large=2*low;largehigh,则表示 R-datalow是叶子,调整结束; /否
32、则令 large 指向 R-datalow 的左孩子 if(largedatalarge.keydatalarge+1.key) large+;若R-datalow的右孩子存在/且关键字大于左兄弟,则令large 指向它if (R-data0.keydatalarge.key) R-datalow.key= R-datalarge.key;low=large;令low指向新的调整结点else break;/当前调整结点不小于其孩子结点的关键字,结束调整 /endforR-datalow.key=R-data0.key;/ 将被调整结点放入最终的位置上 /end of forend of hea
33、pinsert算法分析:设文件长度为n,则该算法需进行n/2趟调整,总的时间复杂度与初建堆类似,最坏时间复杂度为O(nlgn),辅助空间为0(1).22. 写一个建堆算法:从空堆开始,依次读入元素调用上题中堆插入算法将其插入堆中。答:void BuildHeap(seqlist *R)KeyType key;R-length=0;/ 建一个空堆scanf(%d,&key);/ 设 MAXINT 为不可能的关键字while(key!=MAXINT)heapInsert(R,key);scanf(%d,&key);23. 写一个堆删除算法:HeapDelete(R,i),将Ri从堆中删去,并分析算
34、法时间,提示:先将Ri和堆中最后一个元素交换,并将堆长度减 1 ,然后从位置 i 开始向下调整,使其满足堆性质。答:void HeapDelete(seqlist *R,int i)/ 原有堆元素在 R-data1R-dataR-length,/将 R-datai 删除,即将 R-dataR-length 放入 R-datai 中后,/将 R-length 减 1,再进行堆的调整,/以R-dataO为辅助空间,调整为堆(此处设为大根堆)int large;/large 指向调整结点的左右孩子中关键字较大者int low,high;/low 和 high 分别指向待调整堆的第一个和最后一个记录i
35、nt j;if (iR-length)Error(have no such node);R-datai.key=R-dataR-length.key;R-length- ; R-dataR-length.key=key;/ 插入新的记录for(j=i/2;j0;j-)/ 建堆low=j;high=R-length;R-data0.key=R-datalow.key;/R-datalow 是当前调整的结点for(large=2*low;largehigh,则表示 R-datalow是叶子,调整结束;/否则令 large 指向 R-datalow 的左孩子if(largedatalarge.key
36、datalarge+1.key)large+;若R-datalow的右孩子存在/且关键字大于左兄弟,则令large 指向它if (R-data0.keydatalarge.key) R-datalow.key= R-datalarge.key;low=large;令low指向新的调整结点else break;/当前调整结点不小于其孩子结点的关键字,结束调整/endforR-datalow.key=R-data0.key;/ 将被调整结点放入最终的位置上/end of for算法应end of HeapDelete24. 已知两个单链表中的元素递增有序,试写一算法将这两个有序表归并成一个递增有序的单链表。利用原有的链表结点空间。答:typedef struct nodeKeyType key; / 关键字域OtherInfoType info; / 其它信息域,struct node * next; / 链表中指针域RecNode; / 记录结点类型typedef RecNode * LinkList ; / 单链表用 LinkList 表示void mergesort(LinkLi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 自身工作执行责任书5篇
- 信息技术与工业互联网平台建设方案
- 品牌个性化定制承诺书3篇
- 合作伙伴诚信合作承诺书8篇范文
- 教育培训机构招生诚信服务保证承诺书(7篇)
- 2025 高中信息技术数据结构链表的环检测与环入口查找课件
- 2025 高中信息技术数据结构的算法设计教学案例课件
- 技术创新承诺书为创新发展献力范文3篇
- 旅行爱好者旅行攻略规划旅行指导书
- 智能制造项目管理流程与风险控制手册
- DB22-T 3408-2022 建设用地项目节地评价论证规范
- 江南造船在线测评题
- 癌症患者生活质量量表EORTC-QLQ-C30
- 实验室计量器器具校准操作规程
- DL∕T 547-2020 电力系统光纤通信运行管理规程
- 电气控制与PLC教案电气控制与PLC教案
- 建筑材料说课公开课一等奖市赛课获奖课件
- 湖南2023年长沙银行理财经理社会招聘(37)考试参考题库含答案详解
- 混凝土搅拌车维护保养
- 薄膜的物理气相沉积
- 铣刨加罩道路工程施工组织设计方案
评论
0/150
提交评论