归并排序
算法步骤:
先对子集排序,再归并。
首先归并是最简单的,
先写归并,把两个有序子集合并
void Merge(vector<int> &src ,vector<int> &des, int low, int mid ,int high)
{
int i = low; //左边的集合开始索引
int j = mid +1; //右边的集合开始索引
int k = low; //最后保存的集合索引
while( (i <= mid )&& ( j <= high))
{
if(src[i] <= src[j])
des[ k++ ] = src[i++];
else
des[ k++ ] = src[j++];
}
//如果左边集合还有剩余
while( i<= mid)
{
des[k++] = src[i++];
}
while( j<= high)
{
des[k++] = src[j++];
}
//把排好序的数据放回原来集合
for(int i = istart; i <= iend ;i ++)
*(pSrc + i ) = *(pDes + i);
那下面的问题是子集如何划分呢。
对下面数据进行排列
由此可见,子表的划分是以下过程
1.设每个子表长为1
2.相邻子表合并,有序表长加倍。
3.循环执行,直至表长。
注意:考虑循环时,会存在两种情况,(1)最后的数据一个集合长度正好,一个集合比较少
(2)最后的数据就剩一个集合,或者小于
//一次merge过程
void MergePass(vector<int> &src , vector<int> &des ,int len)
{
int length = src.size();
for(int i = 0 : i < n - 2*len ; i = i + len*2)
{
Merge(src,des,i,i+len-1,i+2*len-1);
}
if( i + len -1 <= n)
Merge(src,des,i,i+len-1,length -1);
else
while(i < n)
des[i] = src[i];
}
// 主函数
void mergesort(vector<int> &src)
{
vector<int> des;
int i = 0;
while( i < src.size())
{
MergePass(src,des,i);
i = i *2;
}
}
那递归应该怎么做呢?
很简单
void MergeSort2(vector<int> &src ,vector<int> &des ,int s ,int t)
{
if( s== t)
des[s] = src [s];
else
{
int m = (s + t) / 2;
MergeSort2(src,des,s,m);
MergeSort2(src,des,m+1,t);
Merge(des,src,s,m,t); //归并到src中
}
}
}
// MergeSort.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void MergeSort(int* pSrc ,int iSize);
void MergeSort1(int* pSrc ,int* pDes ,int iLow,int iHight);
int _tmain(int argc, _TCHAR* argv[])
{
int a[7] = {1,5,7,2,4,6,9};
int *b = new int[7];
MergeSort(a,7);
MergeSort1(a,b,0,6);
for(int i = 0 ; i < 7; i++)
cout<<b[i];
delete []b;
return 0;
}
// 归并两个有序的子序列
void Merge(int* pSrc, int* pDes, int istart,int imid ,int iend )
{
int iLeftIndex = istart;
int iRightIndex = imid + 1;
int idesIndex = istart;
while( (iLeftIndex <= imid )&&(iRightIndex <= iend))
{
if( *(pSrc + iLeftIndex) <= *(pSrc + iRightIndex) )
{
*(pDes + idesIndex) = *(pSrc + iLeftIndex);
iLeftIndex++;
idesIndex++;
}
else
{
*(pDes + idesIndex) = *(pSrc + iRightIndex);
iRightIndex++;
idesIndex++;
}
}
//如果左边还有剩余
while(iLeftIndex <= imid )
{
*(pDes + idesIndex) = *(pSrc + iLeftIndex);
idesIndex ++;
iLeftIndex++;
}
如果右边还有剩余
while(iRightIndex <= iend)
{
*(pDes + idesIndex) = *(pSrc + iRightIndex);
iRightIndex++;
idesIndex++;
}
//把排好序的数据放回原来集合
for(int i = istart; i <= iend ;i ++)
*(pSrc + i ) = *(pDes + i);
}
//一次归并排序
/*
参数 iLen表示子表的长度
参数 iSize表示原数组长度
*/
void MergePass(int* pSrc, int* pDes, int iLen, int iSize)
{
int i = 0;
while( i <= iSize - 2*iLen)
{
Merge(pSrc,pDes,i,i + iLen -1, i + 2 * iLen -1);
i = i + 2* iLen;
}
//还剩两个子序列且其中一个长度小于 iLen
if( i + iLen + 1 <= iSize)
Merge(pSrc,pDes,i,i + iLen -1, iSize -1);
else
//还剩小于等于一个子序列,此次不归并
while( i < iSize)
{
*(pDes + i) = *(pSrc + i);
i++;
}
}
//归并主程序
void MergeSort(int* pSrc ,int iSize)
{
int *pTmp = new int[iSize];
int i = 1;
while( i < iSize)
{
MergePass(pSrc,pTmp,i,iSize);
i = i * 2;
}
delete []pTmp;
for(int j = 0; j < iSize ; j++)
{
cout<< *(pSrc + j);
}
cout<<endl;
}
//递归算法
void MergeSort1(int* pSrc ,int* pDes ,int iLow,int iHight)
{
if(iLow == iHight)
{
*(pDes + iLow) = *(pSrc + iLow);
return;
}
if(iLow < iHight)
{
int imid = (iLow + iHight) / 2;
MergeSort1(pSrc,pDes,iLow,imid);
MergeSort1(pSrc,pDes,imid + 1,iHight);
Merge(pDes,pSrc,iLow,imid,iHight);
for(int i = iLow ; i< iHight;i++)
*(pDes + i) = *(pSrc + i);
}
}