排序
排序就是將資料由小到大或由大到小排列,常見排序演算法有氣泡排序、選擇排序、插入排序、合併排序與快速排序等,其中以合併排序與快速排序的演算法效率比較好,但程式也較複雜。
(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的排序程式執行結果
以下為氣泡排序與插入排序演算法教學影片