您的位置:首页 > 其它

归并排序

2014-03-07 13:49 330 查看
归并排序利用分治法,每次将原序列分为大小基本相等的两个子序列,将两个子序列分别排好序后,再将两个子序列合并为排好序的原序列,而长度大于一的子序列可以递归地分解成更小的子序列,从而递归的用归并排序来解决。因此,递归排序的关键在于如何合并。

简单的归并排序的合并过程是需要借助临时数组的,因此还是比较费空间的。所以如果用对链表组成的序列的排序,归并排序可以不需要额外的空间,这样会更好。

如下是基于数组的序列的归并代码:

void MergeSort(int* pData,int length)
{
int* pTemp = new int[length];

DoMergeSort(pData,pTemp,0,length-1);

delete[] pTemp;
}

void DoMergeSort(int* pData,int* pTemp,int low,int high)
{
if(low == high)
return;

int middle = (low+high) /2 ;
DoMergeSort(pData,pTemp,low,middle);
DoMergeSort(pData,pTemp,middle+1,high);

for(int i=low;i<=high;++i)
pTemp[i] = pData[i];

int left = low;
int right = middle+1;

for(int i=low;i<=high;++i)
{
if(left>middle)
pData[i] = pTemp[right++];
else if(right > high)
pData[i] = pTemp[left++];
else
{
if(pTemp[left] < pTemp[right])
pData[i] = pTemp[left++];
else
pData[i] = pTemp[right++];
}
}
}


下面是对上面合并方法的一个简单变种:

void MergeSort2(int* pData,int length)
{
int* pTemp = new int[length];

DoMergeSort2(pData,pTemp,0,length-1);

delete[] pTemp;
}

void DoMergeSort2(int* pData,int* pTemp,int low,int high)
{
if(low == high)
return;

int middle = (low+high) /2 ;
DoMergeSort(pData,pTemp,low,middle);
DoMergeSort(pData,pTemp,middle+1,high);

for(int i=low;i<=middle;++i)
pTemp[i] = pData[i];
for(int j=1;j<=high-middle;++j)
pTemp[high-j+1] = pData[middle+j];

for(int i=low,left=low,right=high;i<=high;++i)
{
if(pTemp[left] < pTemp[right])
pData[i] = pTemp[left++];
else
pData[i] = pTemp[right--];
}
}


变化之处,就是在从主数组将数据拷贝到临时数组的时候,左边部分是顺序拷贝的,但是右边部分则是倒序拷贝的,最终的结果就是在临时数组中,从low到middle这段是递增的,而从middle+1到high这一段时递减的。于是,在下面的拷贝数据回原数组的过程中,就需要从两端开始,往中间拷贝,从而使回到原数组中的数据再次全部变成递增的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: