遞歸的歸并排序很常見,本文在遞歸的基礎上,給出了非遞歸的寫法。
//遞歸的寫法
void Merge(vector<int>& ans, vector<int>& src, int left, int mid, int right) //對一個vector中兩個排序好的部分進行合并
{
int i = left, j = mid+1, k=left;
while (i<=mid && j<=right)
{
ans[k++] = src[i] <= src[j] ? src[i++] : src[j++];
}
while (i<=mid) { ans[k++] = src[i++]; }
while (j<=right) { ans[k++] = src[j++];
}
}
void MergePass(vector<int>& ans, vector<int>& src, int left, int right)
{
int n = src.size();
vector<int> v3(n); //給出n的大小
if (left == right) ans[left] = src[left];
else {
int mid = (right - left)/2 + left;
MergePass(v3,src,left,mid);
MergePass(v3,src,mid+1,right); //将資料存放到v3中
Merge(ans,v3,left,mid,right); //将v3中的資料進行合并
}
}
void MergeSort(vector<int>& ans,vector<int>& src)
{
int n = src.size();
MergePass(ans,src,0,n-1);
}
//非遞歸的方法
void Merge(vector<int>& ans, vector<int>& src, int left, int mid, int right)
{
int i = left, j = mid+1, k=left;
while (i<=mid && j<=right)
{
ans[k++] = src[i] <= src[j] ? src[i++] : src[j++];
}
while (i<=mid) { ans[k++] = src[i++]; }
while (j<=right) { ans[k++] = src[j++];
}
}
void NiceMergePass(vector<int>& ans, vector<int>& src, int n, int s)
{
int i=0;
for (i;i+2*s-1<=n-1;i=i+2*s) //判斷是否滿足2s的大小,若滿足,則可以進行2s大小的合并
{
Merge(ans,src,i,i+s-1,i+2*s-1);
}
if (i+s <= n-1) //此步為不夠2s大小,但是大于s,比如s為4,剩下的資料為5,則将4個與一個進行合并
{
Merge(ans,src,i,i+s-1,n-1);
}
else //剩下的資料不夠s
{
ans[i] = src[i];
i++;
}
}
void NiceMergeSort(vector<int>& src)
{
int n = src.size();
vector<int> ans(n);
int s = 1; //s為進行歸并的大小,從1開始,成倍增長
while (s<n) //若s的大小大于vector的長度,則終止
{
NiceMergePass(ans,src,n,s); //将src分别進行兩個s大小的合并,至ans中
s+=s;
NiceMergePass(src,ans,n,s); //将ans分别進行兩個s大小的合并,至src中
s+=s;
}
}
河漢清且淺,相去複幾許。