面試必備:排序算法匯總(c++實現)


排序算法主要考點: 7種排序

              冒泡排序、選擇排序、插入排序、shell排序、堆排序、快速排序、歸並排序

以上排序算法是面試官經常會問到的算法,至於其他排序比如基數排序等等,這里不列舉。

以下算法通過c++實現,開發工具Visual Studio 2012:代碼下載


 

一、排序 :將雜亂無章的數據元素,通過一定的方法按關鍵字順序排列的過程

  排序分為內部排序、外部排序;

  若整個排序過程不需要訪問外存便能完成,則稱此類排序問題為內部排序

  反之,若參加排序的記錄數量很大,整個序列的排序過程不可能在內存中完成,則稱此類排序問題為外部排序

   假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,

   即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,則稱這種排序算法是穩定的;

     否則稱為不穩定的。

  1. 冒泡排序

    時間復雜度:最好的情況:表本身就是有序的,n-1次比較,時間復雜度為O(n);最壞的情況:表是逆序的,此時需要比較 1+2+3+...(n-1) = (n(n-1))/2,時間復雜度為O(n2)

    優點:簡單、穩定

    缺點:慢,每次只能移動相鄰兩個數據,效率低

    c++實現:

 1             //冒泡排序
 2             void Bubble_Sort(int *list,int count)
 3             {
 4                 int flag = true;
 5                 int i = 0,j = 0;
 6                 for(i=0;i<=count&&flag;i++)
 7                 {
 8                     flag = false;
 9                     for(j=count -1;j>=i;j--)
10                     {
11                         if(list[j]<list[j-1])
12                         {
13                             swap(list[j],list[j-1]);
14                             flag = true;
15                         }
16                     }
17                 }
18 
19             }

  2. 選擇排序

    時間復雜度:O(n2)  :無論最好、最壞情況,都需要比較 (n(n-1))/2次,最好的情況交換次數為0,最壞的情況交換次數為n-1

    優點:交換移動數據次數相當少,性能上略優於冒泡排序

    缺點:效率低

    c++實現:

 1         //選擇排序
 2         void Select_Sort(int *list,int count)
 3         {
 4             int min,i,j;
 5             for(i=0;i<count;i++)
 6             {
 7                 min = i;
 8                 for(j=i+1;j<count;j++)
 9                 {
10                     if(list[i]>list[j])
11                     {
12                         min = j;
13                     }
14                 }
15                 if(min!=i)
16                 {
17                     swap(list[i],list[min]);
18                 }
19 
20             }
21         }

  3. 插入排序

    時間復雜度:最好情況:表本身就是有序的,比較次數是n-1次,沒有移動記錄,時間復雜度為O(n);最壞情況:表本身是無序的,比較次數是2+3+4+...+n = (n+2)(n-1)/2,移動次數也達到最大

    值為 (n+4)(n-1)/2次,所以時間復雜度為O(n2);如果根據概論相同的原則,平均比較和移動次數約為n2/4;

    優點:比選擇,冒泡排序性能要好一些

    缺點:效率較低

    c++實現:

 1         //插入排序
 2         void Insert_Sort(int *list,int count)
 3         {
 4             int temp;/*此處充當哨兵,不在list數組里面單獨占一個單位*/
 5             int i,j;
 6             for(i=1;i<count;i++)
 7             {
 8                 if(list[i]<list[i-1])
 9                 {
10                     temp = list[i];
11                     for(j=i-1;list[j]>temp&&j>=0;j--)
12                     {
13                         list[j+1] = list[j];
14                     }
15                     list[j+1] = temp;
16                 }
17             }
18         }    

  4. shell排序

    時間復雜度:O(n3/2)

    優點:跳躍式移動,使得排序效率提高

    缺點:不是一種穩定的排序算法

    c++實現:

 1        //shell排序
 2         void Shell_Sort(int *list,int count)
 3         {
 4             int i,j;
 5             int temp;
 6             int increment = count;
 7             do
 8             {
 9                 increment = increment/3+1;
10                 for(i = increment;i<count;i++)
11                 {
12                     if(list[i]<list[i-increment])
13                     {
14                         temp = list[i];
15                         for(j=i-increment;j>=0&&list[j]>temp;j-=increment)
16                         {
17                             list[j+increment] = list[j];
18                         }
19                         list[j+increment] = temp;
20                         
21                     }
22                     
23                 }
24 
25             }while(increment>1);
26         }

  5. 堆排序

    時間復雜度:O(nlogn)

    優點:性能上遠遠超過冒泡、選擇、插入的時間復雜度O(n2)

    缺點:不是一種穩定的排序算法

    c++實現:

 

