// 维基百科
归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用
算法描述
归并操作的过程如下:
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- 重复步骤3直到某一指针达到序列尾
- 将另一序列剩下的所有元素直接复制到合并序列尾
分类 | 排序算法 |
---|---|
数据结构 | 数组 |
最差时间复杂度 | Θ(nlog n) |
最优时间复杂度 | Θ(n) |
平均时间复杂度 | Θ(nlog n) |
最差空间复杂度 | Θ(n) |
最佳算法 | 有时是 |
算法思路:
1.假设数组 a[ 10 ] = {26,5,37,1,61,11,59,15,48,19, 12}
首先声明一个变量k用于存储数组 a[10] 子序列的长度
初始 k = 1, 表示a数组中每个元素为一个数组
2.设定两个位置标志 start1,end1. 表示第一个序列的起始与结束
start2,end2 表示第二个序列的其实与结束。(注意一个序列并不只有一个元素)
当k= 1 时, 数组a的序列
[26] , [5] , [37], [1], [61], [11], [59], [15], [48], [19], [12] (其中 start1 = 0, end1 = start1 + k - 1, start2 = end1 + 1, end2 = start2 + k - 1)
一次归并后
[26, 5] , [37, 1], [1,61], [11,59], [15,48], [19,12]
此时k = 2; 所以每次归并后 k = k*2;
设置一个循环每次归并后
start1 = end2 + 1;
其余值根据start1做出变化,然后 k = k*2;
直到start1 + k >= size - 1; size 为数组长度。
算法代码:
/***************************************
* Function:
* 数据结构_归并排序
* Lnstree by 2012
****************************************/
#include <stdio.h>
// a[]为待排序的数组 b[]辅助数组 k为子序列的长度 n为数组的大小
void Mpass (int a[], int b[], int k, int n)
{
int start1,end1; // 对应第一个有序子序列起始与终止位置
int start2, end2; // 对应第二个有序子序列起始与终止位置
start1 = 0;
int m = 0;
int i,j;
while (start1 + k <= n-1)
{
start2 = start1 + k;
end1 = start2 - 1;
end2 = (start2 + k - 1 <= n - 1)? (start2+k-1) : n - 1;
for (i = start1, j = start2; i<= end1 && j <= end2;)
{
if (a[i] <= a[j])
{
b[m] = a[i];
i++;
m++;
}
else
{
b[m] = a[j];
j++;
m++;
}
}
while (i <= end1)
{
b[m] = a[i];
i++;
m++;
}
while (j <= end2)
{
b[m] = a[j];
j++;
m++;
}
start1 = end2 + 1;
}
// 将数组中剩余的元素导入数组
for (i = start1; i < n; i ++, m++)
{
b[m] = a[i];
}
}
void Msort(int a[], int b[], int n)
{
int i,k,count;
k = 1;
count = 1;
while (k < n)
{
Mpass(a,b,k,n); // 归并两个子序列
for (i = 0; i < n; i++)
{
a[i] = b[i];
}
printf ("\n第%2d操作后:", count++);
for (i = 1; i < n + 1; i++)
{
if ((i==n) && ((i%(2*k) != 0)))
printf("%5d]", a[i-1]);
else
{
if (i%(2*k) == 1)
{
printf("[%2d", a[i - 1]);
}
else if (i%(2*k) == 0)
{
printf("%4d]", a[i - 1]);
}
else
{
printf("%4d", a[i - 1]);
}
}
}
k = k*2;
}
}
int main()
{
int a[10] = {26,5,37,1,61,11,59,15,48,19};
int b[10];
int i,j;
printf("\n源数据:");
for (i = 0; i < 10; i++)
{
printf ("%4d", a[i]);
}
Msort(a,b,10);
printf("\n处理后的数据:");
for (i = 0; i < 10; i++)
{
printf ("%4d", a[i]);
}
return 0;
}