对本文出现的排序算法的分析见http://blog.csdn.net/libinjlu/article/details/12859211
1.插入排序
template <typename Comparable>
void insertionSort(vector<Comparable>& a)
{
int j;
for(int p=1;p<a.size();p++)
{
Comparable tmp=a[p];
for(j=p;j>0&&tmp<a[j-1];j--)
a[j]=a[j-1];
a[j]=tmp;
}
}
有R个逆序,因此运行时间为O(R+N)。若逆序数为O(N),则以线性时间运行。R为N(N-1)/4,因此为Ω(N^2).
2.希尔排序(有时也叫缩减增量排序)
a.希尔排序(基于插入排序,使用希尔增量)
template <typename Comparable>
void shellsort(vector<Comparable>& a)
{
for(int gap=a.size()/2;gap>0;gap/=2)
for(int i=gap;i<a.size();i++)
{
Comparable tmp=a[i];
int j=i;
for(;j>=gap&&tmp<a[j-gap];j-=gap)
a[j]=a[j-gap];
a[j]=tmp;
}
}
b.希尔排序(基于简单交换排序,使用希尔增量)
void shellsort(int v[],int n)//based on simple exchange sort
{
int gap,i,j,temp;
for(gap=n/2;gap>0;gap/=2)
for(i=gap;i<n;i++)
for(j=i-gap;j>=0&&v[j]>v[j+gap];j-=gap){
temp=v[j];
v[j]=v[j+gap];
v[j+gap]=temp;
}
}
使用希尔增量的希尔排序每一趟排序是插入排序或简单交换排序,因此最坏是O(N^2)的。
3.堆排序
inline int leftChild(int i)//root index is 0
{
return 2*i+1;
}
template <typename Comparable>
void percDown(vector<Comparable>& a,int i,int n)
{
int child;
Comparable tmp;
for(tmp=a[i];leftChild(i)<n;i=child)
{
child=leftChild(i);
if(child!=n-1&&a[child]<a[child+1])//if there is right child
child++;
if(tmp<a[child])
a[i]=a[child];
else
break;
}
a[i]=tmp;
}
template <typename Comparable>
void heapsort(vector<Comparable>& a)
{
for(int i=a.size()/2;i>=0;i--)//buildHeap
percDown(a,i,a.size());
for(int j=a.size()-1;j>0;j--) //deleteMax
{
swap(a[0],a[j]);//通过最大堆将数组以递增序排列,可节省一个辅助数组。
percDown(a,0,j);
}
}
构建堆花费O(N),然后执行N次deleteMax操作,每次花费O(log N)。因此总运行时间为O(N log N)。
4.归并排序
template <typename Comparable>
void merge(vector<Comparable>& a,vector<Comparable>&tmpArray,int leftPos,int rightPos,int rightEnd)
{
int leftEnd=rightPos-1;
int tmpPos=leftPos;
int numElements=rightEnd-leftPos+1;
while(leftPos<=leftEnd&&rightPos<=rightEnd)
{
if(a[leftPos]<a[rightPos])
tmpArray[tmpPos++]=a[leftPos++];
else
tmpArray[tmpPos++]=a[rightPos++];
}
while(leftPos<=leftEnd)
tmpArray[tmpPos++]=a[leftPos++];
while(rightPos<=rightEnd)
tmpArray[tmpPos++]=a[rightPos++];
for(int i=0;i<numElements;i++,rightEnd--)
a[rightEnd]=tmpArray[rightEnd];
}
template <typename Comparable>
void mergeSort(vector<Comparable>& a,
vector<Comparable>& tmpArray,int left,int right)
{
if(left<right)
{
int center=(left+right)/2;
mergeSort(a,tmpArray,left,center);
mergeSort(a,tmpArray,center+1,right);
merge(a,tmpArray,left,center+1,right);
}
}
template <typename Comparable>
void mergeSort(vector<Comparable>& a)
{
vector<Comparable> tmpArray(a.size());
mergeSort(a,tmpArray,0,a.size()-1);//单参驱动多参函数
}
O(N log N)。
5.快速排序
从左向右依次判断,取中间索引为分划枢纽:
//order v ascendent
void qsort(int v[],int left,int right)
{
int i,last;
void swap(int v[],int i,int j);
if(left>=right)
return;
swap(v,left,(left+right)/2);//the element to depart
last=left;//to v[0]
for(i=left+1;i<=right;i++)//depart
if(v[i]<v[left])
swap(v,++last,i);
swap(v,left,last);//move the depart element to the right place
qsort(v,left,last-1);//the left half
qsort(v,last+1,right);//the right half
}
void swap(int v[],int i,int j)
{
int temp;
temp=v[i];
v[i]=v[j];
v[j]=temp;
}
从左右向中间判断,取中间值为分划枢纽:
template <typename Comparable>
void insertionSort(vector<Comparable>& a,int left,int right)
{
int j;
for(int p=left+1;p<=right;p++)
{
Comparable tmp=a[p];
for(j=p;j>0&&tmp<a[j-1];j--)
a[j]=a[j-1];
a[j]=tmp;
}
}
/**
*Return median of left,center,right.
*Order these and hide the pivot.
*/
template <typename Comparable>
const Comparable& median3(vector<Comparable>& a,int left,int right)
{
int center=(left+right)/2;
if(a[center]<a[left])
swap(a[left],a[center]);
if(a[right]<a[left])
swap(a[right],a[left]);
if(a[right]<a[center])
swap(a[right],a[center]);
swap(a[center],a[right-1]);//place pivot at position right-1
return a[right-1];
}
template <typename Comparable>
void quicksort(vector<Comparable>& a,int left,int right)
{
if(left+10<=right)//qsort
{
Comparable pivot=median3(a,left,right);
//Begin partitioning
int i=left,j=right-1;
for(;;)
{
while(a[++i]<pivot);
while(pivot<a[--j]);
if(i<j)
swap(a[i],a[j]);
else
break;
}
swap(a[i],a[right-1]);//Restore pivot
quicksort(a,left,i-1);
quicksort(a,i+1,right);
}
else//insertion sort on the subarray
insertionSort(a,left,right);
}
template <typename Comparable>
void quicksort(vector<Comparable>& a)
{
quicksort(a,0,a.size()-1);
}
快速选择:
//to find the kth smallest
//place it in a[k-1]
template <typename Comparable>
void quickSelect(vector<Comparable>& a,int left,int right,int k)
{
if(left+10<=right)//qsort
{
Comparable pivot=median3(a,left,right);
//Begin partitioning
int i=left,j=right-1;
for(;;)
{
while(a[++i]<pivot);
while(pivot<a[--j]);
if(i<j)
swap(a[i],a[j]);
else
break;
}
swap(a[i],a[right-1]);//Restore pivot
if(k<=i)
quickSelect(a,left,i-1,k);
else if(k>i+1)
quickSelect(a,i+1,right,k);
//succeed !!
}
else//insertion sort on the subarray
insertionSort(a,left,right);
}
最坏是O(N^2),平均为O(N)
6.间接排序(对象占用空间大,复制开销大)
template <typename Comparable>
class Pointer
{
public:
Pointer(Comparable *rhs=NULL):pointee(rhs){};
bool operator<(const Pointer& rhs)const//for compare in quicksort
{
return *pointee<*rhs.pointee;
}
operator Comparable*()const//类型转换
{
return pointee;
}
private:
Comparable* pointee;
};
template <typename Comparable>
void largeObjectSort(vector<Comparable>& a)
{
vector<Pointer<Comparable> > p(a.size());
int i,j,nextj;
for(i=0;i<a.size();i++)
p[i]=&a[i];
quicksort(p);
//shuffle items in place
for(i=0;i<a.size();i++)
if(p[i]!=&a[i])
{
Comparable tmp=a[i];
for(j=i;p[j]!=&a[i];j=nextj)
{
nextj=p[j]-&a[0];
a[j]=*p[j];
p[j]=&a[j];
}
a[j]=tmp;
p[j]=&a[j];
}
}
最坏的情况为3N/2次复制。