快速排序(Quick Sort) 挖坑填數法

2021-09-22 16:44:29 字數 3633 閱讀 5451

前面的博文講了氣泡排序、選擇排序、插入排序,今天我們談談快速排序!

快速排序的基本思想是:

1.先從序列中取出乙個數作為基準數。

2.分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。(分割槽的方式多樣,但一定要保證基準數左邊的數比它大(小),右邊的數比它小(大))

3.再對左右區間重複第一步、第二步,直到各區間只有乙個數。

快速排序的關鍵點(一定要理解):

1、 如何確定基準數?

一般情況下,選取當前陣列的第乙個數。

2、如何找到比基準數大(小)的數?(假設從小到大排序)

先從後往前找比基準數小的數;再從前往後找比基準數大的數;(注意次序不能顛倒)

3、找到的數如何放,才能實現比基準數大和小的數分別在基準數的兩邊?

採用挖坑填數法,具體過程如下:

①每次把基準數所在的位置看成乙個坑位a,定義兩個變數:left和right分別指向陣列的左端和右端。

②從後往前掃瞄陣列,當發現有值小於基準值時,將當前值填到坑位a中,同時當前值所在的位置看成新的坑位b;

③從前往後掃瞄陣列,當發現有值大於基準值,將當前值填到坑位b中,同時當前值所在的位置看成坑位a;

不停的重複第②~③步的操作,直到left>=right相遇,表示這一輪的內迴圈比較結束,

將基準值填到left(right)指向的坑位中,就完成了本輪的排序;

4、以基準值為分割點,將當前的陣列為兩個小的陣列,依次從第1步遞迴迴圈操作;

為了便於學者深入理解,舉例:[14, 18, 11, 30, 28,4 ]進行從小到大的排序

整個過程中涉及三個引數:當前基準數num,left,right; (left,right分別代表當前陣列的左右端位置)

第1輪:基準數num=14

①交換前的資料:[14, 18, 11, 30, 28,4 ] 當前坑位[0],left=0,right=5

②從right=5的位置開始從後往前,找到比14小的第乙個數4,此時的left=0,right=5,滿足leftright,內迴圈結束,將基準值14放在最後乙個坑位[2]的位置。

交換後的資料:[4,11,14,30,28,18]

第1輪結束。(14左邊的數都比14小,14右邊的數都比14大)

以基準數14為分割點,用劃分。表示如下:[,14,],

(一)先對14左邊的子陣列進行遞迴快速排序:

第2輪:基準數num=4(14左邊的子陣列)

①交換前的資料:[,14,]當前坑位[0], left=0,right=1(因為當前陣列為);

②從right=1的位置從後往前,直到right=0也沒有找到比4小的數,此時的left=0,right=0,由於left等於right,內迴圈結束,將基準值4放在最後乙個坑位[0]的位置。

③交換後的資料為:[4,11,14,18,28,30]

第2輪結束。(4左邊的數都比4小,4右邊的數都比4大)

以基準數4為分割點,用劃分。表示如下:[4,,14,30,28,18],

第3輪:基準數num=11(4右邊的子陣列)

①交換前的資料:[4,,14,30,28,18]當前坑位[1], left=1,right=1(因為當前陣列為);

由於left等於right,內迴圈結束,將基準值11放在最後乙個坑位[1]的位置。

③交換後的資料為:[4,11,14,18,28,30]

第第3輪結束。(11左邊的數都比11小,11右邊的數都比11大)

(二)先對14右邊的子陣列進行遞迴快速排序:

第4輪,基準值num=30(14右邊的子陣列)

①交換前的資料:[4,11,14,] 當前坑位[3],left=3,right=5(因為當前陣列為)

②從right=5的位置開始從後往前,找到比30小的第乙個數18,此時的left=3,right=5,滿足left第4輪結束。

以基準數30為分割點,用劃分。表示如下:[4,11,14,,30]

第5輪:基準值num=18(30左邊的子陣列)

①交換前的資料:[4,11,14,,30]當前坑位[3], left=3,right=4(因為當前陣列為)

②從right=4的位置開始從後往前,直到right=3都沒有找到比18小的數,此時的left=3,right=3,由於left等於right,內迴圈結束,將基準值18放在最後乙個坑位[3]的位置。

第5輪結束

以基準數18為分割點,用劃分。表示如下:[4,11,14,18,,30]

第6輪:基準值num=28(18右邊的子陣列)

①交換前的資料:[4,11,14,18,,30]當前坑位[4], left=4,right=4,由於left等於right,內迴圈結束, 將基準值28放在最後乙個坑位[4]的位置。

②交換後的資料為:[4,11,14,18,28,30]

第6輪結束

排序後最終的陣列為:[4,11,14,18,28,30]

對挖坑填數進行如下總結:三個引數基準數,left(i),right(j)(假設有n個數)

1.i =left; j = right; 將基準數挖出形成第乙個坑a[i]。

2.j–由後向前找比它小的數,找到後挖出此數填前乙個坑a[i]中。

3.i++由前向後找比它大的數,找到後也挖出此數填到前乙個坑a[j]中。

4.再重複執行2,3二步,直到i==j,將基準數填入a[i]中。

整個快速排序的時間複雜度仍然是o(n的平方);

快速排序是一種不穩定的排序演算法,也就是說,多個相同的值的相對位置也許會在演算法結束時產生變動。

為了便於道友們向我諮詢問題,特意開設了乙個免費的知識星球——captianxue,星球提供學習、理財、生活、職場等各類文章和免費答疑!!

完整的**如下:

#include#includeusing namespace std;

void quicksort(int s, int left, int right)

s[i] = x; //把基準數填入

quicksort(s, left, i - 1); //當前基準數左邊的子陣列遞迴呼叫

quicksort(s, i + 1, right);//當前基準數右邊的子陣列遞迴呼叫 }}

int main() ;

printf("原來的陣列為:\n");

for(int i=0; i<6; i++)

printf("%d ",s[i]);

printf("\n");

quicksort(s,0,5);//呼叫快速排序的函式,引數為陣列名,陣列的左端點,陣列的右端點

printf("排序後的陣列(從小到大)為:\n");

for(int i=0; i<6; i++)

printf("%d ",s[i]);

printf("\n");

return 0;

}

當然,還有一種快速排序,選取當前陣列中首,尾,中三個數的中位數,即大小居中的數為基準數。其他的操作過程不變!學者可以自我實現。

更多的排序演算法:

sort函式排序

氣泡排序

選擇排序

插入排序

快速排序

希爾排序

堆排序

快速排序 QuickSort

快速排序通常用於排序的最佳的使用選擇,其期望執行時間為 o nlgn 能夠進行就地排序。最壞執行時間為 o n 2 演算法描述 分解 divide 陣列 a beg end 被劃分為兩個子陣列 a beg mid 1 和a mid 1 end 使得a beg mid 1 中的資料都小於 a mid ...

快速排序 quicksort

快速排序 quicksort 是分治法的典型例子,它的主要思想是將乙個待排序的陣列以陣列的某乙個元素x為軸,使這個軸的左側元素都比x大,而右側元素都比x小 從大到小排序 然後以這個x在變換後陣列的位置i分為左右兩個子陣列,再分別進行快速排序,直到子陣列中只有乙個元素為止。快速排序演算法如下 void...

快速排序 QuickSort

1,void quicksort int a,int low,int high 這個函式是排序的遞迴部分,mid就是已經確定的基準元素的位置。2,int partition int a,int low,int high 這個函式幹了兩件事 1 挑出來乙個基準元素 這裡選的是最後乙個作為基準 找它的正...