概念:
所谓排序,就是要整理文件中的记录,使之按照关键字递增(或递减)次序排列起来。当待排序记录的关键字均不同是,排序结果是唯一的,否则排序结果不唯一。
在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的。否则,这种排序方法是不稳定的。
马老师的常用排序算法口诀:冒择路(入)兮(希尔)快归堆[冒泡 选择 插入 希尔 快速 归并 堆 排序]
排序算法分类:
插入排序(直接插入排序,希尔排序)、选择排序(直接选择排序,堆排序)、交换排序(冒泡排序,快速排序)、归并排序、基数排序。
一、插入排序
插入排序的基本思想是每步将一个待排序的记录按其排序码值的大小,插到前面已经排好的文件中的适当位置,知道全部插入完为止。插入排序方法主要有直接插入排序和希尔排序。
1.直接插入排序:
直接插入排序的过程为在插入第i个记录时,R1,R2,...,Ri-1已经排好序,将第i个记录的排序码ki一次和R1,R2,...,Ri-1的排序码逐个进行比较,找到适当的位置。使用直接插入排序,对于具有n个记录的文件,要进行n-1躺排序。
直接插入排序的平均时间复杂度为O(N2),使用于数据较少的排序。
实现插入排序的伪代码如下:
用C语言实现插入排序的代码如下:
2.希尔排序
希尔排序(Shell Sort)是插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。
希尔排序基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
该方法实质上是一种分组插入方法。
Shell排序的时间性能优于直接插入排序
希尔排序的时间性能优于直接插入排序的原因:
①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
②当n值较小时,n和n2的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(n2)差别不大。
③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
因此,希尔排序在效率上较直接插人排序有较大的改进。
希尔排序是不稳定排序算法,执行时间依赖于增量序列,其平均时间复杂度为O(n1.3)。
二、选择排序
选择排序算法的基本思想是每步从待排序的记录中选出排序码最小的记录,顺序存放在已排序的记录序列后面,直到全部排完。选择排序中主要使用直接选择排序和堆排序。
1.直接选择排序
直接排序的过程是,首先在所有记录中选出排序码最小的记录,把它与第一个记录交换,然后在其余的记录内选出排序码最小的记录,与第2个记录交换……以此类推,直到所有记录排完为止。直接选择排序的平均时间复杂度为O(N2),是不稳定排序。
直接选择排序用C语言实现如下:
2.堆排序
堆排序是一种树形选择排序,是对直接选择排序的有效改进。n个关键字序列K1,K2,……,Kn称为堆,当且仅当该序列满足(Ki≤K2i且Ki≤K2i+1),(1≤i≤n)。Ki相当于二叉树中的非叶节点,K2i,K2i+1相当于Ki的左右儿子。根结点(堆顶)的关键字是堆里所有结点关键字中最小者,称为小根堆;根结点的关键字是堆里所有结点最大者,称为大根堆。
堆排序的最坏时间负责度为O(nlog2n),堆排序的平均性能接近于最坏性能。由于建初始堆的比较次数较多,所以堆排序不适合记录较少的文件。堆排序就是就地排序,辅助空间为O(1),它是不稳定排序。
堆排序的关键步骤有两个,一是如何建立初始堆;二是当堆的根结点与堆的最后一个结点交换后,如何对少了一个结点后的结点序列做调整,使之重新称为堆。
//用C语言实现堆排序算法代码如下:
三、交换排序
交换排序的基本思想是两两比较待排序记录的排序码,并交换不满足顺序要求的那些偶对,直到满足条件为止。交换排序的主要方法有冒泡排序和快速排序。
1.冒泡排序
冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。
由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。
冒泡排序最坏时间复杂度为O(n2),平均时间性能比直接插入排序要差的多,但它是稳定的。
冒泡排序用C语言实现的代码如下:
2.快速排序
四、归并排序