1. 程式人生 > 實用技巧 >十大經典排序演算法(六、快速排序)

十大經典排序演算法(六、快速排序)

快速排序又是一種分而治之思想在排序演算法上的典型應用。本質上來看,快速排序應該算是在氣泡排序基礎上的遞迴分治法。

快速排序的最壞執行情況是 O(n²),比如說順序數列的快排。但它的平攤期望時間是 O(nlogn),且 O(nlogn) 記號中隱含的常數因子很小,比複雜度穩定等於 O(nlogn) 的歸併排序要小很多。所以,對絕大多數順序性較弱的隨機數列而言,快速排序總是優於歸併排序。

演算法步驟

  1. 從數列中挑出一個元素,稱為 "基準"(pivot);

  2. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽退出之後,該基準就處於數列的中間位置。這個稱為分割槽(partition)操作;

  3. 遞迴地(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 }