[answerer的演算法課堂]簡單描述4種排序演算法(C語言實現)
[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語言課程裡頭第一次講到的排序演算法,可以說得上是所有排序演算法裡頭最簡單的演算法了。
思想:按一定的順序,比如要求從大到小進行排序,那麼第一位到最後一位(也可從最後一位到第一位)依次進行多次比較
這個演算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名“氣泡排序”。
for(int i=0;i<n;i++)//比較n輪 for(int j=0;j<n,j++)//n輪中每一輪比較n次 { if(a[j]>a[j+1]) { temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } }
for(int i=0;i<n;i++)//比較n輪 for(int j=0;j<n-i;j++)//每一輪比較n-j次 { if(a[j]>a[j+1]) { temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } }
忽略我的排版,確實很糟糕,我會努力去改的
為什麼可以這樣優化呢?這就需要從機理來研究了,由於冒泡是每一次選出的是每一輪中的最大(小)的數,那麼下輪開始,我們就不需要再將未排序的數再與已經排序的數進行比較了!
這裡希望大家重視一下優化的版本,優化過後,時間複雜度會低些,這樣程式執行時間就會減少,雖然在冒泡這裡體現並不明顯,但隨著學習的深入,你會逐漸發現,演算法的優劣(時間複雜度&&空間複雜度),對一個程式而言很重要,特別是在資訊學競賽中(才不會用冒泡這種低端演算法呢)
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)
思想:也是和冒泡一樣,進行多輪比較,但不一樣的地方在於,經過每一次比較之後,每一輪會確定一個最小(大)的數對應的位置,最後才進行一次交換,相比之下,冒泡是一直在交換,事實上,冒泡和直接選擇排序一樣,比較低端,能不用盡量不用,尤其對長度較大的陣列。
int temp; for(int i=0;i<n-1;i++) { int k=i; for(int j=i+1;j<n;j++) if(a[j]<a[k]) k=j;//每一輪中選出最小的陣列元素對應的下標 temp=a[k]; a[k]=a[i]; a[i]=temp; }
03.直接插入排序
直接插入排序(Straight Insertion Sort)是一種最簡單的排序方法,其基本操作是將一條記錄插入到已排好的有序表中,從而得到一個新的、記錄數量增1的有序表。
直接插入排序的時間複雜度還是O(n^2)
思想:每次選擇一個元素,將這個元素與陣列中該元素之前所有的元素進行比較,然後將它插到合適的位置。
int i,j,temp; for ( i = 1; i < n; i++) { temp = a[i];//每一輪選出一個元素 for ( j = i; j > 0 && a[j - 1] > temp; j--) { a[j] = a[j - 1];//與前面的元素比較大小,然後插進去,後面的元素退一位 } a[j] = temp; }
04.希爾排序
希爾排序(Shell's Sort)是插入排序的一種又稱“縮小增量排序”(Diminishing Increment Sort),是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。該方法因D.L.Shell於1959年提出而得名。
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。希爾排序是基於插入排序的以下兩點性質而提出改進方法的:
插入排序在對幾乎已經排好序的資料操作時,效率高,即可以達到線性排序的效率。
但插入排序一般來說是低效的,因為插入排序每次只能將資料移動一位。
在某些極端情況下,希爾排序的時間複雜度會達到O(n^2)
希爾排序的平均時間複雜度是O(n^(1.3—2))
思想:直接插入排序要進行多次的比較交換,如果說,一個數組中大部分元素都處於有序的狀態下,那麼就不需要進行多次的交換了。那麼就需要先對陣列進行一定的處理。
以下是希爾增量下的希爾排序,關於希爾排序的增量,有很多種選擇,例如Hibbard增量,這些增量有些是通過數學證明得到的,有些則是還沒有得到證明的,人們確信正確的經驗得出的。。個人感覺有點像孿生素數猜想那樣的吧,但證明難度應該沒有那麼高。
for (int gap= n/2; gap > 0; gap /= 2)//分組 { for (int i = gap; i < n; i ++ ) { int temp = a[i]; int j; //這裡基本上和插入排序差不多 for (j = i; j >= gap && a[j - gap] > temp; j -= gap) a[j] = a[j - gap]; a[j] = temp; } }
ps.希爾排序的動圖我在網上找不到,只能用圖片代替了 對於這樣的一個數組,進行分組,gap=n/2,然後每分好之後,再gap/=2,一直到gap=1,這個過程使得陣列的整體有序性提高,從而使直接插入排序的工作量減少很多.
對於其它增量實現的,這裡不貼出來了,因為,我不會寫唉(逃