快速排序是由东尼 · 霍尔所发展的一种排序算法。
快速排序是由东尼 · 霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高!它是处理大数据最快的排序算法之一了。虽然 Worst Case 的时间复杂度达到了 O(n²),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好,可是这是为什么呢,我也不知道。好在我的强迫症又犯了,查了 N 多资料终于在《算法艺术与信息学竞赛》上找到了满意的答案:
快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。
1. 算法步骤
- 从数列中挑出一个元素,称为 “基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
2. 动图演示

代码实现
JavaScript
function quickSort(arr, left, right) {var len = arr.length,partitionIndex,left = typeof left != 'number' ? 0 : left,right = typeof right != 'number' ? len - 1 : right;if (left < right) {partitionIndex = partition(arr, left, right);quickSort(arr, left, partitionIndex-1);quickSort(arr, partitionIndex+1, right);}return arr;}function partition(arr, left ,right) { // 分区操作var pivot = left, // 设定基准值(pivot)index = pivot + 1;for (var i = index; i <= right; i++) {if (arr[i] < arr[pivot]) {swap(arr, i, index);index++;}}swap(arr, pivot, index - 1);return index-1;}function swap(arr, i, j) {var temp = arr[i];arr[i] = arr[j];arr[j] = temp;}function partition2(arr, low, high) {let pivot = arr[low];while (low < high) {while (low < high && arr[high] > pivot) {--high;}arr[low] = arr[high];while (low < high && arr[low] <= pivot) {++low;}arr[high] = arr[low];}arr[low] = pivot;return low;}function quickSort2(arr, low, high) {if (low < high) {let pivot = partition2(arr, low, high);quickSort2(arr, low, pivot - 1);quickSort2(arr, pivot + 1, high);}return arr;}
Python
def quickSort(arr, left=None, right=None):left = 0 if not isinstance(left,(int, float)) else leftright = len(arr)-1 if not isinstance(right,(int, float)) else rightif left < right:partitionIndex = partition(arr, left, right)quickSort(arr, left, partitionIndex-1)quickSort(arr, partitionIndex+1, right)return arrdef partition(arr, left, right):pivot = leftindex = pivot+1i = indexwhile i <= right:if arr[i] < arr[pivot]:swap(arr, i, index)index+=1i+=1swap(arr,pivot,index-1)return index-1def swap(arr, i, j):arr[i], arr[j] = arr[j], arr[i]
Go
func quickSort(arr []int) []int {return _quickSort(arr, 0, len(arr)-1)}func _quickSort(arr []int, left, right int) []int {if left < right {partitionIndex := partition(arr, left, right)_quickSort(arr, left, partitionIndex-1)_quickSort(arr, partitionIndex+1, right)}return arr}func partition(arr []int, left, right int) int {pivot := leftindex := pivot + 1for i := index; i <= right; i++ {if arr[i] < arr[pivot] {swap(arr, i, index)index += 1}}swap(arr, pivot, index-1)return index - 1}func swap(arr []int, i, j int) {arr[i], arr[j] = arr[j], arr[i]}
C++
// 严蔚敏《数据结构》标准分割函数Paritition1(int A[], int low, int high) {int pivot = A[low];while (low < high) {while (low < high && A[high] >= pivot) {--high;}A[low] = A[high];while (low < high && A[low] <= pivot) {++low;}A[high] = A[low];}A[low] = pivot;return low;}void QuickSort(int A[], int low, int high) // 快排母函数{if (low < high) {int pivot = Paritition1(A, low, high);QuickSort(A, low, pivot - 1);QuickSort(A, pivot + 1, high);}}
Java
public class QuickSort implements IArraySort {@Overridepublic int[] sort(int[] sourceArray) throws Exception {// 对 arr 进行拷贝,不改变参数内容int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);return quickSort(arr, 0, arr.length - 1);}private int[] quickSort(int[] arr, int left, int right) {if (left < right) {int partitionIndex = partition(arr, left, right);quickSort(arr, left, partitionIndex - 1);quickSort(arr, partitionIndex + 1, right);}return arr;}private int partition(int[] arr, int left, int right) {// 设定基准值(pivot)int pivot = left;int index = pivot + 1;for (int i = index; i <= right; i++) {if (arr[i] < arr[pivot]) {swap(arr, i, index);index++;}}swap(arr, pivot, index - 1);return index - 1;}private void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}
PHP
function quickSort(arr) <= 1)return $arr;$middle = $arr[0];$leftArray = array();$rightArray = array();for ($i = 1; arr); arr[$i] > $middle)$rightArray[] = i];else$leftArray[] = i];}leftArray);$leftArray[] = $middle;rightArray);return array_merge($leftArray, $rightArray);}
C
typedef struct _Range {int start, end;} Range;Range new_Range(int s, int e) {Range r;r.start = s;r.end = e;return r;}void swap(int x, int y) {int t = *x;x = y;*y = t;}void quick_sort(int arr[], const int len) {if (len <= 0)return; // 避免 len 等於負值時引發段錯誤(Segment Fault)// r[] 模擬列表, p 為數量, r[p++] 為 push,r[--p] 為 pop 且取得元素Range r[len];int p = 0;r[p++] = new_Range(0, len - 1);while (p) {Range range = r[--p];if (range.start >= range.end)continue;int mid = arr[(range.start + range.end) / 2]; // 選取中間點為基準點int left = range.start, right = range.end;do {while (arr[left] < mid) left; // 檢測基準點左側是否符合要求while (arr[right] > mid) --right; // 檢測基準點右側是否符合要求if (left <= right) {swap(&arr[left], &arr[right]);left;right--; // 移動指針以繼續}} while (left <= right);if (range.start < right) r[p++] = new_Range(range.start, right);if (range.end > left) r[p++] = new_Range(left, range.end);}}
递归法
void swap(int x, int y) {int t = *x;x = y;*y = t;}void quick_sort_recursive(int arr[], int start, int end) {if (start >= end)return;int mid = arr[end];int left = start, right = end - 1;while (left < right) {while (arr[left] < mid && left < right)left++;while (arr[right] >= mid && left < right)right--;swap(&arr[left], &arr[right]);}if (arr[left] >= arr[end])swap(&arr[left], &arr[end]);elseleft++;if (left)quick_sort_recursive(arr, start, left - 1);quick_sort_recursive(arr, left + 1, end);}void quick_sort(int arr[], int len) {quick_sort_recursive(arr, 0, len - 1);}
C++
函数法
sort(a,a + n);// 排序a[0]-a[n-1]的所有数.
迭代法
// 参考:http://www.dutor.net/index.php/2011/04/recursive-iterative-quick-sort/struct Range {int start, end;Range(int s = 0, int e = 0) {start = s, end = e;}};template // 整數或浮點數皆可使用, 若要使用物件 (class) 時必須設定 "小於"(<)、"大於"(>)、"不小於"(>=)的運算子功能void quick_sort(T arr[], const int len) {if (len <= 0)return; // 避免 len 等於負值時宣告堆疊陣列當機// r[] 模擬堆疊, p 為數量, r[p++] 為 push,r[--p] 為 pop 且取得元素Range r[len];int p = 0;r[p++] = Range(0, len - 1);while (p) {Range range = r[--p];if (range.start >= range.end)continue;T mid = arr[range.end];int left = range.start, right = range.end - 1;while (left < right) {while (arr[left] < mid && left < right) left++;while (arr[right] >= mid && left < right) right--;std::swap(arr[left], arr[right]);}if (arr[left] >= arr[range.end])std::swap(arr[left], arr[range.end]);elseleft++;r[p++] = Range(range.start, left - 1);r[p++] = Range(left + 1, range.end);}}
递归法
templatevoid quick_sort_recursive(T arr[], int start, int end) {if (start >= end)return;T mid = arr[end];int left = start, right = end - 1;while (left < right) { // 在整个范围内搜寻比枢纽元值小或大的元素,然后将左侧元素与右侧元素交换while (arr[left] < mid && left < right) // 试图在左侧找到一个比枢纽元更大的元素left++;while (arr[right] >= mid && left < right) // 试图在右侧找到一个比枢纽元更小的元素right--;std::swap(arr[left], arr[right]); // 交换元素}if (arr[left] >= arr[end])std::swap(arr[left], arr[end]);elseleft++;quick_sort_recursive(arr, start, left - 1);quick_sort_recursive(arr, left + 1, end);}template // 整數或浮點數皆可使用, 若要使用物件 (class) 時必須設定 "小於"(<)、"大於"(>)、"不小於"(>=)的運算子功能void quick_sort(T arr[], int len) {quick_sort_recursive(arr, 0, len - 1);}
参考地址:
https://github.com/hustcc/JS-Sorting-Algorithm/blob/master/6.quickSort.md
