注:轉載請標明原文出處鏈接:https://xiongyiming.blog.csdn.net/article/details/100574970
1 快速排序
快速排序(Quicksort)是對冒泡排序的一種改進。快速排序由C. A. R. Hoare在1960年提出。
快速排序的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
(以上均來自百度百科)
下面舉個例子來說明快速排序的思想。如下圖所示,給出無序的一組序列。
對於第一個元素4,快速排序的目的是將元素4放入合適的位置,使得4前面的元素都小於4,4後面的元素都大於4。
接下來,分別對4前面的元素和4後面的元素進行快速排序,使用遞歸即可完成操作。
而快速排序的核心(難點)就是如何將一個元素放入合適的位置。這裏這個核心過程稱之爲 partition (分割)
如下圖所示,使用序列中的第一個元素l作爲基準,基準用v表示,進行比較之後,這個基準v將遍歷整個序列。在比較的過程中,一部分元素小於v,另一部分元素大於v。 使用 j 表示分界點,e 表示當前訪問的元素。
v 表示基準,一般從第一個元素開始
l 表示第一個元素的索引
j 表示大於v 和 小於v 的分界點的索引
i 表示當前訪問的元素的索引
由下圖我們可知
區間 arr[l+1, j] < v
區間 arr[j+1, i-1] > v
下面將看一下當前索引i是如何放入合適的位置的
假設i索引位置e>v,那麼直接將e放入>v區間內
然後再討論下一個元素:
如下圖所示,假設 i 索引位置 e<v,那麼直接將e放入<v區間內,這時我們需要將e和j後面的一個元素交換位置即可,此時j需要往後移動一位。
接着i往後移動一位,在考察下一個元素,以此類推…
此時整個序列分爲3個部分,現在只需要將v和j索引位置元素進行交換即可。
後面使用遞歸即可完成所有的快速排序。
快速排序算法複雜度
2 實現簡單的快速排序
代碼示例
#include<iostream>
using namespace std;
template<typename T>
//對arr[l,r]部分進行partition操作//
//返回p, 使得arr[l,p-1]<arr[p] ; arr[p+1,r]>arr[p]//
int __partition(T arr[], int l, int r) {
T v = arr[l];//基準
// arr[l+1,j]<v ; arr[j+1,i]>v //
int j = l;
for (int i = l + 1; i <= r; i++) {
if (arr[i] < v) {
swap(arr[j + 1], arr[i]);
j++;
}
}
swap(arr[l], arr[j]);
return j;
}
template<typename T>
// 對arr[l,r]部分進行快速排序//
void __quickSort(T arr[], int l, int r) {
if (l >= r)
return;
int p = __partition(arr, l, r);
__quickSort(arr, l, p - 1);
__quickSort(arr, p + 1, r);
}
template<typename T>
//使用快速排序 讓數組中的數字從小到大排序 //
void quickSort(T arr[], int n)
{
__quickSort(arr, 0, n - 1);//遞歸
}
int main() {
int a[10] = { 10,9,8,7,6,5,4,3,2,1 };
quickSort(a, 10);
for (int i = 0; i < 10; i++)
cout << a[i] << " ";
cout << endl;
cin.get();
return 0;
}
運行結果
參考資料
[1] 算法與數據結構–綜合提升篇(c++版)
[2] https://github.com/liuyubobobo/Play-with-Algorithms
[3] https://cuijiahua.com/blog/2017/12/algorithm_4.html