排序

排序就是將資料由小到大或由大到小排列,常見排序演算法有氣泡排序、選擇排序、插入排序、合併排序與快速排序等,其中以合併排序與快速排序的演算法效率比較好,但程式也較複雜。

(1)氣泡排序演算法

假設由小到大排序五個數字,55、78、89、45與65,從頭到尾不斷比較交換相鄰兩數,直到最大數到最後位置,縮小比較的範圍,再找出縮小範圍的最大數字放置於最後,直到剩下一個元素為止。

Ste1)排序第1個到第5個元素,從前往後每次比較交換相鄰兩數,最後前5個元素的最大數89就在最後面。

—Step2)排序第1個到第4個元素,從前往後每次比較交換相鄰兩數,最後前4個元素的最大數78就在最後面。

Step3)排序第1個到第3個元素,從前往後每次比較交換相鄰兩數,最後前3個元素的最大數65就在最後面。

Step4)排序第1個到第2個元素,從前往後每次比較交換相鄰兩數,最後前2個元素的最大數55就在最後面。

Step5)最後只剩最後一個元素就不用在比較了,到此完成氣泡排序。

氣泡排序演算法程式

氣泡排序演算法執行結果

氣泡排序演算法效率分析

假設要排序5個資料,程式中第11行到第19行為氣泡排序演算法,外層迴圈i數值由4到1,每次遞減1,外層每執行一次,則內層執行i次,內層迴圈的執行總次數影響整個程式的執行效率,累加內層迴圈的執行次數為「4+3+2+1」,假設要排序n個資料,累加內層迴圈的執行次數為「(n-1)+(n-2)+(n-3)+…+2+1」,總次數接近「n^2」,演算法效率為O(n^2)。

(2)插入排序演算法

假設由小到大排序五個數字,89、55、78、45與65,先考慮前兩個元素,將第2個元素插入到指定的位置,讓第1個到第2個元素由小到大排序好,再考慮前三個元素,將第3個元素插入到指定的位置,讓第1個到第3個元素由小到大排序好,依此類推,直到考慮前n個元素,將第n個元素插入到指定的位置,讓第1個到第n個元素由小到大排序好。

Ste1)先考慮前兩個元素,將第2個元素插入到指定的位置,讓第1個到第2個元素由小到大排序好。

Step2)先考慮前三個元素,將第3個元素插入到指定的位置,讓第1個到第3個元素由小到大排序好。

Step3)先考慮前四個元素,將第4個元素插入到指定的位置,讓第1個到第4個元素由小到大排序好。

Step4)先考慮前五個元素,將第5個元素插入到指定的位置,讓第1個到第5個元素由小到大排序好。

插入排序演算法程式

插入排序演算法執行結果

插入排序演算法效率分析

假設要排序4個資料,程式中第12行到第27行為插入排序演算法,外層迴圈i數值由1到4,每次遞增1,外層每執行一次內層最多執行i次,內層迴圈的執行總次數影響整個程式的執行效率,累加內層迴圈的執行次數為「1+2+3+4」。假設要排序n個資料,「1+2+3+…+(n-2)+(n-1)」,總次數接近「n^2」,演算法效率為O(n^2)。

(3)合併排序演算法

使用合併排序排序8個元素—(55,78,89,45,65,99,23,35)

Step1)先考慮將8個元素分成左右兩半各4個元素,左邊4個元素(55,78,89,45)優先處理。

Step2)考慮將左邊4個元素(55,78,89,45)再分成左右兩半各2個元素,左邊2個元素(55,78)優先處理。

Step3)考慮將左邊2個元素(55,78)分成左右兩半各1個元素(55)與(78),到此只剩一個元素左右兩邊都已完成排序,將左右兩邊合併成一個已排序陣列(55,78)。

Step4)考慮將右邊2個元素(89,45)分成左右兩半各1個元素(89)與(45),到此只剩一個元素左右兩邊都已完成排序,將左右兩邊合併成一個已排序陣列(45,89)。

Step5)考慮左右兩邊各2個元素(55,78)與(45,89)都已完成排序,將左右兩邊合併成一個已排序陣列(45,55,78,89)。

Step6)考慮右邊4個元素(65,99,23,35) 。

Step7)考慮將左邊4個元素(65,99,23,35)再分成左右兩半各2個元素,左邊2個元素(65,99)優先處理。

Step8)考慮將左邊2個元素(65,99)分成左右兩半各1個元素(65)與(99),到此只剩一個元素左右兩邊都已完成排序,將左右兩邊合併成一個已排序陣列(65,99)。

Step9)考慮將右邊2個元素(23,35)分成左右兩半各1個元素(23)與(35),到此只剩一個元素左右兩邊都已完成排序,將左右兩邊合併成一個已排序陣列(23,35)。

Step10)考慮左右兩邊各2個元素(65,99)與(23,35)都已完成排序,將左右兩邊合併成一個已排序陣列(23,35,65,99)。

Step11)考慮左右兩邊各4個元素(45,55,78,89)與(23,35,65,99)都已完成排序,將左右兩邊合併成一個已排序陣列(23,35,45,55,65,78,89,99),到此完成排序。