//調整為一個堆
void Heap_Adjust(int *list,int s,int m)
{
    int temp = list[s];
    for(int j=2*s+1;j<=m;j = 2*j+1)
    {
        if(list[j]<list[j+1]&&j<m)
        {
            j++;
        }
        if(temp>list[j])
            break;
        list[s] = list[j];
        s = j;
    }
    list[s] = temp;
}

//堆排序
void Heap_Sort(int *list,int len)
{
    //創建一個大頂堆
    for(int s = len/2-1;s>=0;s--)
    {
        Heap_Adjust(list,s,len-1);
    }

    //排序
    for(int i = len-1;i >= 1;i--)
    {
        swap(list[0],list[i]);
        Heap_Adjust(list,0,i-1);
    }

}

 

 

 

    6. 歸並排序

    時間復雜度:O(nlogn)

    優點:效率高、穩定

    缺點:占用內存較多

    c++實現:

 

//將有個有序數組排序
void Merge(int *list,int start,int mid,int end)
{
    const int len1 = mid -start +1;
    const int len2 = end -mid;
    const int len = end - start +1;
    int i,j,k;


    int * front = (int *)malloc(sizeof(int)*len1);
    int * back = (int *)malloc(sizeof(int)*len2);

    for(i=0;i<len1;i++)
        front[i] = list[start+i];
    for(j=0;j<len2;j++)
        back[j] = list[mid+j+1];

    for(i=0,j=0,k=start;i<len1&&j<len2&&k<end;k++)
    {
        if(front[i]<back[j])
        {
            list[k] = front[i];
            i++;
        }else
        {
            list[k] = back[j];
            j++;
        }
    }
    while(i<len1)
    {
        list[k++] = front[i++];
    }
    while(j<len2)
    {
        list[k++] = back[j++];
    }

}

 

      //歸並排序
        void Merge_Sort(int *list,int count)
        {
            MSort(list,0,count-1);
        }
        //歸並排序
        void MSort(int *list,int start,int end)
        {
            
            if(start<end)
            {
                int mid = (start+end)/2;
                MSort(list,0,mid);
                MSort(list,mid+1,end);
                Merge(list,start,mid,end);
            }

        }        

  7. 快速排序

    時間復雜度:O(nlogn)(平均情況)

    優點:目前來說最快的排序算法,現在的快排算法大多是快速排序算法的改進算法

    缺點:跳躍式,不穩定

    c++實現:

        //快速排序
        void Quick_Sort(int *list,int count)
        {
            Qsort(list,0,count-1);
        }
       //快速排序
        void Qsort(int *list,int low,int high)
        {
            int pivot;
            if(low<high)
            {
                pivot =Partition(list,low,high);
                Qsort(list,low,pivot-1);
                Qsort(list,pivot+1,high);
            }

        }
     int Partition(int *list,int low,int high)
        {
            int pivotKey;
            pivotKey = list[low];
            while(low<high)
            {
                while(low<high&&list[high]>=pivotKey)
                {
                    high--;
                }
                swap(list[low],list[high]);
                while(low<high&&list[low]<=pivotKey)
                {
                    low++;
                }
                swap(list[low],list[high]);
            }
            return low;
        }

附:

     void swap(int& a,int& b)
        {
            int temp = a;
            a = b;
            b = temp;
        }

 

總結:排序:  插入排序類: 插入排序,希爾排序

        選擇排序類: 選擇排序,堆排序

        交換排序類: 冒泡排序,快速排序

        歸並排序類: 歸並排序

 

 

              


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM