摘要:
(1)归并排序几乎以O(NlogN)的时间界实现,是典型的分治算法;
(2)归并排序的基本思路很简单:就是将目标序列分为两个部分,将两个子序列排序好之后,再将它们合并。注意到合并两个已排序的序列只需要O(N)的时间界。
(3)对两个子序列的排序显然也是通过递归的归并排序实现的。
(4)需要注意的一个小细节是,当子序列的元素很少时,继续调用归并排序未必是一件划算的事.因此可以设置一个边界,当元素个数少于这个值时就掉用最简单的插入排序.
【1】合并的过程
合并的过程相对简单,用两个指针指向两个子序列的开始点,然后比较它们的大小.将较小的一个放入新的数组.然后将指向较小元素的指针前移一位。继续这个过程直到某一个指针达到边界.然后将另一个子序列的剩余所有元素都置入新的数组.
【2】注意的细节:如果每一次递归都创建一个新的数组那么将会占用很多的空间.因此合理的做法是在进入递归之前创建两个数组,然后用两个变量Left,Right标志子序列的边界。每一次合并的过程都是把A[Left1]到A[Right1],A[Left1+1]到A[Right2]合并到B[left1]到B[Right2];
#include "stdafx.h"
#include "malloc.h"
#include "stdlib.h"
#include "string.h"
#define Max 10000000
int Min(int a ,int b)
{
return a < b ? a:b;
}
void Merge(int *A,int *tmp,int Left1,int Right1,int Left2, int Right2)
{
if(Left1==Right1&&Right1==Left2&&Left2==Right2)//只有一个元素不用合并
return;
int point1 = Left1,point2 = Left2,k = Left1;
//int tmp[9];
while(point1 <= Right1 && point2 <= Right2)
{
if(A[point1] <= A[point2])
tmp[Left1++] = A[point1++];
else
tmp[Left1++] = A[point2++];
}
while(point1 <= Right1)
tmp[Left1 ++] = A[point1++];
while(point2 <= Right2)
tmp[Left1++] = A[point2++];
for (Left1 = k;Left1<= Right2;Left1++)
{
A[Left1] = tmp[Left1];
}
}
【2】真正的排序
void Mergesort(int *A,int *tmp,int Left,int Right)
{
int Center;
if(Left == Right)//只有一个元素
return;
Center = (Left + Right)/2;
Mergesort(A,tmp,Left,Center);
Mergesort(A,tmp,Center + 1,Right);
//下面合并
Merge(A,tmp,Left,Center,Center+1,Right);
}
【3】以上的程序都是用递归的办法实现。下面用非递归的办法实现归并排序.
非递归的基本思路
(1)我们应该每次对2^i长度的子序列进行合并。例如最开始对长度为1的相邻子序列进行合并;然后对长度为2的相邻的子序列进行合并。代码如下
void Mergesort2(int *A,int *tmp,int N)
{
//非递归归并
int test[9];
int number = 1;//每次合并个数
int i,Center,end;
while(number <= N-1)
{
for( i = 0; i + number<= N ; i += number)
{
end = i + number - 1;
Center = (i + end)/2;
Merge(A,tmp,i,Center,Center+1,end);
}
if (i <= N-1)
{
//合并多出的元素
Merge(A,tmp,i-number,i-1,i,N-1);
}
number *= 2;
}
}
void Msort(int A[],int N)
{
int i = 1,cutoff,j;
while(i <= N)
{
i *= 2;
}
cutoff = i - N;
int *B = (int *)malloc(sizeof(int)*i);
int *tmp = (int *)malloc(sizeof(A)*N);
Mergesort2(A,tmp,N);
free(tmp);
}