一、归并排序
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。将两个或以上的有序表组合成一个新的有序表。
1、2-路归并排序
初始序列含有n个记录,可看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列,再两两归并,如此重复,直至得到一个长度为n的有序序列为止。
2、举例
上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],实现步骤:
3、总结
与快排和堆排序相比,归并排序的最大特点是,他是一种稳定的排序方法。
Tips:
排序算法的稳定性:保证排序前2个相等的数,在序列中的前后位置顺序和排序后它们两个的前后位置顺序相同。例如,Ai = Aj,Ai排序前位于Aj的前面,排序后Ai还位于Aj的前面。
稳定性的好处:排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就 是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。
排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。
例如,对于如下冒泡排序算法,原本是稳定的排序算法,如果将记录交换的条件改成r[j]>=r[j+1],则两个相等的记录就会交换位置,从而变成不稳定的算法。
void BubbleSort(int r[ ], int n) {
exchange=n; //第一趟冒泡排序的范围是r[1]到r[n]
while (exchange) {//仅当上一趟排序有记录交换才进行本趟排序
bound=exchange; exchange=0;
for (j=1; j if (r[j]>r[j+1]) {
r[j]←→r[j+1];
exchange=j; //记录每一次发生记录交换的位置
}
}
}
堆排序、快速排序、希尔排序、直接选择排序不是稳定的排序算法,而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。
一、基数排序
基数排序是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。
1、什么是多关键字
已知扑克牌中52张牌面的次序关系为:
每一张牌有两个关键字:花色
和面值(2 < 3 < ... < A),且“花色”的地位高于“面值”,在比较任意两张牌面的大小是,先比较“花色”,若“花色”相同,再比较“面值”。所以整理扑克牌的方法有两种:1.按不同“花色”分成次序的四堆,每一堆均有相同“花色”,再分别对每一堆按“面值”大小整理有序。2.按不同“面值”分成13堆,将这13堆牌自小到大叠在一起(“3”在“2”上,“4”在“3”上,... ,最上面的是4张“A”),然后将这付牌整个点到过来再按不同“花色”分成4堆,最后将这4堆牌按小到大的次序合在一起,“梅花”在最下面,“桃心”在最上面,也能得到满足如上次序关系的牌。这两种排序方法便是两张多关键字的排序方法。
1、最高位优先于最低位优先
假设有n个记录的序列{R1,R2,...Rn},且每个记录Ri中含有d个关键字(Ki1,Ki2,...,Kid),序列{R1,R2,...Rn}对关键字(K1,K2,...,Kd)有序是指:对于序列中任意两个记录Ri和Rj(1 <= i < j <= n)都满足下列有序关系:(Ki1,Ki2,...,Kid)<(Kj1,Kj2,...,Kjd),其中K1称为最高位关键字,Kd称为最低位关键字。
实现多关键字排序的方法:
A、先对最高位关键字K1进行排序,间序列分成若干子序列,每个子序列中的记录都具有相同的K1值,然后分别对每个子序列对关键字K2进行排序,按K2值不同再分成若干更小的子序列,依次重复,直到对Kd-1进行排序后得到的每一子序列中的记录都具有相同的关键字(K1,K2,...,Kd-1),而后每个子序列分别对Kd进行排序,最后将所要子序列依次连接在一起成为一个有序序列,这种方法为“最高位优先(MSD)”
B、先从最低位关键字Kd进行排序,在对高一位的关键字Kd-1进行排序,依次重复,直至对K1进行排序后便成为一个有序序列。这种方法称为“最低位优先(LSD)”。
三、内部排序方法的比较
结论:
1、表中的“简单排序”指:除希尔排序外的所有插入排序,冒泡排序和简单选择排序,其中之间插入排序最简单,当序列中的记录“基本有序”或n值较小时,它是最佳的排序方法,因此常将他和其他排序方法(快排,归并排序)结合在一起使用。
2、从平均时间性能看,快排最省时间,但他在最坏情况下的时间性能不如堆排序和归并排序。在n较大,归并排序所需时间比堆排序少,但所需的辅助存储量最多。
3、基数排序适用于n值很大且关键字较小的序列。