首先,歸併排序,分治,遞歸解決小的範圍,再合併兩個有序的小範圍數組,便得到整個有序的數組。
這是很適合用遞歸來寫的,至於非遞歸,便是從小到大,各個擊破,從而使得整個數組有序。代碼如下:
void merge(vector<int> &A, int left, int mid, int right)
{
int i=left,j=mid+1;
vector<int> tmp(right-left+1,0);
int k=0;
while(i<=mid&&j<=right)
{
if(A[i] < A[j]) tmp[k++]=A[i++];
else tmp[k++]=A[j++];
}
while(i<=mid)tmp[k++]=A[i++];
while(j<=right)tmp[k++]=A[j++];
//write to A
for(int i=0;i<right-left+1;++i)
{
A[left+i]=tmp[i];
}
}
void mergeSort(vector<int> &A)
{
const int n=A.size();
int step=1;
int left=0,right,mid;
while(step< n)
{
left=0;
while(left+step<n)
{
mid=left+step-1;
right=mid+step;
if(right>=n) right=n-1;
merge(A,left,mid,right);
left=right+1;
}
step *= 2;
}
}
int partition(vector<int> &A, int left, int right)
{
int pivot=A[right];
int i=left;
for(int k=left;k<right;++k)
{
if (A[k] < pivot) swap(A[i++],A[k]);
}
swap(A[i],A[right]);
return i;
}
void quickSort(vector<int> &A)
{
stack<pair<int,int> > s;
const int n = A.size();
if(n <2 ) return;
int left=0,right=n-1;
s.push(make_pair(left, right));
while(!s.empty())
{
auto cur=s.top();s.pop();
left=cur.first;right=cur.second;
if(left>=right)continue;
int mid=partition(A,left,right);
s.push(make_pair(left, mid-1));
s.push(make_pair(mid+1, right));
}
}
寫習慣了這兩種排序的遞歸版本,此處的非遞歸版本確實不是那麼自然而然的,但是隻要記住遞歸的版本一定可以使用棧來模擬遞歸的過程,那麼我們同樣可以實現非遞歸的版本,此文就是一份備忘吧。