1.插入排序
由N-1趟排序组成,对于p=1到p=N-1趟,插入排序保证从位置0到位置p上的元素为已排序状态。
时间复杂度:O(N^2)
{
int j,p;
ElementType Tmp;
for(p=1;p<N;p++)
{
Tmp=A[j];//把A[j]保存下来,因为它要被插入到前面的某个位置去
for(j=p;j>0&&A[j-1]>Tmp;j--)//大于A[j]的元素逐个后移
{
A[j]=A[j-1];
}
A[j]=Tmp;
}
}
2.希尔排序
希尔排序使用一个序列h1,h2,h3,ht,叫做增量排序。在使用增量hk的一趟排序之后,对于每个i我们有A[i]<A[i+hk],所有相隔hk的元素被排序。
时间复杂度:O(N^(1+a)),其中0<a<1。
void ShellSort(ElementType A[],int N)
{
int j,p,Increment;
ElementType Tmp;
for(Increment=N/2;Increment>0;Increment/=2)
{
for(p=Increment;p<N;p++)
{
Tmp=A[p];
for(j=p;j>=Increment;j-=Increment)
{
if(A[j]<A[j-Increment])
A[j]=A[j-Increment];
else
break;
}
A[j]=Tmp;
}
}
}
3. 堆排序
思想:建立小顶堆,然后执行N次deleteMin操作。
时间复杂度:O(NlogN),实践中,慢于sedgewick的希尔排序
空间复杂度:O(N),用于建立堆得数组
4.归并排序
使用递归把数组分为两部分分别排序,然后合并成一个数组
时间复杂度:O(NlogN)
空间复杂度:O(N)
{
int i, LeftEnd, NumELements,TmpPos;
LeftEnd=Rpos-1;
TmpPos=Lpos;
NumElements=RightEnd-Lpos+1;
while(Lpos<=LeftEnd&&Rpos<=RightEnd)
TmpArray[TmpPos++]=(A[Lpos]<A[Rpos])?A[Lpos++]:A[Rpos++];
while(Lpos<LeftEnd)
TmpArray[TmpPos++]=A[Lpos++];
while(Rpos<RightEnd)
TmpArray[TmpPos++]=A[Rpos++];
for(i=0;i<NumElements;i++,RightEnd--)
A[RightEnd]=TmpArray[RightEnd];
}
5.快速排序
对于小数组(N<20),快排不如插排好。一种好的截止范围是N=10,大于10则用快排。
快排的四步:
①如果S中元素个数是0或1,则返回
②取S中间元素v为枢纽元
③将S-{v}分成两个不相交的集合:分别是S1(小于v),和大于v的部分S2
④返回quicksort(S1),继随v,继而quicksort(S2)
时间复杂度:O(NlogN)
编程思想:1.选取枢纽元,取首尾及中间的三个元素,排序,小的排在首位,大的排在尾部,中的作为枢纽元
2.排序时把枢纽元放在Right-1的位置上,i=Left+1;j=Right-2;开始交换过程
{
int center =(Left+Right)/2;
if(A[Left]>A[Center])
swap(&A[Left],&A[Center]);
if(A[Left]>A[Right])
swap(&A[Left],&A[Right]);
if(A[Center]>A[Right])
swap(&A[Center],&A[Right]);
swap(&A[Center],&A[Right-1]);
return A[Right-1];
}
Qsort(ElementType A[],int Left,int Right)
{
int i,j;
ElementType Pivot;
if(Left+9<Right) //10个元素以上的数组使用快排
{
Pivot=Median3(A[],Left,Right);
i=Left+1;
j=Right-2;
while(A[i++]<Pivot);
while(A[j--]>Pivot);
if(i<j)
swap(&A[i],&A[j])
else
break;
swap(&A[i],&A[Right-1]);
Qsort(A,Left,i-1);
Qsort(A,i+1,Right);
}
else
InsertSort(A,Right-Left+1);
}
6.直接选择排序
描述:选出数组中最小的元素,与数组的第一个元素交换;然后选择出数组中次小的元素,与与第二个元素交换,直到完成
选择排序需要比较N(N-1)/2次,即N2次,而交换则只需要N-1次
对于是否已经排好序,或者随机文件,所花费的时间是一致的,即执行时间具有强迫性
选择排序应用在数据项比较大,键比较小的情况下,因为此时移动元素花费时间较多,而对于其他排序算法,元素移动频繁的多
{
int i, j;
int min;
for(i=0; i<N-1; i++)
{
min = i;
for(j=i+1; j<=N-1; j++)
if(A[j]<A[min]) min=j;
swap(A[i],A[min]);
}
}