//分治合并排序算法
//原理:把两个已经排序好的序列进行合并,成为一个排序好的序列。
//1. 在解决一个问题时,算法要一次或多次的调用自身来解决相关的子问题,这些算法一般采用分治策略:
// 将原来的问题划分为n个规模较小而结构和原问题类似的子问题,递归地解决这些问题,然后合并其结
// 果就得到原来问题的解。
// 分治法在每一层递归时都有三个步骤:
// a. 分解Divede:将原问题分解为一系列的子问题
// b. 解决Conquer:递归解决问题,若问题较小,直接解决问题
// c. 合并Combine: 将原来的结果合并成原问题的解
//
//2. 排序过程
// 以下列程序的打印结果为例
//Example for Divide and Conquer Sort!
//输入数组:Input Array A[12] = {2,11,7,7,9,11,5,3,3,0,1,3}
//Sort...
//Merge:A[0..11] 要排序0-11下标的数据
//Merge:A[0..5] 则要先排序0-5下标的数据
//Merge:A[0..2] 再分解为要排序0-2下标的数据
//Merge:A[0..1] 再分解为要排序0-1下标的数据
//Merge:A[0],Return 再分解为排序0下标的数据,当然这里就没法再分了
//Merge:A[1],Return 同上
//Combine:A[0...0...1] = {2,11} 合并0-1下标的数据
//Merge:A[2],Return 不能分的下标2的数据
//Combine:A[0...1...2] = {2,7,11} 合并0-1和2的数据
//Merge:A[3..5] 同样分解3-5下标
//Merge:A[3..4]
//Merge:A[3],Return
//Merge:A[4],Return
//Combine:A[3...3...4] = {7,9}
//Merge:A[5],Return
//Combine:A[3...4...5] = {7,9,11} 合并的3-5下标数据
//Combine:A[0...2...5] = {2,7,7,9,11,11} 合并的0-5下标数据
//Merge:A[6..11] 同样分解6-11
//Merge:A[6..8]
//Merge:A[6..7]
//Merge:A[6],Return
//Merge:A[7],Return
//Combine:A[6...6...7] = {3,5}
//Merge:A[8],Return
//Combine:A[6...7...8] = {3,3,5}
//Merge:A[9..11]
//Merge:A[9..10]
//Merge:A[9],Return
//Merge:A[10],Return
//Combine:A[9...9...10] = {0,1}
//Merge:A[11],Return
//Combine:A[9...10...11] = {0,1,3}
//Combine:A[6...8...11] = {0,1,3,3,3,5}合并的6-11下标数据
//Combine:A[0...5...11] = {0,1,2,3,3,3,5,7,7,9,11,11} 全部合并起来
#include "stdio.h"
//函数功能:将Array数据中的[left..middle]和[middle+1..right]两个数据序列
// (这两个序列假设已经为升序序列)进行升序组合
//输入: Array: 待组合序列
// left: 左侧序列开始下标位置
// middle:左侧序列结束下标位置,同时middle+1为右侧序列开始下标位置
// right: 右侧序列结束下标位置
//输出: Array: 已组合排序的序列
//返回: 0申请内存错误,1成功
int Combine(int *Array,int left,int middle,int right)
{
int i,i1,i2;
int start = left;
int *pArrayNew;
if (right == left) return;
pArrayNew = (int*)malloc((right-left+1)*sizeof(int));
if (NULL == pArrayNew) {
printf("Error Sort:Can't Alloc Memery!\n");
return 0;
}
i = 0;
i1 = left;
i2 = middle+1;
while(start <= right) {
start++;
if (i1 == (middle+1)) { //左侧数据合并完毕,只合并右侧数据
pArrayNew[i++] = Array[i2++];
continue;
}
if (i2 == (right+1)) { //右侧数据合并完毕,只合并左侧数据
pArrayNew[i++] = Array[i1++];
continue;
}
if (Array[i1] < Array[i2]) {
pArrayNew[i++] = Array[i1++];
} else {
pArrayNew[i++] = Array[i2++];
}
}
memcpy(&Array[left],pArrayNew,(right-left+1)*sizeof(int));
printf("Combine:A[%d...%d...%d] = {",left,middle,right);
for (i = left; i <= right;i++) {
printf("%d",Array[i]);
if (i != right) {
printf(",");
}
}
printf("}\n");
free(pArrayNew);
return 1;
}
//函数功能:将piArrayIn数据中的iSize个数据进行升序排序
//输入: piArrayIn:待排序序列
// iStart:排序数据的开始位置下标,取0
// iEnd: 排序数据的最后位置下标,取piArrayIn的长度-1
//输出: piArrayIn:已排序序列
//返回: 0申请内存错误,1成功
int MergeSort(int *piArrayIn,int iStart,int iEnd)
{
int iMid;
if (iStart == iEnd) {
printf("Merge:A[%d],Return\n",iStart);
return;
}
printf("Merge:A[%d..%d]\n",iStart,iEnd);
iMid = (iEnd - iStart)/2;
if ( MergeSort(piArrayIn,iStart,iStart+iMid) == 0) {
return 0;
}
if ( MergeSort(piArrayIn,iStart+iMid+1,iEnd) == 0) {
return 0;
}
return Combine(piArrayIn,iStart,iStart+iMid,iEnd);
}
////////////////////////////////////////////////////////
//TEST Code
#define ARRAY_LEGTH 12
int A[ARRAY_LEGTH];
int main()
{
int i;
srand((int)time(0));
printf("Example for Divide and Conquer Sort!\n");
printf("Input Array A[%d] = {",ARRAY_LEGTH);
for (i = 0; i < ARRAY_LEGTH; i++) {
A[i] = rand()%ARRAY_LEGTH;
printf("%d",A[i]);
if (i != ARRAY_LEGTH-1) {
printf(",");
}
}
printf("}\n");
printf("Sort...\n");
MergeSort(A,0,ARRAY_LEGTH-1);
printf("After Sort:A[%d] = {",ARRAY_LEGTH);
for (i = 0; i < ARRAY_LEGTH; i++) {
printf("%d",A[i]);
if (i != ARRAY_LEGTH-1) {
printf(",");
}
}
printf("}\n");
return 1;
}