快速排序是一種不僅爲了教學目的而且實際應用廣泛的快速排序算法。平均來說,這個算法的複雜度是O(n log n),所以十分適合用來對大數據量進行排序。當你理解後,會覺得快速排序算法的思想十分簡單,甚至你可以像寫冒泡排序算法那樣很快的寫出快速排序的算法。
算法
快速排序採用了分治法的策略,下面描述了遞歸的步驟:
- 選擇一箇中間值。我們選擇一箇中間元素作爲中間值,這個中間元素可以是在待排序元素範圍內的任何值,甚至即使它不存在於待排序數組中也可以。
- 分組. 我們使用以下方法來對元素進行重新排序:將所有小於中間值的數據排序到數組的左半邊部分,所有大於中間值的數據放在數組的右半邊部分。等於中間值的數據可以任意的放在數組左邊或者右邊。注意,這個待排序數組可能被分隔爲兩個不等長的部分。
- 對分隔後的兩個數組進行排序。 用遞歸的方法對左右兩個部分分別使用快速排序算法。(快速排序還有非遞歸的方法,更加高效)
分組算法詳解
有兩個索引 i 和 j ,在分組算法最初 i 指向待排序數組的第一個元素而 j 則指向數組的最後一個元素。向後移動索引 i ,並將其指向的元素與中間值比較直到出現大於中間值的元素,這時再向前移動索引 j ,並將其指向元素與中間值比較,直到出現小於中間值的元素。這時如果 i < j,就將 i 指向的元素與 j 指向的元素進行對調,並將 i 移動到下一個元素的位置,j 移動到前一個元素的位置。 最後當i = j 時整個分組過程結束。
分組後,所有在第 i 個元素之前的值都小於等於中間值,而在 第 j 個元素後的所有值都大於等於中間值。
示例. 對{1, 12, 5, 26, 7, 14, 3, 7, 2} 進行快速排序
注意,爲了不讓示例過長,我們在這裏只是演示了遞歸的第一層的步驟,但是,實際 {1, 2, 5, 7, 3} and {14, 7, 26, 12} 會繼續進行遞歸排序。
爲什麼這種排序方法可行?
在分組這一步,我們將待排序數組分隔爲了兩個部分,這樣使左邊部分中所有元素a都小於等於右邊部分中的元素b,並且a 和 b 滿足 a ≤ pivot ≤ b .在完成遞歸調用後左右兩個部分的數組便都是有序排列的,考慮上邊說的滿足條件即可得出整個數組被排序的結論。
複雜度分析
平均地,快速排序算法的複雜度爲 O(n log n ) ,但是證明過程就不在這裏寫了。在最壞的情況下,快速排序執行O(n2)次,但是應用在大多數實際的數據中都表現良好,並且效率一般優於其他複雜度爲O(n log n) 的排序算法。
代碼片段
分組算法自身是很重要的,因此它可以提出作爲單獨的功能點。C++中包含固定的函數用來執行快速排序,但是java中包含兩個單獨的函數分別用來分組和排序。
JAVA
int partition(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
return i;
}
void quickSort(int arr[], int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1)
quickSort(arr, left, index - 1);
if (index < right)
quickSort(arr, index, right);
}
C++
void quickSort(int arr[], int left, int right) {
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
/* partition */
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
/* recursion */
if (left < j)
quickSort(arr, left, j);
if (i < right)
quickSort(arr, i, right);
}
Download link:
full quicksort package. 完整的代碼包下載