常用排序算法(转)

来源:互联网 发布:中国的宏观经济数据 编辑:程序博客网 时间:2024/04/29 07:18

1.插入排序

由N-1趟排序组成,对于p=1到p=N-1趟,插入排序保证从位置0到位置p上的元素为已排序状态。

时间复杂度:O(N^2)

代码
void InsertionSort(ElementType A[],int N)
{
  
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。

代码
//代码不太好理解,使用了3层循环
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)

代码
void Merge(ElementType A[],ElementType TmpArray[], int Lpos, int Rpos, int RightEnd)
{
    
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;开始交换过程

代码
ElementType Median3(ElementType A[],int Left, int Right)
{
    
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(1)
        {
        
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

对于是否已经排好序,或者随机文件,所花费的时间是一致的,即执行时间具有强迫性

选择排序应用在数据项比较大,键比较小的情况下,因为此时移动元素花费时间较多,而对于其他排序算法,元素移动频繁的多

代码
void sort(ElementType A[], int N) 

  
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]); 
  }    

 

原创粉丝点击