前面的博文講了氣泡排序、選擇排序、插入排序,今天我們談談快速排序!
快速排序的基本思想是:
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 挑出來乙個基準元素 這裡選的是最後乙個作為基準 找它的正...