合并排序,分治思想

来源:互联网 发布:简单的编程代码 编辑:程序博客网 时间:2024/05/02 11:47

2011-06-17 22:42:09

 

一般分法思想分为三个步骤:

分解:将原问题分解成一系列子问题

解决:递归解决各子问题。若子问题足够小,则直接求解

合并:将子问题的结果合并成原问题的解

 

 

合并排序就是用了这个思想。

分解:将n个元素分成各含 n / 2个元素的子序列

解决:用合并排序法对两个子序列递归地排序

合并:合并两个已排序的子序列以得到排序结果

 

子序列排序时,其长度为1时递归结束。单个元素已有序

 

下面用C实现如下

 

//为了计算方便,没有使用数组下标为0的元素,即下标从1开始int main(void){    long Start = 0,         End = 0;    int i;    int a[N + 1];       srand( ( unsigned ) time( NULL ));    End = clock();    printf("InsertSort Time:%ld/n", End - Start);    for (i = 1; i <= N; i++)    {        a[i] = ( int ) ( 90 * rand() / (RAND_MAX + 1.0) + 10);    //    printf("%4d", a[i]);    }    Start = clock();    MergeSort(a, 1, N);    End = clock();    printf("MergeSort Time:%ld/n", End - Start);//    OutputArray(a, N);    return 0;} /*MergeSort 采用分治法分治模式在第一层递归上都有三个步骤:分解:将原问题分解成一系列子问题解决:递归解决各子问题。若子问题足够小,则直接求解合并:将子问题的结果合并成原问题的解*/#include <stdio.h>#include <stdlib.h>#include <time.h>#define N 100#define INFI 0x7FFFFFFF   //吵兵,为最大INT值void InsertSort(int nArray[], const int ArraySize);          //插入排序void OutputArray(int nArray[], const int ArraySize);         //输出数组数据void MergeSort(int nArray[], const int ArrayLeft, const int ArrayRight);         //合并排序void Merge(int nArray[], const int ArrayLeft, const int ArrayMid, const int ArrayRight);  //假设有10个元素//第一次分配// |- - - - - | - - - - -|//第二次分配// |- - - |- - | - - - - - |// 直到...// | - | - | - | - - | - - - - - |//即为终结状态的时候开始解决问题,并合并解void MergeSort(int nArray[], const int ArrayLeft, const int ArrayRight){    int ArrayMid;    if (ArrayLeft < ArrayRight)                        {                                                         ArrayMid = (ArrayLeft + ArrayRight) / 2;      //分为较小的区间        MergeSort(nArray, ArrayLeft, ArrayMid);       //处理前一部分区间        MergeSort(nArray, ArrayMid + 1, ArrayRight);  //处理后一部分区间        Merge(nArray, ArrayLeft, ArrayMid, ArrayRight); //合并解    }}void Merge(int nArray[], const int ArrayLeft, const int ArrayMid, const int ArrayRight){    int *pArrayLeft  = NULL,               *pArrayRight = NULL;    int nArrayl, nArrayr;         //左区域和右区域的元素个数    int i,j,k;    nArrayl = ArrayMid - ArrayLeft + 1;        nArrayr = ArrayRight - ArrayMid;    pArrayLeft  = (int *)malloc(sizeof (int) * (nArrayl + 1));    //多分配一个吵兵的位置    pArrayRight = (int *)malloc(sizeof (int) * (nArrayr + 1));       for(i = 0; i < nArrayl; i++)            //存储左区域    {        pArrayLeft[i] = nArray[ArrayLeft + i];    }    pArrayLeft[i] = INFI;       //吵兵    for(i = 0; i < nArrayr; i++)            //存储右区域    {        pArrayRight[i] = nArray[ArrayMid + i + 1];    }    pArrayRight[i] = INFI;      //吵兵    i = j = 0;    for (k = ArrayLeft; k <= ArrayRight; k++)         //合并解,至有序    {        if (pArrayLeft[i] <= pArrayRight[j])        {            nArray[k] = pArrayLeft[i];            i++;        }        else        {            nArray[k] = pArrayRight[j];            j++;        }    }    if (pArrayLeft)        free(pArrayLeft);    if (pArrayRight)        free(pArrayRight);}

原创粉丝点击