数据结构-排序.ppt
《数据结构-排序.ppt》由会员分享,可在线阅读,更多相关《数据结构-排序.ppt(118页珍藏版)》请在三一办公上搜索。
1、第10章 内部排序,10.1 概述,10.2 插入排序,10.3 快速排序,10.4 堆排序,10.5 归并排序,10.6 基数排序,10.7 各种排序方法的综合比较,10.1 概 述,一、排序的定义,二、内部排序和外部排序,三、内部排序方法的分类,一、什么是排序?,排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。,例如:将下列关键字序列,52,49,80,36,14,58,61,23,97,75,调整为,14,23,36,49,52,58,61,75,80,97,1.什么是排序?将一组杂乱无章的数据按一定的规律顺次排列起来。,2.排序的目的是什么?
2、,存放在数据表中,按关键字排序,3.排序算法的好坏如何衡量?时间效率排序速度(即排序所花费的全部比较次数)空间效率占内存辅助空间的大小稳定性若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。,便于查找!,二、内部排序和外部排序,若待排序记录都在内存中,整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序;,反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中 完成,则称此类排序问题为外部排序。,三、内部排序的方法,内部排序的过程是一个逐步扩大记录的有序序列长度的过程。,经过一趟排序,有序序列区,无 序 序 列 区,有序序列区,无
3、序 序 列 区,基于不同的“扩大”有序序列长度的方法,内部排序方法大致可分下列几种类型:,插入类,交换类,选择类,归并类,基数排序,待排记录的数据类型定义如下:,#define MAXSIZE 1000/待排顺序表最大长度,typedef int KeyType;/关键字类型为整数类型,typedef struct KeyType key;/关键字项 InfoType otherinfo;/其它数据项 RcdType;/记录类型,typedef struct RcdType rMAXSIZE+1;/r0闲置 int length;/顺序表长度 SqList;/顺序表类型,1.插入类,将无序子序
4、列中的一个或几个记录“插入”到有序序列中,从而增加记录的有序子序列的长度。,2.交换类,通过“交换”无序序列中的记录从而得到其中关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。,3.选择类,从记录的无序子序列中“选择”关键字最小或最大的记录,并将它加入到有序子序列中,以此方法增加记录的有序子序列的长度。,4.归并类,通过“归并”两个或两个以上的记录有序子序列,逐步增加记录有序序列的长度。,10.2 插 入 排 序,插入排序的基本思想是:,每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。,简言之,边插
5、入边排序,保证子序列中随时都是排好序的,有序序列R1.i-1,Ri,无序序列 Ri.n,一趟直接插入排序的基本思想:,有序序列R1.i,无序序列 Ri+1.n,实现“一趟插入排序”可分三步进行:,3将Ri 插入(复制)到Rj+1的位置上。,2将Rj+1.i-1中的所有记录均后移 一个位置;,1在R1.i-1中查找Ri的插入位置,R1.j.key Ri.key Rj+1.i-1.key;,直接插入排序(基于顺序查找),表插入排序(基于链表存储),不同的具体实现方法导致不同的算法描述,折半插入排序(基于折半查找),希尔排序(基于逐趟缩小增量),1)直接插入排序,新元素插入到哪里?,例1:关键字序列
6、T=(13,6,3,31,9,27,5,11),请写出直接插入排序的中间过程序列。,【13】,6,3,31,9,27,5,11【6,13】,3,31,9,27,5,11【3,6,13】,31,9,27,5,11【3,6,13,31】,9,27,5,11【3,6,9,13,31】,27,5,11【3,6,9,13,27,31】,5,11【3,5,6,9,13,27,31】,11【3,5,6,9,11,13,27,31】,在已形成的有序表中线性查找,并在适当位置插入,把原来位置上的元素向后顺移。,最简单的排序法!,一、直接插入排序,利用“顺序查找”实现“在R1.i-1中查找Ri的插入位置”,算法的
7、实现要点:,从Ri-1起向前进行顺序查找,监视哨设置在R0;,R0=Ri;/设置“哨兵”,循环结束表明Ri的插入位置为 j+1,R0,j,Ri,for(j=i-1;R0.keyRj.key;-j);/从后往前找,j=i-1,插入位置,对于在查找过程中找到的那些关键字不小于Ri.key的记录,并在查找的同时实现记录向后移动;,for(j=i-1;R0.keyRj.key;-j)Rj+1=Rj,R0,j,Ri,j=i-1,上述循环结束后可以直接进行“插入”,插入位置,令 i=2,3,,n,实现整个序列的排序。,for(i=2;i=n;+i)if(Ri.keyRi-1.key)在 R1.i-1中查找
8、Ri的插入位置;插入Ri;,void InsertionSort(SqList+i)if(L.ri.key L.ri-1.key)/InsertSort,L.r0=L.ri;/复制为监视哨for(j=i-1;L.r0.key L.rj.key;-j)L.rj+1=L.rj;/记录后移L.rj+1=L.r0;/插入到正确位置,例2:关键字序列T=(21,25,49,25*,16,08),请写出直接插入排序的具体实现过程。,*表示后一个25,i=1,21,i=2,i=3,i=5,i=4,i=6,25,49,25*,49,16,16,08,49,解:假设该序列已存入一维数组r7中,将r0作为哨兵(T
9、emp)。则程序执行过程为:,初态:,16,25,21,16,完成!,时间效率:因为在最坏情况下,所有元素的比较次数总和为(01n-1)O(n2)。其他情况下也要考虑移动元素的次数。故时间复杂度为O(n2)空间效率:仅占用1个缓冲单元O(1)算法的稳定性:因为25*排序后仍然在25的后面稳定,内部排序的时间分析:,实现内部排序的基本操作有两个:,(2)“移动”记录。,(1)“比较”序列中两个关键字的 大小;,对于直接插入排序:,最好的情况(关键字在记录序列中顺序有序):,“比较”的次数:,最坏的情况(关键字在记录序列中逆序有序):,“比较”的次数:,0,“移动”的次数:,“移动”的次数:,时间
10、复杂度为O(n2),2)折半插入排序,优点:比较次数大大减少,全部元素比较次数仅为O(nlog2n)。时间效率:虽然比较次数大大减少,可惜移动次数并未减少,所以排序效率仍为O(n2)。空间效率:仍为 O(1)稳 定 性:稳定,一个的改进方法:,思考:折半插入排序还可以改进吗?能否减少移动次数?,既然子表有序且为顺序存储结构,则插入时采用折半查找定可加速。,3)希尔(shell)排序,基本思想:先将整个待排记录序列分割成若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。技巧:子序列的构成不是简单地“逐段分割”,而是将相隔某个增量dk的记录组成一
11、个子序列,让增量dk逐趟缩短(例如依次取5,3,1),直到dk1为止。优点:让关键字值小的元素能很快前移,且序列若基本有序时,再用直接插入排序处理,时间效率会高很多。,又称缩小增量排序,38,例:关键字序列 T=(49,38,65,97,76,13,27,49*,55,04),请写出希尔排序的具体实现过程(dk=5,3,1)。,初态:,第1趟(dk=5),第2趟(dk=3),第3趟(dk=1),49,13,13,49,38,27,65,49*,97,55,76,04,27,38,65,49*,97,55,13,55,76,04,55,13,27,04,27,04,49,49*,49,49*,7
12、6,38,76,65,65,97,97,13,27,04,49*,76,97,算法分析:开始时dk 的值较大,子序列中的对象较少,排序速度较快;随着排序进展,dk 值逐渐变小,子序列中对象个数逐渐变多,由于前面工作的基础,大多数对象已基本有序,所以排序速度仍然很快。,ri,时间效率:,空间效率:O(1)因为仅占用1个缓冲单元算法的稳定性:不稳定因为49*排序后却到了49的前面,O(n1.25)O(1.6n1.25)由经验公式得到,10.3 交换排序,两两比较待排序记录的关键码,如果发生逆序(即排列顺序与排序后的次序正好相反),则交换之,直到所有记录都排好序为止。,交换排序的主要算法有:1)冒泡
13、排序 2)快速排序,交换排序的基本思想是:,一、起泡排序,二、一趟快速排序,三、快速排序,四、快速排序的时间分析,一、起泡排序,假设在排序过程中,记录序列R1.n的状态为:,第 i 趟起泡排序,无序序列R1.n-i+1,有序序列 Rn-i+2.n,n-i+1,无序序列R1.n-i,有序序列 Rn-i+1.n,比较相邻记录,将关键字最大的记录交换到 n-i+1 的位置上,1)冒泡排序,基本思路:每趟不断将记录两两比较,并按“前小后大”(或“前大后小”)规则交换。优点:每趟结束时,能挤出一个最大值到最后面位置,一旦下趟没有交换发生,还可以提前结束排序。前提:顺序存储结构,例:关键字序列 T=(21
14、,25,49,25*,16,08),请写出冒泡排序的具体实现过程。,21,25,49,25*,16,0821,25,25*,16,08,4921,25,16,08,25*,4921,16,08,25,25*,4916,08,21,25,25*,4908,16,21,25,25*,49,初态:第1趟第2趟第3趟第4趟第5趟,void BubbleSort(Elem R,int n)while(i 1)/while/BubbleSort,i=n;,i=lastExchangeIndex;/本趟进行过交换的/最后一个记录的位置,if(Rj+1.key Rj.key)Swap(Rj,Rj+1);las
15、tExchangeIndex=j;/记下进行交换的记录位置/if,for(j=1;j i;j+),lastExchangeIndex=1;,冒泡排序的算法分析,最好情况:初始排列已经有序,只执行一趟起泡,做 n-1 次关键码比较,不移动对象。最坏情形:初始排列逆序,算法要执行n-1趟起泡,第i趟(1 i n)做了n-i 次关键码比较,执行了n-i 次对象交换。,因此:时间效率:O(n2)因为要考虑最坏情况空间效率:O(1)只在交换时用到一个缓冲单元稳 定 性:稳定 25和25*在排序前后的次序未改变,时间分析:,最好的情况(关键字在记录序列中顺序有序):只需进行一趟起泡,“比较”的次数:,最坏
16、的情况(关键字在记录序列中逆序有序):需进行n-1趟起泡,“比较”的次数:,0,“移动”的次数:,“移动”的次数:,n-1,冒泡排序的优点:每一趟整理元素时,不仅可以完全确定一个元素的位置(挤出一个泡到表尾),一旦下趟没有交换发生,还可以提前结束排序。,有没有比冒泡排序更快的算法?有!快速排序法全球公认!因为它每趟都能准确定位不止1个元素!,2)快速排序,从待排序列中任取一个元素(例如取第一个)作为中心,所有比它小的元素一律前放,所有比它大的元素一律后放,形成左右两个子表;然后再对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个。此时便为有序序列了。,基本思想:,优点:因为每趟
17、可以确定不止一个元素的位置,而且呈指数增加,所以特别快!前提:顺序存储结构,s,t,low,high,设 Rs=52 为枢轴,将 Rhigh.key 和 枢轴的关键字进行比较,要求Rhigh.key 枢轴的关键字,将 Rlow.key 和 枢轴的关键字进行比较,要求Rlow.key 枢轴的关键字,high,23,low,80,high,14,low,52,例如,R0,52,low,high,high,high,low,可见,经过“一次划分”,将关键字序列 52,49,80,36,14,58,61,97,23,75 调整为:23,49,14,36,(52)58,61,97,80,75,在调整过程
18、中,设立了两个指针:low 和high,它们的初值分别为:s 和 t,,之后逐渐减小 high,增加 low,并保证 Rhigh.key52,和 Rlow.key52,否则进行记录的“交换”。,int Partition(RedType/返回枢轴所在位置/Partition,快速排序,首先对无序的记录序列进行“一次划分”,之后分别对分割所得两个子序列“递归”进行快速排序。,无 序 的 记 录 序 列,无序记录子序列(1),无序子序列(2),枢轴,一次划分,分别进行快速排序,void QSort(RedType&R,int s,int t)/对记录序列Rs.t进行快速排序 if(s t-1)/长
19、度大于1/QSort,pivotloc=Partition(R,s,t);/对 Rs.t 进行一次划分,QSort(R,s,pivotloc-1);/对低子序列递归排序,pivotloc是枢轴位置,QSort(R,pivotloc+1,t);/对高子序列递归排序,void QuickSort(SqList/QuickSort,第一次调用函数 Qsort 时,待排序记录序列的上、下界分别为 1 和 L.length。,pivotkey=21,(08,16)21(25*,49,25),Low=high=3,本趟停止,将中枢点定位并返回位置信息,例1:关键字序列 T=(21,25,49,25*,16
20、,08),计算机如何实现快速排序算法的某一趟过程?,high,low,21,25*,3,21,08,25,16,49,25*跑到了前面,不稳定!,设计技巧:交替/振荡式逼近,例2:以关键字序列(256,301,751,129,937,863,742,694,076,438)为例,写出执行快速算法的各趟排序结束时,关键字序列的状态。,原始序列:256,301,751,129,937,863,742,694,076,438,快速排序,第1趟第2趟第3趟第4趟,256,301,751,129,937,863,742,694,076,438,076,129,256,751,937,863,742,69
21、4,301,438,意即模拟算法实现步骤,256,076,301,129,751,256,076,129,256,438,301,694,742,694,863,937,751,076,129,256,438,301,694,742,751,863,937,076,129,256,301,301,694,742,751,863,937,438,076,129,256,301,438,694,742,751,863,937,时间效率:O(nlog2n)因为每趟确定的元素呈指数增加空间效率:O(log2n)因为递归要用栈(存每层low,high和pivot)稳 定 性:不 稳 定 因为有跳跃式交换
22、。,四、快速排序的时间分析,假设一次划分所得枢轴位置 i=k,则对n 个记录进行快排所需时间:,其中 Tpass(n)为对 n 个记录进行一次划分所需时间。,若待排序列中记录的关键字是随机分布的,则 k 取 1 至 n 中任意一值的可能性相同。,T(n)=Tpass(n)+T(k-1)+T(n-k),设 Tavg(1)b,则可得结果:,结论:快速排序的时间复杂度为O(nlogn),由此可得快速排序所需时间的平均值为:,10.4 选择排序,选择排序的基本思想是:每一趟在后面n-i 个待排记录中选取关键字最小的记录作为有序序列中的第i 个记录。,10.4 选择 排 序,简 单 选 择 排 序,堆
23、排 序,树 形 选 择 排 序,一、简单选择排序,思路异常简单:每经过一趟比较就找出一个最小值,与待排序列最前面的位置互换即可。首先,在n个记录中选择最小者放到r1位置;然后,从剩余的n-1个记录中选择最小者放到r2位置;如此进行下去,直到全部有序为止。优点:实现简单缺点:每趟只能确定一个元素,表长为n时需要n-1趟前提:顺序存储结构,一、简单选择排序,假设排序过程中,待排记录序列的状态为:,有序序列R1.i-1,无序序列 Ri.n,第 i 趟简单选择排序,从中选出关键字最小的记录,有序序列R1.i,无序序列 Ri+1.n,例:关键字序列T=(21,25,49,25*,16,08),请给出简单
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 排序
![提示](https://www.31ppt.com/images/bang_tan.gif)
链接地址:https://www.31ppt.com/p-6364975.html