首先,假設有一個原始雜亂的數列,權值爲 : 3、1、3、6、4、0 。
首先在這個有6個值的數列,先選取一個基準數,這個基準數選法不唯一。
(我們這裏的基準數選擇數列的第一個就好,其他原理也相同,算法程序略不同)。
- 初始基準數: 3。
- L和R表示當前數列的第一個元素的位置,最後一個元素的位置。
- 圖中有兩個指針分別寫着左和右,初始時指向數列的 L-1 和 R+1的位置。
快排的基本做法:
第一趟-移動左指針:
移動左指針,當遇到第一個不小於基準數的數,那麼停止。到3成立,所以停止。
第一趟-移動右指針:
移動右指針,當遇到第一個不大於基準數的數,那麼停止。這裏,到0這已經成立。
第一趟交換:交換
然後此時:如果左指針在右指針的左邊,那麼交換 3 和 0。如果不在,會有另外的選擇。
第二趟-移動左右指針:
和第一趟是同理的,移動完畢後的結果如圖。
第二趟-是否交換?
此時發現右指針在左指針左側了,不符合了左指針在右指針的左邊的條件,所以不交換。
此時的操作:把這個大數列分成兩個小數列,從L到右指針所有的數作爲一個新數列A,從左指針到R的數作爲一個新的數列B。
新的數列A:
新數列B:
分治:A和B遵從同樣的規則。
注意!此時的基準數,是A和B各自的基準數了,新的基準數。A的基準數:0 B的基準數:6。
以數組A爲例A,流程:
移動指針,分別到數值爲0的位置----》並且此時符合交換條件,左指針在左,那麼交換0、0,所以沒什麼大變化。
繼續移動指針。右指針跑到了更左邊的位置。我們需要對A繼續分治。
根據指針位置,分出新的分組:A1、A2
此時A1就剩一個元素了,那麼我們就不管他了
A2還需要最後的移動,A2的基準值:1
左指針在更左邊,進行交換。得到最後的A2數列: 0 、1
A = A1 + A2 = { 0、0、1}
B = {3、4、6}
總數列 = A + B = {0、0、1、3、4、6}
總結:快排幾個重要的點
- 基準值的選取
- 移動指針
- 是否交換?
- 分治
下面給出快排模板:
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n;
int q[N];
void quick_sort(int q[], int l, int r)
{
if(l >= r ) return ;//如果到頭了就停止
int x = q[l], i = l -1, j = r + 1;
while(i<j)
{
do i++; while(q[i] < x);
do j--; while(q[j] > x);
if(i < j) swap(q[i],q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; ++i ) scanf("%d",&q[i]);
quick_sort(q, 0, n-1);
for (int i=0; i < n; ++ i) printf("%d ",q[i]);
}