在前一篇博客中已经提到了插入排序,这里继续介绍下另一种比较高效的排序:合并排序。合并排序用到了分治思
想,其时间复杂度为O(NlgN)。合并算法的关键在于合并。
合并排序的的基本步骤如下:
1.把待排序的数组分为左数组和右数组
2.对左数组和右数组进行迭代排序
3.将左数组和右数组进行合并
显然这些基本步骤符合分治模式在每一层递归上的三个步骤:分解、解决、合并。
每步的实现代码如下:
1.分解数组及进行迭代操作
void merge_sort (int a[], int p, int r)
{
if (p < r)
{
int q = (p + r) / 2;
merge_sort (a, p, q);
merge_sort (a, q + 1, r);
merge (a, p, q, r);
}
}
2.对两个排好序的左右数组合并操作
a).实现一:
void merge (int a[], int p, int q, int r)
{
int i, j;
int n, m;
n = q - p + 1;
m = r - q;
int* Left = new int[n + 1];
int* Right = new int[m + 1];
for (i = 0; i < n; i++)
Left[i] = a[p + i];
for (j = 0; j < m; j++)
Right[j] = a[q + j + 1];
Left[i] = Right[j] = INT_MAX;
i = j = 0;
for (int k = p; k <= r; k++)
{
if (Left[i] < Right[j])
{
a[k] = Left[i++];
}
else
{
a[k] = Right[j++];
}
}
delete Left;
delete Right;
}
b).实现二:
void merge (int a[], int p, int q, int r)
{
int i, j, k;
int n, m;
n = q - p + 1;
m = r - q;
int* Left = new int[n + 1];
int* Right = new int[m + 1];
for (i = 0; i < n; i++)
Left[i] = a[p + i];
for (j = 0; j < m; j++)
Right[j] = a[q + j + 1];
i = j = 0;
for (k = p;i < n && j < m; k++)
{
if (Left[i] < Right[j])
{
a[k] = Left[i++];
}
else
{
a[k] = Right[j++];
}
}
if (i < n)
{
for (int x = 0; x < n - i; x++)
a[k++] = Left[i + x];
}
if (j < m)
{
for (int x = 0; x < m - j; x++)
a[k++] = Right[j + x];
}
delete Left;
delete Right;
}