归并排序是一种较为常用的排序算法,其时间复杂度最坏情况和平均情况均为nlgn,与快速排序相同,它也是一种基于分治思想的排序算法。
它的基本思路是把数组分成A、B两个组,如果这两组的数据是有序的,那么就可以对这两组数据进行合并,继而完成排序。
那么,最关键的问题就变成了如何使得A、B两组数据有序呢?归并排序的思想就是把A、B两组数据分别再分成两组,依次类推,直到小组数据只有一个的时候,就认为此时的小组数据是有序的,然后对小组数据进行合并,完成排序。
假设我们要对数组a[8]={1,5,2,4,6,3,2,6}进行归并排序,为了直观,下图给出归并排序的图示过程:
归并排序分成分成3步:
- 分解子问题
- 递归解决子问题
- 合并已经求解的子问题
下面给出归并排序的实现,也可以访问我的github下载源代码:
#include<stdio.h>
//合并数组的前半部分和后半部分, 前提就是前后两个子数组分别都已经排好序了
void merge(int a[], int first, int mid, int last, int temp[])
{
int i, j, m, n;
i = first, m = mid;
j = mid + 1, n = last;
int k = 0;
while(i<=m && j<=n)
{
if(a[i] < a[j])
{
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
}
}
while(i <= m)
temp[k++] = a[i++];
while(j <= n)
temp[k++] = a[j++];
//将排好序的复制回原数组
for(i=0; i < k; i++)
{
a[first + i] = temp[i];
}
}
void merge_sort(int a[], int first, int last, int temp[])
{
int mid = (first + last)/2;
if(first < last)
{
merge_sort(a, first, mid, temp);
merge_sort(a, mid + 1, last, temp);
merge(a, first, mid, last, temp);
}
}
bool sort(int a[], int n)
{
int *p = new int[n];
if(p == NULL)
return false;
merge_sort(a, 0, n - 1, p);
delete[] p;
return true;
}