005 二分归并排序
一、算法介绍
将待排序序列分成两个子序列,然后对两个子序列使用相同算法进行排序,最后将排好序的两个子序列归并成为一个序列。核心思想是将复杂的问题拆分成为若干个简单的子问题,分别对子问题求解,再对子问题进行综合进而得到大问题的解,这就是所谓的分而治之。
二、算法分析
算法分为两部分,首先是“二分”算法,显然可以利用递归对序列进行拆分,例如数组A[1-8],将其拆分为A[1-4]和A[5-8],然后再对两个数组进行拆分,例如将A[1-4]拆分为A[1-2]和A[3-4],当拆分成A[1]和A[2]时,子数组只有一个元素,无需排序。这时递归调用停止,开始进行归并。
归并是将两个排好序的小序列放到一个大序列中,并保证其有序。由于归并时,是将原序列中相邻的两个序列归并到原序列中,因此可以将原序列中待归并两个子序列的元素分别放到(移走,添加和删除,并不是单纯的复制,但实际操作时不用,只是为了方便理解)两个新的序列中,再将其按大小依次放入原序列的对应位置。具体一点说,比较两个序列中首元素的大小,将更小的放到原序列中,将其中一个已经没有元素时,将另一个序列剩下的元素依次放到原序列中。
如图所示
三、算法代码
void Merge(int A[], int low, int mid, int high) //如算法分析的操作
{
int i, j, k;
int B[mid-low+1], C[high-mid]; //两个存放子序列的数组
k = low;
for(i=0; i<mid-low+1; i++)
{
B[i] = A[k];
k++;
}
for(i=0; i<high-mid; i++)
{
C[i] = A[k];
k++;
}
i = 0;
j = 0;
k = low;
while(i<mid-low+1 && j<high-mid)
{
if(B[i] < C[j])
{
A[k] = B[i];
i++;
}
else
{
A[k] = C[j];
j++;
}
k++;
}
while(i<mid-low+1)
{
A[k] = B[i];
i++;
k++;
}
while(j<high-mid)
{
A[k] = C[j];
j++;
k++;
}
}
void Merge(int a[],int low, int mid, int high) //如图示的算法
{
int j, k, h;
int b[10]; //将两个子序列,放到大数组,排好序
j = low;
h = mid + 1;
k = low;
while (j<=mid&&h<=high)
{
if (a[j] < a[h])
b[k++] = a[j++];
else
b[k++] = a[h++];
}
while (j <= mid)
{
b[k++] = a[j++];
}
while (h<=high)
{
b[k++] = a[h++];
}
for (k = low; k <= high; k++)
{
a[k] = b[k];
}
}
void MergeSort(int A[], int low, int high)
{
if(low<high)
{
int mid = (low + high)/2;
MergeSort(A, low, mid);
MergeSort(A, mid+1, high);
Merge(A, low, mid, high);
}
}
运行结果