快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。
算法步骤
-
从数列中挑出一个元素,称为 "基准"(pivot);
-
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
-
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
JavaScript
1 function quickSort(arr, left, right) { 2 var len = arr.length, 3 partitionIndex, 4 left = typeof left != 'number' ? 0 : left, 5 right = typeof right != 'number' ? len - 1 : right; 6 7 if (left < right) { 8 partitionIndex = partition(arr, left, right); 9 quickSort(arr, left, partitionIndex-1); 10 quickSort(arr, partitionIndex+1, right); 11 } 12 return arr; 13 } 14 15 function partition(arr, left ,right) { // 分区操作 16 var pivot = left, // 设定基准值(pivot) 17 index = pivot + 1; 18 for (var i = index; i <= right; i++) { 19 if (arr[i] < arr[pivot]) { 20 swap(arr, i, index); 21 index++; 22 } 23 } 24 swap(arr, pivot, index - 1); 25 return index-1; 26 } 27 28 function swap(arr, i, j) { 29 var temp = arr[i]; 30 arr[i] = arr[j]; 31 arr[j] = temp; 32 } 33 function partition2(arr, low, high) { 34 let pivot = arr[low]; 35 while (low < high) { 36 while (low < high && arr[high] > pivot) { 37 --high; 38 } 39 arr[low] = arr[high]; 40 while (low < high && arr[low] <= pivot) { 41 ++low; 42 } 43 arr[high] = arr[low]; 44 } 45 arr[low] = pivot; 46 return low; 47 } 48 49 function quickSort2(arr, low, high) { 50 if (low < high) { 51 let pivot = partition2(arr, low, high); 52 quickSort2(arr, low, pivot - 1); 53 quickSort2(arr, pivot + 1, high); 54 } 55 return arr; 56 }
Python
1 def quickSort(arr, left=None, right=None): 2 left = 0 if not isinstance(left,(int, float)) else left 3 right = len(arr)-1 if not isinstance(right,(int, float)) else right 4 if left < right: 5 partitionIndex = partition(arr, left, right) 6 quickSort(arr, left, partitionIndex-1) 7 quickSort(arr, partitionIndex+1, right) 8 return arr 9 10 def partition(arr, left, right): 11 pivot = left 12 index = pivot+1 13 i = index 14 while i <= right: 15 if arr[i] < arr[pivot]: 16 swap(arr, i, index) 17 index+=1 18 i+=1 19 swap(arr,pivot,index-1) 20 return index-1 21 22 def swap(arr, i, j): 23 arr[i], arr[j] = arr[j], arr[i]
C语言
1 void swap(int *x, int *y) { 2 int t = *x; 3 *x = *y; 4 *y = t; 5 } 6 7 void quick_sort_recursive(int arr[], int start, int end) { 8 if (start >= end) 9 return; 10 int mid = arr[end]; 11 int left = start, right = end - 1; 12 while (left < right) { 13 while (arr[left] < mid && left < right) 14 left++; 15 while (arr[right] >= mid && left < right) 16 right--; 17 swap(&arr[left], &arr[right]); 18 } 19 if (arr[left] >= arr[end]) 20 swap(&arr[left], &arr[end]); 21 else 22 left++; 23 if (left) 24 quick_sort_recursive(arr, start, left - 1); 25 quick_sort_recursive(arr, left + 1, end); 26 } 27 28 void quick_sort(int arr[], int len) { 29 quick_sort_recursive(arr, 0, len - 1); 30 }
C++
1 template <typename T> 2 void quick_sort_recursive(T arr[], int start, int end) { 3 if (start >= end) 4 return; 5 T mid = arr[end]; 6 int left = start, right = end - 1; 7 while (left < right) { //在整个范围内搜寻比枢纽元值小或大的元素,然后将左侧元素与右侧元素交换 8 while (arr[left] < mid && left < right) //试图在左侧找到一个比枢纽元更大的元素 9 left++; 10 while (arr[right] >= mid && left < right) //试图在右侧找到一个比枢纽元更小的元素 11 right--; 12 std::swap(arr[left], arr[right]); //交换元素 13 } 14 if (arr[left] >= arr[end]) 15 std::swap(arr[left], arr[end]); 16 else 17 left++; 18 quick_sort_recursive(arr, start, left - 1); 19 quick_sort_recursive(arr, left + 1, end); 20 } 21 template <typename T> //整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"(<)、"大於"(>)、"不小於"(>=)的運算子功能 22 void quick_sort(T arr[], int len) { 23 quick_sort_recursive(arr, 0, len - 1); 24 }