演算法之常見排序演算法 氣泡排序 歸併排序 快速排序

2022-03-17 18:03:21 字數 2574 閱讀 4794

引言

對於程式設計中琳琅滿目的演算法,本人向來是不善此道也不精於此的,而說起排序演算法,也只是會氣泡排序。還記得當初剛做開發工作面試第一家公司時,面試官便讓手寫氣泡排序(入職之後才知道,這面試官就是乙個氣泡排序"病態"愛好者,逢面試必考氣泡排序-__-)。後來看吳軍的一些文章,提到提高效率的關鍵就是少做事情不做無用功,便對這不起眼的排序演算法有了興趣。剛好今天週末有閒,遂研究一二,與各位道友共享。

氣泡排序時間之所以效率低,就是因為將所有數都一視同仁不做區分挨個比較,這是最普通的做事方法,所以效率也是最普通的,時間複雜度為n的平方;而歸併排序效率高,則是採用了分治的思想,將乙個整體分成多個小份,每個小份排好序之後再互相比較,這樣就比冒泡快了不少,時間複雜度為nlogn;快速排序的平均時間複雜度也是nlogn,但是實際的耗費時間會比歸併排序快兩三倍(當然快排在最壞的情況下時間複雜度還是n的平方,比歸併排序大),它的平均執行時間能比歸併更快一些是因為它每次分組時不是隨機分組而是相對有序的分組,即先從陣列中隨機取乙個數作為基數,然後將資料移動,使得基數一邊的數都比它小,另一邊的數都比它大,再在兩邊各取乙個基數進行相同的移動、分組操作,遞迴下去,這樣每個細分的小組都在整體的大陣列中有個位置,合併時直接按從小到大將各個分組合併起來即可,所以一般情況下會比歸併快一些。

了解了思想之後,再用**實現相對就會容易很多。此處就再借用乙個直觀一點的例子來說明歸併與快排二者的區別。假設有1000個學生,想對他們的成績進行排序。方法1借用歸併排序的思想,具體這樣做:將這1000個人分成10組,將每組的100人進行排序,排完之後再在各組之間從小到大依次進行比較,最後得到整個的成績排名。方法2借用快速排序的思想,具體需這樣做:將1000個人也是分成10組,但是是按分數段分,0-10分的放在一組,10-20分的放在一組,20-30分的放在一組,依次類推,分完組之後再在各個小組中進行排序,而當你合併各個小組時,只需將其按從小到大的順序直接合併就行,無需跟方法1一樣將各小組中的資料取出來跟其他小組中的資料挨個比較。看到這裡,想必各位道友對快排比歸併排序還要快一些的原因就有了解了。

演算法可以理解成做事的技巧或者說套路,我們對其的理解可以不止於程式設計,完全可以推廣出去。比如歸併的分治法,將乙個大事情拆解成多個小事件,解決起來就會方便很多。閒話扯了一大堆,下面就將我自己寫的排序給大家貼出來,附帶上注釋講解,如果有之前不了解的道友,相信看完之後便會念頭通透,原地飛公升 >_<。

正文

歸併排序

//

歸併排序

public

static

void mergesort (int

arr)

private

static

void mergesort(int arr, int left, int right, int

temp)

}private

static

void merge(int arr, int left, int mid, int right, int

temp)

else

}while (i <= mid)

while (j <= right)

t = 0;

//此時temp中已經是arr陣列中下標從left到right之間排好序的資料了,因為temp每次都是從0開始賦值,所以需將排好序的數放回arr的對應位置

while (left <=right)

}

快速排序

1

//快速排序

2public

static

void quicksort (int arr, int left, int

right)

7if (right <=left)

10if (right - left == 1 && arr[left] <=arr[right])

13//

取第乙個數為基準數(基數取哪個都行,此處是為了方便)

14int index =arr[left];

15int i = left + 1; //

左指標16

int j = right; //

右指標17

while (i < j && i < right && j > left) //

找到從右邊數第乙個比index小的數

19while (arr[i] < index && i < right) //

找到從左邊數第乙個比index大的數

20if (i < j) 25}

26//

執行完上面迴圈後,arr已經是左邊比index小,右邊比index大的陣列了,只是基準數仍在基準位置left處,需放到它應該在的位置

27if (j != left && arr[j] !=arr[left])

33 quicksort(arr, left, j-1); //

將基準數左邊排序

34 quicksort(arr, j+1, right); //

將基準數右邊排序

35 }

這次的排序演算法就到這裡,如果有不妥之處,還請道友指正。後面如果遇到有意思的演算法題,也會跟道友們分享,下期見!

常見排序演算法之氣泡排序

1 首先,從第乙個元素開始,比較該元素與該元素相鄰的下乙個元素的大小 即第乙個元素與第二個元素的大小 如果該元素比較大則交換位置,否則不交換位置。2 按照1的步驟不斷重複的比較下一元素與其相鄰元素之間的大小,直到第n 1個元素,第一趟比較結束。例如 接下去是第二個元素,重複 1 的步驟,比較其與其相...

常見排序演算法之氣泡排序

氣泡排序 bubble sort 是一種較簡單的排序演算法。它重複地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果他們的順序 如從小到大 首字母從a到z 錯誤就把他們交換過來。比較相鄰的元素。如果第乙個比第二個大 公升序 就交換他們兩個。對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對...

常見演算法之氣泡排序

氣泡排序由於其簡單,通常是我們學習各類程式語言首先選擇學習的乙個排序演算法。1 public class bubblesort 5 建立氣泡排序類的物件 6 bubblesort sorter new bubblesort 7 呼叫排序方法將陣列排序 8sorter.sort array 9 10 ...