码迷,mamicode.com
首页 > 编程语言 > 详细

排序算法——归并排序

时间:2017-12-11 15:06:22      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:col   中移动   ali   相对   div   ges   次数   循环   运行时   

三、归并排序(Merge Sort) 

/**
* 归并排序的驱动程序
*/
void mergeSort(vector<int> &a)
{
    vector<int> tmpArray(a.size());
    mergeSort(a, tmpArray, 0, a.size() - 1);
}
技术分享图片
/**
* 进行递归调用的内部方法
* a为待排序数组
* tmpArray为存放归并排序结果的数组
* left为子数组的最左元素的下标
* right为子数组最右元素的下标
*/
void mergeSort(vector<int> &a, vector<int> &tmpArray, int left, int right)
{
    if (left < right)
    {
        int center = (left + right) / 2;
        mergeSort(a, tmpArray, left, center);  //左半部分序列
        mergeSort(a, tmpArray, center + 1, right);  //右半部分序列
        merge(a, tmpArray, left, center + 1, right);
    }
}
View Code
技术分享图片
/**
* 合并子数组已排序的两半部分
* leftPos:子数组最左元素的下标
* rightPos:后半部分起点的下标
* rightEnd:子数组最右元素的下标
*/
void merge(vector<int> &a, vector<int> &tmpArray, int leftPos, int rightPos, int rightEnd)
{
    int leftEnd = rightPos - 1; //左半部分末尾的位置
    int tmpPos = leftPos;
    int numElements = rightEnd - leftPos + 1;

        /* 主循环:两区间段都未结束时 */
    while (leftPos <= leftEnd && rightPos <= rightEnd)
    {
        if (a[leftPos] <= a[rightPos])
            tmpArray[tmpPos++] = a[leftPos++];
        else
            tmpArray[tmpPos++] = a[rightPos++];
    }
        
        /* 复制前半部分的剩余元素 */
    while (leftPos <= leftEnd)
        tmpArray[tmpPos++] = a[leftPos++];
        
        /* 复制后半部分的剩余元素 */
    while (rightPos <= rightEnd)
        tmpArray[tmpPos++] = a[rightPos++];

        /* 将tmpArray复制回原数组a */
    for (int i = 0; i < numElements; ++i)
    {
        a[rightEnd] = tmpArray[rightEnd]; //注:rightEnd未变
        rightEnd--;
    }
}
View Code

思路:“分治”

          “分”:数组尽可能分,一直分到原子级别 ——logN

          “并”:将原子级别的数两两归并排序,并产生最后结果 ——O(N)

           ——O(NlogN)

步骤:

  1)基准情形:N=1,无需排序

  2)N>1,递归地将前半部分数据a[left,...,center]和后半部分数据a[center+1,...,right]各自归并排序,再用合并算法将这两部分合在一起

  3)合并算法:

             取两个输入数组A,B,一个输出数组C,3个计数器pA,pB,pC,初始置于对应数组的头部;

              A[pA]和B[pB]中的较小者被复制到C中的下一个位置,相关计数器向前推进一步;

             当两个输入表中有一个用完时,将另一个表中剩余的部分复制到C中。

eg.     原始数组 {24,15,1,26,13,27,2,28}             

          拆分: 

技术分享图片 

          合并:

 技术分享图片

时间复杂度:

       归并排序的运行时间为O(NlogN)

  N=1,时间为常数,记为1。

        N>1,用时为2T(N/2)+N(合并所花时间)

   T(N) = 2T(N/2)+N

        两边除以N,得到

        T(N)/N=T(N/2)/(N/2)+1

        T(N/2)/(N/2)=T(N/4)/(N/4)+1

         ......

        T(2)/2=T(1)/1+1

        相加可得 T(N) =NlogN+N =O(NlogN) 

适用情形: 

  归并排序需要使用额外的内存(临时数组),且运行时间严重依赖于比较元素在数组(及临时数组)中移动元素的相对开销,耗时,效率比不上快速排序。

       但其使用的比较次数几乎是最优的,且实现简单,概念简单。

 

排序算法——归并排序

标签:col   中移动   ali   相对   div   ges   次数   循环   运行时   

原文地址:http://www.cnblogs.com/warrior1988/p/8023043.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!