排序學習筆記 2 快速排序

2021-04-22 02:29:51 字數 1711 閱讀 4813

學習排序,參考**、測試程式:

表示一下感謝~~

交換排序。包括氣泡排序和快速排序,一般說來冒泡是不能給別人說的:怕丟臉,呵呵。所以我們就預設交換排序==快速排序。

1. 思想

a)它採用的是分而治之的策略(divide and conque)。基本思想是:任取待排序列的某個記錄(這句話就包含了優化的可能)作為基準,按照該關鍵碼大小,將整個序列分成兩個序列——--左側的所有記錄的關鍵碼都比基準小(或者等),右側的都比基準大,基準則放在兩個子串行之間,顯然這時基準放在了最後應該放置的位置(這個找pivot的方法,有很多,但是基本上都不對效能產生大的影響。但是好的pivot會很好的避免最壞情況的出現)。分別對左右子串行重複上面的過程,直到最後所有的記錄都放在相應的位置(就是遞迴了,沒什麼好辦法)。

b)整體上說,他的效能是所有排序裡面最好的,而且消耗的輔助空間比較小。但是,最大的問題就是:遞迴,資料量大的時候會把stack爆掉。

c)不穩定排序,效能:o(n*lg(n));

d)當輸入源是已經排序好的資料,這時候快速排序會得到最差的效能:每次新的比較都只是比上次少乙個元素;

2. 版本

1)經典快速排序(嚴版)

尋找pivot的過程是整個演算法的關鍵:是while巢狀兩個小while:首先把最left元素作為pivot,從右向左,遇到小的放到left;從左向右,遇到大的,放到right;-->中間碰頭,把pivot放到對應位置上。找完所有元素結束。

《**》

template

int partition2(t a, int left, int right)

a[left] = pivot; 

return left;

}這個方法還有乙個變形,就是:從左到右,遇到小的停;從右向左,遇到大的停;互換;碰頭的時候,把pivot放到對應位置上(通過交換得到)。和這個區別不大

2)簡化pivot版(殷版)

實際上尋找pivot不必要那麼費勁,從這邊到那邊,很難記住。殷版的比較實用,好記:在for迴圈中,讓pivot從左到右比較,遇到乙個小的,就把pivotpos++(pivotpos從left取值開始),然後pivotpos和當前第i個元素值進行交換。等迴圈結束之後,pivot與所有的值都進行了一次比較,pivotpos也記錄下了這樣乙個位置:左邊的值都小,右邊的之都大,然後把pivot值放到這裡;ok。

《**》

template 

int partition(t a, int left, int right)

}swap(a[left], a[pivotpos]);

return pivotpos;

}3)對整個快速排序的效能優化

a)當資料個數為5->25的時候,才能直接插入法的效率比qsort快至少10%。所以,在遞迴過程中,待排資料個數小於m的時候,使用直接插入法;

b)基本同上,個數小於m的時候,直接忽略。完成之後,得到乙個總體上大致已經排好序的序列,然後對整體使用直接插入法

c)對於pivot的選擇,除了上述的兩種基本方法外,可以提高。當每次劃分得到的兩個子串行的個數非常接近的時候,效果是最好的;所以我們希望得到乙個最接近中值的pivot,至少不能弄成最差情況。所以,可以把pivot的值等於:right、left和中點這三

個值的中間值(參見文章「三個數字的中間值「);

d)綜合運用前三種方案,可以把qsort的效率提高20->25%。

快速排序學習筆記

學習資料出處 白話經典演算法系列之六 快速排序 快速搞定 快速排序採用分治策略,其基本思想 1 從數列中選乙個元素x作為基準數 2 分割槽過程,把不小於x的元素放到x的右邊,小於x的元素放到x的左邊 3 再對左右區間重複進行分割槽操作,直到各區間只有乙個數 morewindows總結的 挖坑填數 分...

學習筆記 快速排序

基本步驟 1 確定分界點x a l a r a l r 1 2 劃分區間 小於x的在一邊,大於x的在另一邊 3 遞迴處理左右兩端 const int n 1e5 5 int n,a n void quick sort int a,int l,int r quick sort a,l,j quick ...

學習筆記 快速排序

將乙個一維陣列從小到大排列。快速排序利用了遞迴的思想。需要三個引數,陣列本身,陣列起始索引也就是0,陣列最右索引,也就是陣列長度 1。簡單來說,快速排序的思想是這樣的,先選擇乙個數作為基準數,把比它小的都移動到左邊,把比它大的都移動到右邊,然後針對左邊這個子陣列,再選擇乙個基準數,比它小的移到左邊,...