归并排序

  先介绍下分治法,分治法就是将原问题分解为几个规模较小但在形式上跟原问题一样的子问题,递归地求解这些子问题,然后再合并这些子问题的解,来建立原问题的解。归并排序就是典型的遵循分治法思想的算法,归并排序的每一步,都将原问题分解为左右两部分,处理完这两部分后,将此两部分合并,再往上递归,最后就是整个问题的解了。

  考虑以下序列:

4

6

1

3

9

5

8

2

  此时,将此问题分解为两半

  

  继续分解,直接每部分只有两个元素,例如左边分解为以下两部分

  

  这个时候,直接对这两部分分别排序,因为这两部分刚好是排好序的,所以得到

  

  这个时候,需要对这两部分的处理结果进行合并处理,合并的时候需要一个额外的空间(设为A)来存储此合并结果,合并完后,再将此空间内的数据,覆盖到原空间中去。合并处理流程如下:同时对左右两部分中的元素进行遍历,如下图所示:

  

  此时比较两部分所指向的元素,1比较小,则将1拷贝到A中,然后将右边的指针指向下一个元素,依次类推,将3和4比较,3比较小,则将3拷贝到A中后, 右边的拷贝完了,将不再从中取元素,而从左边依次将元素拷贝到A中,最后A的结果如下:

1

3

4

6

  同样的,右边的进行处理后,将得到

2

5

8

9

  然后,再次对                                        

  

  进行以上合并操作,就是最后的解了

void MergeSort(int numArr[], int size){  
    int* pBuff = new int[size];  
    _MergeSort(numArr, pBuff, 0, size - 1);  
    delete[] pBuff;  
}  
void _MergeSort(int numArr[], int pBuff[], int left, int right){  
    if (right > left){  
        int mid = (left + right) / 2;  
        _MergeSort(numArr, pBuff, left, mid);  
        _MergeSort(numArr, pBuff, mid + 1, right);  
  
        //将numArr[left,mid]和numArr[mid + 1,right]合并  
        _Merge(numArr, pBuff, left, mid + 1, right);  
    }  
}  
void _Merge(int numArr[], int pBuff[], int lPos, int rPos, int rEnd){  
    int nLEnd = rPos - 1;  
    int i = lPos;  
    int j = rPos;  
    int n = 0;  
    int nSize = rEnd - lPos + 1;  
    while (true){  
        if (i <= nLEnd && j <= rEnd)  
            pBuff[n++] = (numArr[i] < numArr[j]) ? numArr[i++] : numArr[j++];  
        else if (i <= nLEnd)  
            pBuff[n++] = numArr[i++];  
        else if (j <= rEnd)  
            pBuff[n++] = numArr[j++];  
        else  
            break;  
    }  
    memcpy(numArr + lPos, pBuff, nSize * sizeof(int));  
}  

   以上代码最关键的部分就是_Merge函数,要做到合并的时候,各部分不越界,要非常细致的检查合并的左右部分的超始和终止位置,还有,不要在_Merge函数中进行申请缓存区的操作,因为_Merge函数的大量调用,进行malloc操作会大大降低算法速度,只在最外层调用一次申请内存操作就可以了。

  归并排序的时间复杂度为O(NlogN)

转载于:https://www.cnblogs.com/zengyg/p/8735075.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值