合併排序演算法程式

函式mergesort用於切割,函式merge用於合併兩個已排序陣列。

合併排序演算法執行結果

合併排序演算法效率分析

假設要排序n個資料,程式中第4行到第45行為合併排序演算法,第10行到第11行的mergesort函式每次將資料拆成一半,所以合併排序的mergesort的遞迴深度為O(log(n)),第12行的merge動作每一層都需要O(n),所以合併演算法效率為O(n*log(n)),相較於氣泡排序與插入排序演算法效能較佳,但排序過程須額外使用O(n)的暫存記憶體空間,所以記憶體空間的使用較氣泡排序與插入排序演算法來的多。

(4)快速排序演算法

使用快速排序由小到大排序8個元素(55,78,89,45,65,99,23,35)

Step1)將第1個元素(55)當成標兵,使用i由前往後找出比55大的元素,使用j由後往前找出比55小的元素。

Step2)若i小於j,則交換兩數。

Step3)將第1個元素(55)當成標兵,使用i由前往後找出比55大的元素,使用j由後往前找出比55小的元素。

Step4)若i小於j,則交換兩數。

Step5)將第1個元素(55)當成標兵,使用i由前往後找出比55大的元素,使用j由後往前找出比55小的元素。

Step6) 若i小於j,則交換兩數,否則將第1個元素(55) 與第j個元素互換。

Step7)元素(55)找到排序好時所在的位置,分成左邊(45,35,23)與右邊(65,99,89,78)分別執行快速排序。

Step8)縮小快速排序範圍到第1個到第3個元素(45,35,23),將第1個元素(45)當成標兵,使用i由前往後找出比45大的元素,使用j由後往前找出比45小的元素。

Step9) 若i小於j,則交換兩數,否則將第1個元素(45) 與第j個元素互換。

Step10)元素(45)找到排序好時所在的位置,分成左邊(23,35)與右邊沒有元素(),左邊繼續執行快速排序。

Step11)縮小快速排序範圍到第1個到第2個元素(23,35),將第1個元素(23)當成標兵,使用i由前往後找出比23大的元素,使用j由後往前找出比23小的元素,若i小於j,則交換兩數,否則將第1個元素(23) 與第j個元素互換。

Step12)元素(23)找到排序好時所在的位置,分成左邊沒有元素()與右邊(35) ,不須繼續排序。

Step13)縮小快速排序範圍到第5個到第8個元素(65,99,89,78),將第5個元素(65)當成標兵,使用i由前往後找出比65大的元素,使用j由後往前找出比65小的元素,若i小於j,則交換兩數,否則將第5個元素(65) 與第j個元素互換。

Step14)元素(65)找到排序好時所在的位置,分成左邊沒有元素()與右邊(99,89,78) ,右邊(99,89,78)使用快速排序進行排序。

Step15)縮小快速排序範圍到第6個到第8個元素(99,89,78),將第6個元素(99)當成標兵,使用i由前往後找出比99大的元素,使用j由後往前找出比99小的元素。

Step16) 若i小於j,則交換兩數,否則將第6個元素(99) 與第j個元素互換。

Step17)元素(99)找到排序好時所在的位置,分成左邊(78,89)與右邊沒有元素() ,左邊(78,89)使用快速排序進行排序。

Step18)縮小快速排序範圍到第6個到第7個元素(78,89),將第6個元素(78)當成標兵,使用i由前往後找出比78大的元素,使用j由後往前找出比78小的元素,若i小於j,則交換兩數,否則將第6個元素(78) 與第j個元素互換。

Step19)元素(78)找到排序好時所在的位置,分成左邊沒有元素() 與右邊(89), 不須繼續排序。

快速排序演算法程式

快速排序演算法執行結果

快速排序演算法效率分析

假設要排序n個資料,程式中第10行到第29行為快速排序演算法,第26行到第27行的quicksort函式每次將資料拆成一半或接近一半,所以快速排序的quicksort的遞迴深度接近O(log(n)),每一層都需要O(n),所以快速排序演算法平均效率為O(n*log(n)),相較於氣泡排序與插入排序演算法效能較佳,但最差情形就是每次切割都很不均勻,分成一邊只有1個數字,另一邊是n-1個數字(當數字已經由大到小或由小到大完成排序時),這時快速排序演算法效率為O(n^2),並不會比氣泡排序與插入排序演算法來的好。相較於合併排序演算法,最差情形合併排序比快速排序效率要好,快速排序平均而言需使用O(log(n))記憶體空間,因為遞迴深度所占記憶體空間,而合併排序須額外使用O(n)的記憶體空間。

(5)比較各排序演算法的效率

(6)使用STL進行排序

在(Standard Template Library)STL中提供了排序(sort)函式,須包含algorithm函式庫,排序演算法的效率為O(n*log(n)),不用辛苦撰寫合併排序或快速排序,直接呼叫使用。

STL中排序演算法的函式說明,如下表。

使用STL的排序程式

使用STL的排序程式執行結果

以下為氣泡排序與插入排序演算法教學影片