本文討論兩種著名且頗有用的排序算法:插入排序,快速排序。算法
插入排序的思想與打牌起牌相似:每次從牌堆裏拿一張牌,插入到已經排好序的牌中。數組
具體算法描述以下:bash
從第一個元素開始,該元素能夠認爲已經被排序less
取出下一個元素,從該元素開始,從後向前掃描表ide
若是前一個元素大於後一個元素,則交換兩個元素的位置測試
重複步驟 3,直到前一個元素不大於後一個元素ui
重複步驟 2~4spa
現有一組數組 A = [5, 6, 3, 1, 8, 7, 2, 4],共有八個記錄,排序過程以下:code
[5] 6 3 1 8 7 2 4 ↑ │ └───┘ [5, 6] 3 1 8 7 2 4 ↑ │ └────────┘ [3, 5, 6] 1 8 7 2 4 ↑ │ └──────────┘ [1, 3, 5, 6] 8 7 2 4 ↑ │ └──┘ [1, 3, 5, 6, 8] 7 2 4 ↑ │ └────┘ [1, 3, 5, 6, 7, 8] 2 4 ↑ │ └────────────────┘ [1, 2, 3, 5, 6, 7, 8] 4 ↑ │ └─────────────┘ [1, 2, 3, 4, 5, 6, 7, 8]
動態過程以下:
htm
代碼實現:
function isort(A, n, i, j, t) { for (i = 2; i <= n; i++) { # scan for (j = i; j > 1 && A[j-1] > A[j]; j--) { # swap 2 elements t = A[j-1] A[j-1] = A[j] A[j] = t } } } # 測試代碼 # 每一個數字佔一行 { A[NR] = $0 } END { isort(A, NR) for (i = 1; i <= NR; i++) { print A[i] } }
要排序的文件: $ cat isort.txt 5 6 3 1 8 7 2 4 排序後輸出: $ awk -f isort.awk isort.txt 1 2 3 4 5 6 7 8 輸入倒序的10個數字: $ seq 1 10 | tac | awk -f isort.awk 1 2 3 4 5 6 7 8 9 10
算法複雜度分析:
由於有兩層循環,因此算法複雜度爲
$$ O(n^2)$$
快速排序是圖靈獎得主 C. R. A. Hoare 於1960 年提出的一種劃分交換排序。它採用了一種分治的策略,一般稱其爲分治法(Divide and Conquer)。
分治法的基本思想是:將原問題分解爲若干個規模更小但結構與原問題類似的子問題。遞歸地解這些子問題,而後將這些子問題的解組合爲原問題的解。
步驟爲:
從數列中挑出一個元素,稱爲"基準"(pivot),
從新排序數列,全部元素比基準值小的擺放在基準前面,全部元素比基準值大的擺在基準的後面(相同的數能夠到任一邊)。在這個分區結束以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做。
遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。
圖解能夠看這裏,講得比較詳細。
代碼實現:
function swap(A, left, right, t) { t = A[left] A[left] = A[right] A[right] = t } function qsort(A, left, right, pivot, i, j) { if (left < right) { # select a pivot element pivot = left i = left j = right while (i < j) { # increment i till you get a number greater than the pivot element while (A[i] <= A[pivot] && i <= right) i++ # decrement j till you get a number less than the pivot element while (A[j] > A[pivot] && j >= left) j-- # if i < j swap the elements in locations i and j if (i < j) { swap(A, i, j) } } # when i >= j it means the j-th position is the correct position # of the pivot element, hence swap the pivot element with the # element in the j-th position swap(A, pivot, j) # Repeat quicksort for the two sub-arrays, one to the left of j # and one to the right of j qsort(A, left, j - 1) qsort(A, j + 1, right) } } # 測試代碼 { A[NR] = $0 } END { qsort(A, 1, NR) for (i = 1; i <= NR; i++) { print A[i] } }
和插入排序同樣,測試以下:
$ cat isort.txt 5 6 3 1 8 7 2 4 $ awk -f qsort.awk isort.txt 1 2 3 4 5 6 7 8 $ seq 1 10 | tac | awk -f qsort.awk 1 2 3 4 5 6 7 8 9 10
算法複雜度分析:平均複雜度爲 $$ O(nlogn) $$