分治法的思想是将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解。
归并排序算法完全遵循分治模式,操作步骤如下:
分解:将待排序的n个元素的序列分解为分别具有n/2个元素的两个子序列。
解决:使用归并排序递归地排序两个子序列。
合并:合并两个已排序的子序列以产生已排序的原序列。
“合并”操作中通过调用一个辅助过程MERGE(A,p,q,r)来完成,其中A是一个数组,p,q和r是数组下表,满足,该过程假设子数组A[p..q]和A[q+1..r]都已排好序。该过程合并这两个子数组形成单一的已排好序的子数组并代替当前子数组A[p..r]。
伪代码如下,需要注意,在每个子数组的末尾增加一张哨兵值,以避免在每个基本步骤中必须检查是否子数组为空:
MERGE(A,p,q,r)
n1 = q – p + 1 //计算子数组A[p..q]的长度n1
n2 = r – q //计算子数组A[q+1 ..r]的长度n2
//创建长度分别为n1+1和n2+1的数组L和R,数组的额外位置保存哨兵值
let L[1..n1+1] and R[1..n2+1] be new arrays
for i = 1 to n1
L[i] = A[p + i - 1] //将子数组A[p..q]复制到L[1..n1]
for j = 1 to n2
R[j] = A[q + j] //将子数组A[q+1 ..r]复制到R[1..n2]
L[n1 + 1] =
R[n2 + 1] = //将哨兵值放在数组L和R的末尾
i = 1
j = 1
//在开始循环的每次迭代时,子数组A[p..k-1]按从小到大的顺序依次包含L和R中的k-p个//最小元素,进而,L[i]和R[j]是各自所在数组中未被复制回数组A的最小元素
for k = p to r
if L[i] <= R[j]
A[k] =L[i]
i = i + 1
else
A[k] = R[j]
j = j + 1
下面的过程MERGE-SORT(A,p,r)排序子数组中A[p..r]中的元素,其中将MERGE过程作为归并排序算法中的一个子程序来应用:
MERGE-SORT(A,p,r)
if p< r
q=
MERGE-SORT(A,p,q)
MERGE-SORT(A,q+1,r)
MERGE(A,p,q,r)
程序代码如下:
#include "stdio.h"
#include "stdlib.h"
#define MAX 10
void print_array(int *array_test,unsignedint x)
{
unsignedint i;
for(i=0;i<x;i++)
{
printf("%d",array_test[i]);
}
printf("\n");
}
static void merge(int array[],int low,intmid,int high)
{
inti,k;
//申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
int*temp=(int*)malloc((high-low+1)*sizeof(int));
intbegin1=low; //左半边开始下标
intend1=mid; //左半边结束下标
intbegin2=mid+1; //右半边开始下标
intend2=high; //右半边开始下标
printf("mid=%d",mid);
k=0;
while(begin1<=end1 && begin2<=end2)
{
//左右两边分别比较,并且一次存入临时数组
if(array[begin1]<array[begin2])
{
temp[k++]=array[begin1++];
}
else
{
temp[k++]=array[begin2++];
}
}
//若第一个序列有剩余,直接拷贝出来粘到合并序列尾
while(begin1<=end1)
{
temp[k++]=array[begin1++];
}
//若第二个序列有剩余,直接拷贝出来粘到合并序列尾
while(begin2<=end2)
{
temp[k++]=array[begin2++];
}
//将排序好的序列拷贝回数组中
for(i=0;i<(high-low+1);i++)
{
array[low+i]=temp[i];
}
printf("合并: ");
print_array(array,MAX);
free(temp);
}
void merge_sort(int array[],unsigned intfirst,unsigned int last)
{
intmid=0;
if(first<last)
{
mid=(first+last)/2;
merge_sort(array,first,mid); //划分左半部分
merge_sort(array,mid+1,last); //划分右半部分
merge(array,first,mid,last); //合并
}
}
int main()
{
intarray_test[MAX]={0,9,8,4,3,2,1,5,6,7};
printf("start:");
print_array(array_test,MAX);
merge_sort(array_test,0,9);
printf("end:");
print_array(array_test,MAX);
return0;
}