归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
例如,有两组有序数据,我们可以通过如下方式(以下简称归并排序)让两组数据快速有序
我们可以依次从两组中取最前的那个最小元素依次有序放到新的数组中,然后再把新数组中有序数据拷贝到园数组中,快速完成排序。
依靠这种思路,再结合分而治之的思想来实现归并排序
具体步骤
对于下面一组待排序数组
先以中间为界,把其均分为A和B两个数组(如果是奇书个,允许两组数相差一个)
如果A和B两组数据能够有序,则我们可以通过上面的方式让数组快速排好序。
此时,A组有4个成员,B组有5个成员,但两个数组都无序,然后我们可以采用分治法继续对AA组和B组进行均分,以A组为例,又可以均分A1和A2两个组如下:
均分后,A1 组和 A2 组仍然无序,继续利用分治法细分,以 A1 组为例,A1 又可分成如下
两组。
数组细分到一个元素后,这时候,我们就可以采用归并法借助一个临时数组将数组 A1 有序化!A2 同理!
依次类推,将 A1 组和 A2 组归并成有序的 A 组, B 组同理!
最后,将 A 和 B 组使用归并大法合并,就得到了完整的有序的结果!
归并排序算法图示:
程序实现
#include<iostream>
using namespace std;
void mergeAdd(int* a, int begin, int middle, int end,int *b) {
int index = begin;
int left = begin;
int right = middle;
while (left <= middle - 1 && right <= end)
b[index++] = (a[left] > a[right] ? a[right++] : a[left++]);//取小值
while (left <= middle - 1)
b[index++] = a[left++];
while (right <= end)
b[index++] = a[right++];
memcpy(a+begin, b+begin, sizeof(int) * (end - begin + 1));
}
void mergeSort(int* a, int begin, int end, int* b){
if (end > begin) {
int index = begin + (end - begin) / 2;
mergeSort(a, begin, index,b);
mergeSort(a, index+1, end, b);
mergeAdd(a, begin, index+1, end, b);
}
}
int main() {
int a[] = {163,161,158,165,171,170,163,159,162};
int len = sizeof(a) / sizeof(int);
int* b = new int[len];
int middle = len / 2;
mergeSort(a, 0, len - 1,b);
for (int i = 0; i < len; i++)
cout << a[i] << endl;
system("pause");
return 0;
}
运行结果
平均时间复杂度: O( n * log n)
最好情况:O(n * log n)
最坏情况:O(n * log n)
排序方式:Out-place
稳定性:稳定