下面是归并排序的一些特征:
- 时间复杂度,最好最坏平均都为:O(nlog2n)
- 空间复杂度,最好最坏平均都为:O(n)
- 是否稳定:稳定
二路归并的时间复杂度为O(nlog2n),多路归并排序在引入败者树后也为O(nlog2n)
只有在最后一次排序后才每个元素才确定是在最终位置
归并的含义是将两个或两个以上的有序表组合成一个新的有序表
2路归并排序的基本思想:将初始待排序的每个元素都看成是一个排好序的子表,然后两两归并,得到n/2个长度为2或1的有序表;再两两归并,如此重复,直到合并为长度为n的有序表为止
下面是2路归并排序的代码:
void merge_sort(int arr[], int low, int high)
{
if (low < high) {
int mid = (low+high)/2; // 从中间划分两个子序列
merge_sort(arr, low, mid); // 对左侧子序列进行递归排序
merge_sort(arr, mid+1, high); // 对右侧子序列进行递归排序
merge(arr, low, mid, high); // 归并
}//if
}
/**
* 合并两个有序表
*/
void merge(int arr[], int low, int mid, int high)
{
// arr[low...mid]与arr[mid+1...high]各自有序,将他们合并
int i, j, k;
for (k=low; k<=high; k++)
arr_bk[k] = arr[k]; // 将arr中的所有元素复制到arr_bk中
for (i=low, j=mid+1, k=i; i<=mid&&j<=high; k++) {
if (arr_bk[i] <= arr_bk[j])
arr[k] = arr_bk[i++];
else
arr[k] = arr_bk[j++];
}//for
while (i<=mid) arr[k++] = arr_bk[i++]; // 若第一个表未检测完,复制
while (j<=high) arr[k++] = arr_bk[j++]; // 若第二个表未检测完,复制
}
测试代码,可直接复制后编译执行:
#include <stdio.h>
#include <stdlib.h>
void show(int arr[], int len);
void merge_sort(int arr[], int low, int high);
void merge(int arr[], int low, int mid, int high);
int * arr_bk; // 辅助排序的数组
int main()
{
const int len = 7;
int arr[len] = {7, 10, 11, 9, -8, 2, 27};
arr_bk = (int *)malloc(sizeof(int)*len);
merge_sort(arr, 0, len-1);
free(arr_bk);
show(arr, len);
return 0;
}
void show(int arr[], int len)
{
int i;
for (i=0; i<len; i++) {
printf("%4d", arr[i]);
}
printf("
");
}
void merge_sort(int arr[], int low, int high)
{
if (low < high) {
int mid = (low+high)/2; // 从中间划分两个子序列
merge_sort(arr, low, mid); // 对左侧子序列进行递归排序
merge_sort(arr, mid+1, high); // 对右侧子序列进行递归排序
merge(arr, low, mid, high); // 归并
}//if
}
/**
* 合并两个有序表
*/
void merge(int arr[], int low, int mid, int high)
{
// arr[low...mid]与arr[mid+1...high]各自有序,将他们合并
int i, j, k;
for (k=low; k<=high; k++)
arr_bk[k] = arr[k]; // 将arr中的所有元素复制到arr_bk中
for (i=low, j=mid+1, k=i; i<=mid&&j<=high; k++) {
if (arr_bk[i] <= arr_bk[j])
arr[k] = arr_bk[i++];
else
arr[k] = arr_bk[j++];
}//for
while (i<=mid) arr[k++] = arr_bk[i++]; // 若第一个表未检测完,复制
while (j<=high) arr[k++] = arr_bk[j++]; // 若第二个表未检测完,复制
}