一、归并排序
1.1 基本思想
将两个或两个以上的有序表合并成一个新的有序表。
1.2 图示
举例:下图黄色和青色代表的是一个序列中的两个有序的子序列。
比较两个指针所指元素的大小,将值更小的元素放入到辅助数组
B
B
B中,然后向右移动指针。
此时一个指针已经到头了,因此只需要把另一个数组剩余的元素遍历将元素放入到辅助数组中即可。
1.3 归并排序代码
ElemType *B = (ElemType*)malloc((n + 1) * sizeof(ElemType)); // 辅助数组B
void Merge(ElemType A[], int low, int mid, int high) {
//表A的两段A[low...mid]和A[mid...high]各自有序,将他们合并为一个有序表
int i, j, k;
for(k = low;k <= high; k++)
B[k] = A[k]; //将A中元素都复制到B中
for(i = low, j = mid + 1, k = i; i <= mid && j <= high; k++) {
if(B[i] <= B[j]) //比较B的左右两段中的元素
A[k] = B[i ++]; //将较小值复制到A中
else
A[k] = B[j ++];
}
while(i <= mid) A[k++] = B[i++]; //若第一个表未检测完,复制
while(j <= high) A[k++] = B[j++]; //若第二个表未检测完,复制
}
void MergeSort(ElemType A[], int low, int high) {
if(low < high) {
int mid = (low + high) / 2; //从中间划分两个子序列
MergeSort(A, low, mid); //对左侧子序列进行递归排序
MergeSort(A, mid + 1, high); //对右侧子序列进行递归排序
Merge(A, low, mid, high); //归并
}
}
1.4 性能分析
1.4.1 复杂度
- 空间复杂度:使用到了辅助数组,空间复杂度为 O ( n ) O(n) O(n)
- 时间复杂度:每趟归并的时间复杂度为 O ( n ) O(n) O(n),共需进行 ⌈ l o g 2 n ⌉ ⌈log_2n⌉ ⌈log2n⌉趟归并,因此时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)。
1.4.2 稳定性
- 由于 M e r g e ( ) Merge() Merge()操作不会改变相同关键字记录的相对次序,所以 2 2 2路归并排序算法是一种稳定的排序算法。
二、基数排序
2.1 基本思想
- 一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。
原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。基数排序的方式可以采用 L S D ( L e a s t s i g n i f i c a n t d i g i t a l ) LSD(Least significant digital) LSD(Leastsignificantdigital)或 M S D ( M o s t s i g n i f i c a n t d i g i t a l ) MSD(Most significant digital) MSD(Mostsignificantdigital), L S D LSD LSD的排序方式由键值的最右边开始,而 M S D MSD MSD则相反,由键值的最左边开始。
- M S D MSD MSD:先从高位开始进行排序,在每个关键字上,可采用计数排序
- L S D LSD LSD:先从低位开始进行排序,在每个关键字上,可采用桶排序
2.2 图示
初始序列如下:
序列中的数为
2
2
2位数,可以将关键字分为
2
2
2组。
(1) 第一趟(按照个位分配)
(2) 第二趟(按照十位分配)
从结果中看出,序列已经成功排序。
2.3 性能分析
2.3.1 复杂度
- 空间复杂度:一趟排序需要的辅助空间为 r r r( r r r个队列: r r r个队头指针和 r r r个队尾指针),但以后的排序中会重复使用这些队列,所以基数排序的空间复杂度为 O ( r ) O(r) O(r)
- 时间复杂度:基数排序需要进行 d d d趟分配和收集,一趟分配需要 O ( n ) O(n) O(n),一趟收集需要 O ( r ) O(r) O(r),所以基数排序的时间复杂度为 O ( d ( n + r ) ) O(d(n+r)) O(d(n+r)),他与序列的初始状态无关。
2.3.2 稳定性
- 对于基数排序算法而言,很重要一点就是按位排序时必须是稳定的,所以基数排序算法是一种稳定的排序算法。
2.4 适用场景
- 数据元素的关键字可以方便的拆为 d d d组,且 d d d较小;
- 每组关键字的取值范围不大,即 r r r较小;
- 数据元素个数 n n n较大。