排序.docx
- 文档编号:11001566
- 上传时间:2023-02-24
- 格式:DOCX
- 页数:42
- 大小:349.12KB
排序.docx
《排序.docx》由会员分享,可在线阅读,更多相关《排序.docx(42页珍藏版)》请在冰豆网上搜索。
排序
第8章排序
内容概要:
本章主要介绍各种内排序方法的基本思想、实现算法和性能,并在综合应用设计中,给出了各种排序算法的C语言实现
教学目标
1.理解各种排序方法的基本思想。
2.掌握各种排序方法的实现算法并理解其算法的性能。
3.通过综合应用设计,掌握各种排序算法的C语言实现过程。
基本知识点:
排序的概念;各种排序的方法。
重点:
各种排序算法的性能特点;各种排序算法的比较和选择。
难点:
复杂排序算法设计。
本章知识体系结构:
课时安排:
6个课时
课程
数据结构
教学教具
多媒体课件
学时
2
班级
06网络
教学日期/课时
/2课时
教学单元
第8章排序
教学方法
讲授(PPT)
教学目标
1.理解插入排序、交换排序、选择排序的基本思想。
2.掌握插入排序、交换排序和选择排序的实现算法并理解其算法的性能。
教学重点
插入排序、交换排序和选择排序方法及性能特点
教学难点
算法性分析
组
织
教
学
一、导入新课
二、插入排序
三、交换排序
四、选择排序
五、小结
作
业
复习本讲内容并预习下一讲内容
课堂情况及
课后分析
课程
数据结构
教学教具
多媒体课件
学时
2
班级
06网络
教学日期/课时
/2课时
教学单元
第8章排序
教学方法
讲授(PPT)
教学目标
1.理解二路归并排序、基数排序、自然排序的基本思想。
2.掌握二路归并排序、基数排序、自然排序的实现算法并理解其算法的性能。
教学重点
二路归并排序、基数排序、自然排序方法及性能特点
教学难点
算法性分析
组
织
教
学
一、导入新课
二、二路归并排序
三、基数排序
四、自然排序
五、小结
作
业
习题8
课堂情况及
课后分析
课程
数据结构
教学教具
多媒体课件
学时
2
班级
06网络
教学日期/课时
/2课时
教学单元
第8章排序
教学方法
讲授(PPT)
教学目标
1.理解选择排序的基本思想。
2.掌握选择排序的实现算法并理解其算法的性能。
教学重点
插入排序、交换排序和选择排序方法及性能特点
教学难点
算法性分析
组
织
教
学
六、导入新课
七、插入排序
八、交换排序
九、选择排序
一十、小结
作
业
复习本讲内容并预习下一讲内容
课堂情况及
课后分析
排序(Sorting)是程序设计中的一种重要操作,是按数据元素的某个项值有序重排数据元素集合或序列中各数据元素位置的操作。
作为排序依据的数据项称为“排序码”,也即数据元素的关键码。
当计算机中的数据表按关键码有序时,便于查找其中的数据,如有序表的折半查找,具有较高的查找效率。
若关键码是主关键码,则对于任意待排序序列,经排序后得到的结果是唯一的;若关键码是次关键码,排序结果可能不唯一,这是因为有相同关键码的数据元素,这些元素在排序结果中,它们之间的位置关系与排序前不一定能保持一致。
使用某个排序方法,对任意的数据元素序列按关键码进行排序:
若相同关键码元素间的位置关系在排序前与排序后保持一致,称此排序方法是稳定的;不能保持一致的排序方法称为不稳定的。
排序分为两类:
内排序和外排序。
内排序:
指待排序列完全存放在内存中所进行的排序(适合数量不太大的元素序列)。
外排序:
指排序过程中还需访问外存储器的方法。
对于数量足够大的元素序列,因不能同时放入内存,只能使用外排序。
8.1插入排序
8.1.1直接插入排序
直接插入排序方法的基本思想是:
先将存放于数组中的第一个数据元素看成是一个有序的子序列,然后从第2个数据元素起逐个按序插入到有序子序列中(每插入一个就使有序子序列中数据的个数加1),直到整个序列有序为止。
例8-1设待排序数列为:
46,25,51,32,11,76,88,65,18。
直接插入排序过程如下:
初始序列462551321176886518
视第一个数为一个有序的子序列有:
46)2551321176886518
把第2个数插入有序子序列得:
2546)51321176886518
把第3个数插入有序子序列得:
254651)321176886518
把第4个数插入有序子序列得:
25324651)1176886518
…
把第9个数插入有序子序列得(最终结果)111825324651657688
1.直接插入排序算法(升序)描述
(1)从数列中取出第2个元素a2,如果a1>a2,则把a1向后移动一个位置;把a2放在a1的原位置,转下一步;否则把a2放回其原位置,转下一步。
(2)从数列中取出第3个元素a3,依次与第2、第1个元素进行比较,在比较的过程中如果某一个元素大于a3,则使其向后移动一个位置后再与下一个进行比较,如果都大于a3,则把a3方在第一个位置;转下一步;如果某一个元素小于a3,则把a3放入空出来的位置;转下一步。
(3)(i-1)从数列中取出第i个元素ai,依次与第i-1、第i-2、…、第1个(共i-1个)元素进行比较,在比较的过程中如果某一个元素大于ai,则使其向后移动一个位置后再与下一个进行比较,如果都大于ai,则把ai放在第一个位置;转下一步;如果某一个元素小于ai,则把ai放入空出来的位置;转下一步。
(4)当i-1=n时算法结束。
直接插入排序算法的流程图如图8-1,其中待排序数列存放在一维数组A[n]中,变量m用于存放待插入的元素。
2.直接插入排序算法的效率分析
空间效率:
仅用了一个辅助单元。
时间效率:
向有序表中逐个插入数据的操作,进行了n-1趟,每趟操作分为比较关键码和移动数据,而比较的次数和移动数据的次数取决于待排序列按关键码的初始排列。
最好情况下:
即待排序列已按关键码有序,每趟操作只需1次比较2次移动。
总比较次数=n-1次
总移动次数=2(n-1)次
最坏情况下:
即第j趟操作,插入数据需要同前面的j个数据进行j次关键码比较,移动数据的次数为j+2次。
平均情况下:
即第j趟操作,插入数据大约同前面的j/2个记录进行关键码比较,移动数据的次数为j/2+2次。
由此,直接插入排序的时间复杂度为O(n2)。
是一个稳定的排序方法。
8.1.2折半插入排序
直接插入排序的基本操作是向有序子序列中插入一个数据,插入位置的确定通过对有序子序列中记录按关键码逐个比较得到的。
平均情况下总比较次数约为n2/4。
既然是在有序表中确定插入位置,自然可以利用折半查找的方法来确定插入位置,即:
通过待插入数据与有序子序列中的中间数据的关键码的比较,将有序子序列一分为二,下次比较时只在其中一个有序子序列中进行即可,这样继续下去,直到要比较的子表中只有一个数据时,比较一次便可确定插入位置。
例8-2设有数列:
810151618222639521935。
其中52之前的9个数已有序,用折半插入方法把第10个数19插入有序子序列的过程如下:
(1)确定待插入位置:
取出待插入的数19与位于有序子序列中间的数(( 9+1)/2=5)即第5个数18进行比较,由19>18知待插入位置在第5个数之后;把19再与位于第5个和第9个数中间的数((5+9)/2=7)即第7个数26进行比较,由19<26知待插入位置在第7个数之前(第5个数之后);把19再与位于第5个和第7个数中间的数((5+7)/2=6)即第6个数22进行比较,由19<22知待插入位置在第6个数之前(第5个之后)即待插入位置为6。
序子序列中待插入位置及其之后各位置上的数依次向后移动一个位置有:
8101516182226395235。
(2)把数19送入待插入位置6得:
810151618192226395235
插入过程结束。
设待排序数列存放于一维数组r[n]中,r[j].key表示第j个数据的排序码,若用low和high分别表示待插入数据预插入区间的最前和最后一个数据所在的位置,m表示该区间的中间位置,则折半插入排序算法可描述如下:
1.折半插入排序算法描述
(1)low=1;high=j-1;r[0]=r[j];(有序子序列长度为j-1,第j个数据为待插入数据,设置有序子序列区间,待插入数据送辅助单元r[0])
(2)若low>high,得到插入位置,转(5)
(3)low≤high,m=(low+high)/2;(取有序表的中点,并将表一分为二,确定待插入区间)
(4)若r[0].key (2) (5)(high+1即为待插入位置),从j-1到high+1的数据,逐个后移一个位置,r[high+1]=r[0](放置待插入数据)。 2.折半插入排序方法的时间效率 由于确定插入位置采用了折半查找,关键码的比较次数至多为log2(n+1)次,移动数据的次数和直接插入排序相同,故时间复杂度仍为O(n2)。 是一个稳定的排序方法。 8.1.3表插入排序 直接插入排序、折半插入排序均要大量移动数据,时间开销大。 若要不移动数据完成排序,则需要改变数据的存储结构。 所谓表插入排序,就是通过链接指针,按关键码的大小,实现从小到大的链接过程,为此需增设一个指针项。 操作方法与直接插入排序类似,所不同的是直接插入排序要移动记录,而表插入排序是修改链接指针。 用静态链表来说明,即: 在存储数据元素时为数据元素增加一个数据项,用于存放相邻的下一数据元素的存放位置的信息,并把数据存放在一个数组之中。 例如有8个数据 为每个数据增加一个指针数据项后变为: 假设数据元素已存储在静态链表中,且0号单元作为头结点,不移动数据而只是改变链指针域,将数据建为一个有序链表的方法如下: 首先,设置空的循环链表,即头结点指针域置0,并在头结点数据域中存放比所有记录关键码都大的整数MAXINT。 接下来,逐个结点向链表中插入即可。 例8-3表插入排序示例 MAXINT 49 38 65 97 76 13 27 49 0 - - - - - - - - 视第1个数49为一个有序子序列,头结点指向有序子序列中第1个数所在的位置,即0.next=1;有序子序列中最后一个数所在位置的next域值为0,即1.next=0;得 MAXINT 49 38 65 97 76 13 27 49 1 0 - - - - - - - 取出数组中第2个数据38(作为待插入数据);由第0个元素的0.next=1知有序子序列中第1个数据的位置为1,数据为49,由于49>38,应插入38到49之前,即有序子序列中现有两个数据38和49,0.next=2指出有序子序列中第1个数据的位置,2.next=1指出有序子序列中第2个数据的位置,1.next=0表示1中数据是有序子序列的最后一个数据。 所以有: MAXINT 49 38 65 97 76 13 27 49 2 0 1 - - - - - - 取出数组中第3个数据65(作为待插入数据);由第0个元素的0.next=2知有序子序列中第1个数据38的位置为2,值为38,由于65>38(不应插在38之前),再由2.next=1知有序子序列中第2个数据49的位置,由于65>49(也不应插在49之前),再由1.next=0知49是有序子序列的最后一个数据,所以插入65作为有序子序列的最后一个数据,即有序子序列中现有3个数据38,49和65,0.next=2指出有序子序列中第1个数据的位置,2.next=1指出有序子序列中第2个数据的位置,1.next=3指出有序子序列中第3个数据的位置,3.next=0表示3中数据是有序子序列的最后一个数据。 所以有: MAXINT 49 38 65 97 76 13 27 49 2 3 1 0 - - - - - 与前两步类似可得以后各步结果如下: MAXINT 49 38 65 97 76 13 27 49 2 3 1 4 0 - - - - MAXINT 49 38 65 97 76 13 27 49 2 3 1 5 0 4 - - - MAXINT 49 38 65 97 76 13 27 49 6 3 1 5 0 4 2 - - MAXINT 49 38 65 97 76 13 27 49 6 3 1 5 0 4 7 2 - MAXINT 49 38 65 97 76 13 27 49 6 8 1 5 0 4 7 2 3 设p,q为同类型指针变量,用p->key表示p所指数据的值域,p->next表示p所指数据的指针域,q用于指向有续子序列中p所指数据的前一个数据,从第2步开始,第i步(2≤i≤n)的比较和插入过程也即表插入排序算法如下: 1.表插入排序算法描述 (1)如果i>n,则排序结束,否则,取q=&0(为第0个元素的地址);p=0.next(为第0个元素的指针域) (2)如果p->key (2)(继续与下一个数据比较) (3)如果p->key (1) (4)如果p->key≥ⅰ.key,则i.next=p;q->next=i(插入待插入数据到第1个比它大的数据之前);i=i+1;转 (1) 表插入排序得到一个有序的链表,查找则只能进行顺序查找,而不能进行随机查找,如折半查找。 为此,还需要对记录进行重排。 重排记录方法: 按链表顺序扫描各结点,将第i个结点中的数据元素调整到数组的第i个分量数据域。 因为第i个结点可能是数组的第j个分量,数据元素调整仅需将两个数组分量中数据元素交换即可,但为了能对所有数据元素进行正常调整,指针域也需作处理。 例8-4对表插入排序结果进行重排示例 MAXINT 49 38 65 97 76 13 27 49 6 8 1 5 0 4 7 2 3 由r[0].next=6知有序数列的第1个数存于r[6]中,指针p=r[6].next=7指出有序数列的下一个数存放在r[7]中,交换r[1]和r[6]中的数据及位置信息next值,并将r[1].next由7改为6(用于表明原来在r[1]中的内容已移到r[6]中)得: MAXINT 13 38 65 97 76 49 27 49 6 (6) 1 5 0 4 8 2 3 由p=7知有序数列的第2个数存于r[7]中,指针p=r[7].next=2即有序数列的下一个数存放的位置,交换r[2]和r[7]中的数据及位置信息next值,并将r[2].next由2改为7(用于表明原来在r[2]中的内容已移到r[7]中)得: 由p=7知有序数列的第2个数存于r[7]中,指针p=r[7].next=2即有序数列的下一个数存放的位置,交换r[2]和r[7]中的数据及位置信息next值,并将r[2].next由2改为7(用于表明原来在r[2]中的内容已移到r[7]中)得: MAXINT 13 27 65 97 76 49 38 49 6 (6) (7) 5 0 4 8 1 3 由p=2知有序数列的第3个数存于r[2]中(由于原来在r[2]中的数据已移走,并由现r[2]中的r[2].next=7知被移到r[7]中),指针p=r[7].next=1即有序数列的下一个数存放的位置,交换r[3]和r[7]中的数据及位置信息next的值,并将r[3].next由原来的1改为7(用于表明原来在r[3]中的内容已移到r[7]中)得: MAXINT 13 27 38 97 76 49 65 49 6 (6) (7) (7) 0 4 8 5 3 与前几步类似可得其以后各步的结果如下: MAXINT 13 27 38 49 76 97 65 49 6 (6) (7) (7) (6) 4 0 5 3 MAXINT 13 27 38 49 49 97 65 76 6 (6) (7) (7) (6) (8) 0 5 4 MAXINT 13 27 38 49 49 65 97 76 6 (6) (7) (7) (6) (8) (7) 0 4 MAXINT 13 27 38 49 49 65 76 97 6 (6) (7) (7) (6) (8) (7) (8) 0 2.重排算法 (1)p=r[0].next;i=1;(指向第一个数据位置,从第一个数据开始调整) (2)若i=n+1时,调整结束;否则, a.若i=p,p=r[p].next;i++;转 (2)(数据元素应在这分量中,不用调整,处理下一个结点) b.若p>i,r[i].elem<-->r[p].elem;(交换数据元素) j=r[p].next;(保存下一个结点地址) r[p].next=r[i].next;r[i].next=p;(修改位置信息,保持后续链表不被中断) p=j;i++;(指向下一个处理的结点)转 (2) c.若p 3.表插入排序的时间效率 表插入排序的基本操作是将一个数据插入到已排好序的有序链表中,设有序表长度为i,则需要比较至多i+1次,修改指针两次。 因此,总比较次数与直接插入排序相同,修改指针总次数为2n次。 所以,时间复杂度仍为O(n2)。 8.1.4希尔排序(Shell’sSort) 希尔排序又称缩小增量排序,是1959年由D.L.Shell提出来的,较前述几种插入排序方法有较大的改进。 直接插入排序算法简单,在n值较小时,效率比较高,在n值很大时,若序列按关键码基本有序,效率依然较高,其时间效率可提高到O(n)。 希尔排序即是从这两点出发,给出插入排序的改进方法。 希尔排序方法: 1.选择一个步长序列t1>t2>…>tk,tk=1; 2.按步长序列个数k,对序列进行k趟排序; 3.第i趟排序,以ti为间隔,将待排序列分割成ti个子序列,并分别对各子序列进行直接插入排序。 例8-5待排序列为39,80,76,41,13,29,50,78,30,11,100,7,41,86。 步长因子分别取5、3、1,则排序过程如下: p=53980764113295078301110074186 └──────---------───┴──────----------───┘ └─────---------────┴──────--------────┘ └────────---------─┴──────--------────┘ └───────---------──┴─────────-------─┘ └───────---------──┘ 子序列分别为{39,29,100},{80,50,7},{76,78,41},{41,30,86},{13,11}。 对各子序列排序后得: 子序列分别为{29,30,50,13,78},{7,11,76,100,86},{41,39,41,80}。 对各子序列排序后得: p=11373929114130764150868078100 此时,序列基本“有序”,对其进行直接插入排序,得到最终结果: 7111329303941415076788086100 设由n个数组成的待排序序列存储在一维数组e[n]中,k为步长因子,x为一中间变量。 一趟增量为k的插入排序算法如下: 依次对k个子序列进行直接插入排序,其中第m个子序列的排序算法如下: (即用直接插入排序方法,对e[n]中元素: e[m],e[m+k],e[m+2k]……e[m+i*k]进行排序,其中m+i*k≤n) (1)从数列中取出第2个元素x=e[m+k],如果e[m]>e[m+k],则e[m+k]=e[m];e[m]=x;(即把e[m]向后移动一个位置;把e[m+k]放在e[m]的原位置),转 (2)。 (2)从数列中取出第3个元素x=e[m+2k],依次与e[m+k]、e[m]进行比较,在比较的过程中如果某一个e[r](r=m或m+k)大于e[m+2k],则使其向后移动一个位置(即e[r+k]=e[r])后再与下一个进行比较,如果都大于e[m+2k],则e[m]=x(即放在最前一个位置);转下一步;如果某一个e[r]小于e[m+2k],则把e[m+2k]放入空出来的位置(即e[r+k]=x);转下一步。 ……… (i)从数列中取出第i+1个元素x=e[m+i*k],依次与e[m+(i-1)*k]、e[m+(i-2)*k]、…、…、e[m+k]、e[m]进行比较,在比较的过程中如果某一个e[r]大于e[m+i*k],则使其向后移动一个位置(即e[r+k]=e[r])后再与下一个进行比较,如果都大于e[m+i*k],则e[m]=x(即放在最前一个位置);转下一步;如果某一个e[r]小于e[m+i*k],则e[r+k]=x(即放入空出来的位置);转下一步。 ………… 当m+i*k>n时,第m个子序列的排序算法结束。 由于希尔排序算法仅为对不同的k,重复调用算法8-5,请读者作为作业自己给出希尔排序算法的一个完整的算法描述和对应的算法流程图。 希尔排序的时间效率 希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于步长因子序列的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。 目前还没有人给出选取最好的步长因子序列的方法。 步长因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意: 步长因子中除1外没有公因子,且最后一个
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 排序