归并排序
简介:
前面介绍的插入排序,交换排序和选择排序这三类排序算法都是将无序的记录序列按关键字的大小排成一个有序序列.
而归并排序则是将两个或两个以上的有序序列合并成一个有序序列的过程.
归并排序(Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。
算法描述:
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
- eg:
a: 1 3 5 7 9
b: 2 4 6 8 10 12 14
//1 和 2, 比, 小,将 1 放入c,
//3 和 2, 比, 大,将 2 放入c,
//3 和 4, 比, 小,将 3 放入c,
....
c > 1 2 3 4 5 6 7 8 9 10 12 14
//我们在合并这两个序列时,每次只用比较当前a序列第一个和当前b序列第一个的大小,谁小就先放入有序序列中,当a比较完后,直接将b剩余的依次放入有序序列即可.
//将有序数组a[]和b[]合并到c[]中
void MemeryArray(int a[], int n, int b[], int m, int c[])
{
int i, j, k;
i = j = k = 0;
while (i < n && j < m)
{
if (a[i] < b[j])
c[k++] = a[i++];
else
c[k++] = b[j++];
}
while (i < n)
c[k++] = a[i++];
while (j < m)
c[k++] = b[j++];
}
//可以看出合并有序数列的效率是比较高的,可以达到O(n)。
//解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
//可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递[归]的分解数列,再合[并]数列就完成了[归并]排序。
过程演示:
首先:
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]
4 2 8 6 0 5 1 7 3 9
//一开始,分成两拨.
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]
4 2 8 6 0 5 1 7 3 9
//一开始,再分别分成两拨.
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]
4 2 8 6