您的位置:首页 > 其它

简谈算法之:并归排序(Merge Sort)

2014-09-29 10:33 253 查看
并归排序是分治算法的入门级算法,其中又包含了递归的要素。其核心思想是把一个待排序的集合或者说成是数组平分成两部分排序,先排好左边的再排好右边的,最后合并两个有序子数组形成最后有序的数组。只要将这个思想递归使用便完成了我们的并归排序了。
对于算法刚入门的人来说,我想并归排序是一个相当有意思的算法,也许会问:“怎么就先排左边再排右边,最后合起来就得到要排序的数组呢?”,是的笔者当年也是为这个问题想了很久,很费解。到后来笔者是这样理解,首先并归排序他是递归的那么理解递归好的办法是从底至顶理解。什么是递归的底呢?那一定是递归停止条件。
在并归排序的递归停止条件就是,当数组只有一个元素的时候停止递归开始返回,设这样递归位置为LOW1,比这高的位置设为为LOW2,这个递归位置包含两个LOW1的返回(一个左边一个右边即LOW2有两个元素),以此类推。对于并归排序,可以推算出总共有N个LOW1,N/2个LOW2,N/4个LOW3....,而这个编号最大等于lgN。
而理解并归排序关键起始是LOW2层,在这一层里我们有两个LOW1,我们可以认为是两个已经排好续的数组,那么我们可以很方便的在Θ (n)时间内将两个数组合并,如下面代码中的Merge函数,一旦完成Merge,则合并的有序数组作为LOW2的返回到LOW3层。在LOW3层重复Merge方法并将有序数组作为返回到LOW4。一直这个过程直到返回至第一次调用,此时便已经得到排序好的数组。
接下来我们分析并归排序的算法复杂度。对于LOW1因为只有一个元素所以为Θ (1),而总计有N个LOW1,所以算法在LOW1层总计花销 N*Θ (1) = Θ (N),对于LOW2有两个元素需要合并则耗时Θ (2),总计N/2个LOW2,则LOW2层花费N/2*Θ (2)=Θ (N),如此我们总计有lgN个Θ (N),所以最后的并归排序的时间复杂度为lgN*Θ (N)=
Θ (NlgN)。
void Meage(int *pArry, int iP, int iMid, int iQ)
{
int iNum = iQ - iP + 1;
if(pArry[iMid] < pArry[iMid + 1])return ;//运气很好,两个子数组是有序的
int *pTmp = new int[iNum];
int tmp;
int i = iP;
int j = iMid + 1;
int k = 0;
for (;i <= iMid && j <= iQ;)
{
if (pArry[i] < pArry[j])
{
pTmp[k++] = pArry[i++];
}
else
{
pTmp[k++] = pArry[j++];
}
}

if(i > iMid)
{
memcpy(pTmp + k, pArry + j , sizeof(int) * (iQ - j + 1));
}
else if (j > iQ)
{
memcpy(pTmp + k, pArry + i , sizeof(int) * (iMid - i + 1));
}

memcpy(pArry + iP, pTmp, sizeof(int) * iNum);
delete []pTmp;
}
void MeageSort(int *pArry, int iP, int iQ)
{
if(iP == iQ) return;//停止递归的条件

int iMid = (iP + iQ) / 2;

//排左边
MeageSort(pArry, iP, iMid);
//再排右边
MeageSort(pArry, iMid + 1, iQ);
//合并两个子数组
Meage(pArry, iP, iMid, iQ);

}




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: