[answerer的算法課堂]簡單描述4種排序算法(C語言實現)


這是我第一次寫文章,想要記錄自己的學習生活,寫得不好請包涵or指導,本來想一口氣寫好多種,后來發現,寫太多的話反而可讀性不強,而且,我文筆,知識有限吶。慢慢來吧

目錄

名稱 冒泡排序 直接選擇排序 直接插入排序 希爾排序
時間復雜度 O(n^2) O(n^2) O(n^2) O(n^(1.3-2)

ps.沒有講到穩定性和空間復雜度。

冒泡排序

冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。
它重復地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從從Z到A)錯誤就把他們交換過來。走訪元素的工作是重復地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。

  • 時間復雜度大約為O(n^2),可進行一些優化
    這應該是c語言課程里頭第一次講到的排序算法,可以說得上是所有排序算法里頭最簡單的算法了。
  • 思想:按一定的順序,比如要求從大到小進行排序,那么第一位到最后一位(也可從最后一位到第一位)依次進行多次比較
  • 這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名“冒泡排序”。

代碼實現(未優化版本)

 1//這里按從小到大排序
2for(int i=0;i<n;i++)//比較n輪
3for(int j=0;j<n,j++)//n輪中每一輪比較n次
4{
5  if(a[j]>a[j+1])
6  {
7    temp=a[j];
8    a[j]=a[j+1];
9    a[j+1]=temp;
10  }
11

代碼實現(優化版本)

 1for(int i=0;i<n;i++)//比較n輪
2for(int j=0;j<n-i;j++)//每一輪比較n-j次
3{
4  if(a[j]>a[j+1])
5  {
6    temp=a[j];
7    a[j]=a[j+1];
8    a[j+1]=temp;
9  }
10}

為什么可以這樣優化呢?這就需要從機理來研究了,由於冒泡是每一次選出的是每一輪中的最大(小)的數,那么下輪開始,我們就不需要再將未排序的數再與已經排序的數進行比較了!
這里希望大家重視一下優化的版本,優化過后,時間復雜度會低些,這樣程序運行時間就會減少,雖然在冒泡這里體現並不明顯,但隨着學習的深入,你會逐漸發現,算法的優劣(時間復雜度&&空間復雜度),對一個程序而言很重要,特別是在信息學競賽中(才不會用冒泡這種低端算法呢)

02.直接選擇排序

直接選擇排序(Straight Select Sorting)
也是一種簡單的排序方法,它的基本思想是:第一次從R[0]R[n-1]中選取最小值,與R[0]交換,第二次從R[1]~R[n-1]中選取最小值,與R[1]交換,….,第i次從R[i-1]~R[n-1]中選取最小值,與R[i-1]交換,…..,第n-1次從R[n-2]R[n-1]中選取最小值,與R[n-2]交換,總共通過n-1次,得到一個按排序碼從小到大排列的有序序列。

  • ps.其實並不一定是從小到大,也可從大到小。 選擇排序的時間復雜度也是O(n^2)

  • 思想:也是和冒泡一樣,進行多輪比較,但不一樣的地方在於,經過每一次比較之后,每一輪會確定一個最小(大)的數對應的位置,最后才進行一次交換,相比之下,冒泡是一直在交換,事實上,冒泡和直接選擇排序一樣,比較低端,能不用盡量不用,尤其對長度較大的數組。

    代碼實現

 1content_copy
2int temp;
3for(int i=0;i<n-1;i++)
4{
5  int k=i;
6  for(int j=i+1;j<n;j++)
7    if(a[j]<a[k])
8    k=j;//每一輪中選出最小的數組元素對應的下標
9temp=a[k];
10a[k]=a[i];
11a[i]=temp;
12}

動態圖解

在這里插入圖片描述在這里插入圖片描述
03.直接插入排序

 

直接插入排序(Straight Insertion
Sort)是一種最簡單的排序方法,其基本操作是將一條記錄插入到已排好的有序表中,從而得到一個新的、記錄數量增1的有序表。

  • 直接插入排序的時間復雜度還是O(n^2)
  • 思想:每次選擇一個元素,將這個元素與數組中該元素之前所有的元素進行比較,然后將它插到合適的位置。

代碼實現

1    int i,j,temp;
2    for ( i = 1; i < n; i++) {
3         temp = a[i];//每一輪選出一個元素
4        for ( j = i; j > 0 && a[j - 1] > temp; j--) {
5            a[j] = a[j - 1];//與前面的元素比較大小,然后插進去,后面的元素退一位
6        }
7        a[j] = temp;
8    }

動態圖解

在這里插入圖片描述在這里插入圖片描述
04.希爾排序

 

希爾排序(Shell's Sort)是插入排序的一種又稱“縮小增量排序”(Diminishing Increment
Sort),是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。該方法因D.L.Shell於1959年提出而得名。
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

希爾排序是基於插入排序的以下兩點性質而提出改進方法的: 插入排序在對幾乎已經排好序的數據操作時,效率高,即可以達到線性排序的效率。
但插入排序一般來說是低效的,因為插入排序每次只能將數據移動一位。

  • 在某些極端情況下,希爾排序的時間復雜度會達到O(n^2)

  • 希爾排序的平均時間復雜度是O(n^(1.3—2))
    思想:直接插入排序要進行多次的比較交換,如果說,一個數組中大部分元素都處於有序的狀態下,那么就不需要進行多次的比較和交換了。那么就需要先對數組進行一定的處理。

  • 以下是希爾增量下的希爾排序,關於希爾排序的增量,有很多種選擇,例如Hibbard增量,這些增量有些是通過數學證明得到的,有些則是還沒有得到證明的,人們確信正確的經驗得出的。。個人感覺有點像孿生素數猜想那樣的吧,但證明難度應該沒有那么高。

代碼實現

 1  for (int gap= n/2; gap > 0; gap /= 2)//分組
2    {
3        for (int i = gap; i < n; i ++ )
4        {
5            int temp = a[i];
6            int j;          //這里基本上和插入排序差不多
7            for (j = i; j >= gap && a[j - gap] > temp; j -= gap)
8                a[j] = a[j - gap];
9            a[j] = temp;
10        }
11    }

圖解

  • ps.希爾排序的動圖我在網上找不到,只能用圖片代替了
    對於這樣的一個數組,進行分組,gap=n/2,然后每分好之后,再gap/=2,一直到gap=1,這個過程使得數組的整體有序性提高,從而使直接插入排序的工作量減少很多.
    在這里插入圖片描述在這里插入圖片描述
    對於其它增量實現的,這里不貼出來了,因為,我不會寫唉(逃

最后,這是我第一次寫博客,很多東西,如markdown語法什么的都不太會,我本來在編輯器上寫好的了,然后復制過來亂碼了,只能一段一段復制粘貼,希望大家包涵,如有錯誤,請指正,萬分感謝! 圖片來源於網絡,侵刪!


免責聲明!

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



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