读书日记-归并排序算法

一、性能

  时间复杂度总为O(nlgn)。

二、思想:

  遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解。

算法导论对归并排序的描述是:

  分解:分解待排序的n个元素的序列成各具有n/2个元素的两个子序列。

  解决:使用归并排序递归地排序两个子序列。

  合并:合并两个已排序的子序列以产生已排序的答案。

 

即,1、不断平分序列,分解至序列长度为1。(此时不用比较,长度1的每个序列都已排好序)

  2、递归"回升",将两个已排序的序列通过比较进行合并。


三、例子: 

96 20 60 33 72 02 42 57 22 50

 

对以上序列进行归并排序: 

 1、递归分解至序列个数为1。

  ->  {96,20,60,33,72,02,42,57,22,50}                             n = 10

  ->  {96,20,60,33,72},{02,42,57,22,50}         n =  5

  ->  {96,20},{60,33,72},{02,42},{57,22,50}       n  =  2|3

  ->   {96},{20},{60},{33,72},{02},{42},{57},{22,50}   n  = 1|2

  -> {96},{20},{60},{33},{72},{02},{42},{57},{22},{50}  n =1

  2、两两序列合并,递归"回升",比较排序

  -> {96},{20},{60},{33},{72},{02},{42},{57},{22},{50}  n =  1
  ->   {96},{20},{60},{33,72},{02},{42},{57},{22,50}         n  = 1|2
  ->    {20,96},{33,60,72},{02,42},{22,50,57}          n  = 2|3
  ->    {20,33,60,72,96},{02,22,42,50,57}            n =  5
  ->    {02,20,22,33,42,50,57,60,72,96}               n =  10

 

三、代码: 

  

/*
    @param  intArr 待排序输入数组
    @param   p     起始位置
    @param   q     中间位置
    @param   r      结束位置
    @param   tArr    缓存数组用于比较缓存
*/
void Merge(int* intArr,int p,int q,int r,int* tArr)
{
    int n1 = q - p+1;
    int n2 = r - q;
    int* lArr = tArr + p;
    int* rArr = lArr + n1 + 1;    
    memcpy(lArr,(intArr+p),n1*sizeof(int));    // 将左序列存至lArr
    memcpy(rArr,(intArr+q+1),n2*sizeof(int)); // 将右序列存至lArr
    lArr[n1] = 0xFFFF;//极大值 用于做哨兵位,后面比较不用判断索引超出
    rArr[n2] = 0xFFFF;//极大值
    
    int i =0,j=0;
    for(int k=p;k<=r;++k)
    {
        if(lArr[i]<=rArr[j])
        {
            intArr[k] = lArr[i];
            ++i;
        }
        else
        {
            intArr[k] = rArr[j];
            ++j;
        } 
    }
}
/*
    @param  intArr 待排序输入数组
    @param   p     起始位置
    @param   r     结束位置
    @param   tArr    缓存数组用于比较缓存
*/
void MergeSort(int* intArr,int p,int r,int* tArr)
{
    if(p<r)
    {
        int q = (p+r)/2; // 默认向下取整
        MergeSort(intArr,p,q,tArr);
        MergeSort(intArr,q+1,r,tArr);
        Merge(intArr,p,q,r,tArr);
    }
}
// 实际调用函数,一开始创建足够大的tArr数组,避免重复创建删除
void MergeSort_Real(int* intArr,int p,int r)
{
    if(p<r)
    {
        int * tArr = new int[r-p+3];
        MergeSort(intArr,p,r,tArr);
        delete[] tArr;
        tArr =NULL;
    }
}

 

posted @ 2015-12-09 09:24  稀饭lei___  阅读(248)  评论(0编辑  收藏  举报