快速排序,聽這個名字就能想到它排序速度比較快方法,是一種分治思想,現在各種語言中自帶的排序庫很多使用的都是快速排序。
快速排序是一種原地排序,只需要乙個很小的棧作為輔助空間,空間複雜度為o(log2n),所以適合在資料集比較大的時候使用。
時間複雜度比較複雜,最好的情況是o(n),最差的情況是o(n2),所以平時說的o(nlogn),為其平均時間複雜度。
隨機找出乙個數,可以隨機取,也可以取固定位置,一般是取第乙個或最後乙個稱為基準,然後就是比基準小的在左邊,比基準大的放到右邊,如何放做,就是和基準進行交換,這樣交換完左邊都是比基準小的,右邊都是比較基準大的,這樣就將乙個陣列分成了兩個子陣列,然後再按照同樣的方法把子陣列再分成更小的子陣列,直到不能分解為止。
(一)演算法思想
本質是分而治之思想的運用。首先選取乙個元素作為主元(pivot),將大於該主元的元素放在陣列的右邊,小於主元的元素放在陣列的左邊,等於主元的元素位置不變,然後不斷迭代上述規則完成排序。
(1)主元pivot。取頭、中、尾三處的中位數,並交換位置,使頭中尾按照從小到大的順序排放(*)。此時,運用乙個trick,將mid處元素值與right-1處元素值交換。
(2)子集的劃分。設定兩個變數i和j,令i=left、j=right-1;第一次迴圈時,i=0,j=len(arr)-2。
(3)i每次向右移動乙個位置(i++),當該位置元素值大於等於主元時停止移動;此時,j向左移動,每次移動乙個位置(j–),當該位置元素值大於等於基準值時停止移動。
(4)交換i、j處的值,然後重複執行步驟3,直至i=j時,停止移動。交換i與right-1處值(即pivot值)。
(5)此時,pivot左邊的都是小於其值,右邊都是大於其元素的值。然後不斷對左右部分遞迴執行上述4步驟。
注意點:
(1)主元的選取。如果取陣列第乙個元素a[0],很大可能造成整個排序時間複雜度過高。例如a=[1,2,3,4,…,n],此時選1作為主元,會使得t(n)=o(n)+t(n-1)=o(n)+o(n-1)+t(n-1)=o(n^2),時間複雜度過大。
(2)主元存放的位置。主元確定後,left位於無序區的最左邊,right位於無序區的最右邊,left(3)與pivot相等元素的處理。在子集劃分過程中,如果遇到與pivot值相等的元素,有兩種選擇,一種是把它視為小於pivot的元素(即i++或j–),即忽略;另外一種是把它視為大於pivot的元素(i或j停下來,等待與j或i的交換),即停下來作交換。考慮一種特殊的例子,a=[1,1,1,1,…,1],如果選擇忽略策略的話,此時i會不斷向前移動,直至移動至j處(j位於pivot處,最右邊),時間複雜度t=o(n^2)。如果選擇停下來作交換,原始序列會被基本上被等分成n/2的序列,然後不斷往下遞迴,最後時間複雜度為o(nlogn)。
(4)何時停止劃分。i=j處,交換i與pivot位置的值。
(5)不斷迭代。pivot與i交換位置後,此時pivot左邊全是小於等於主元值的元素,pivot右邊全是大於等於主元值的元素。然後對左右部分,不斷迭代使用快排。 (6)小規模資料的處理。由於不斷遞迴,會占用系統堆疊的空間,且系統堆疊的進出很耗費時間,對於小規模資料,此時,插入排序優於快排。
(二)**實現
def quick_sort(arr):
quicksort(arr,0,len(arr)-1)
def quicksort(arr,left,right):
pivot=median3(arr,left,right)
i=left+1
j=right-2
while(true):
while(a[i]
i++
while(a[j]
>pivot):
j--
if(ia[i],a[j]
=a[j],a[i]
else:
break
a[i],pivot=pivot,a[i]
quicksort(arr,left,i-1)
quicksort(arr,i+1,right)
def median3(arr,left,right):
center=
(left+right)/2
#leftif(a[left]
>a[center]
): a[left],a[center]
=a[center],a[left]
#leftif(a[left]
>a[right]
): a[left],a[right]
=a[right],a[left]
#centerif(a[center]
>a[right]
): a[center],a[right]
=a[right],a[center]
a[center],a[right-1]
=a[right-1],a[center]
//統一介面
void qucik_sort(int a[
],int n)
void quicksort(int a[
],int left,int right)
while(a[--j]
>pivot)
if(iswap(
&a[i],&a[j]);
else
break;}
swap(
&a[i],&a[right-1]
); //交換主元與i的值
//遞迴排序
quicksort(a,left,i-1)
; quicksort(a,i+1,right);}
voif median3(int a[
],int left,int right)
void swap(int a,int b)
(三)演算法分析
優點:速度快,剩空間,缺點:非常脆弱,在實現時一定要注意幾個小細節。
什麼情況下是最好的呢:
待排序列公升序有序o(n),即,1 2 3 4 5 6 7,這種情況下,基準選擇第乙個數,調整次數最少,注意只是除錯次數減少,比較次數沒變少,
所以從理論上來說,比較只需要把資料放入暫存器,然後比較。
mov ax,
mov cx,
cmp ax,cx
但實際情況下,因為有l1,l2的存在,然後你的程式又存在程序切換,現場恢復等等各種複雜因素,實際上的速度就好說了。
什麼情況下是最差的呢:
待排序序列降序有序o(n2),即,7 6 5 4 3 2 1,這種情況就退化為氣泡排序。
最近面試被懟了?缺面試題刷提公升自己嗎?
今日部落格
效能優化之資料庫優化
資料庫效能優化,原理適用於大部分資料庫包括sqlite、mysql、oracle、sql server,詳細介紹了索引(優缺點、分類、場景、規則)和事務,最後介紹了部分單獨針對sqlite的優化……閱讀全文
oalp、oatp、htap這些名詞都是個啥?
oltp是事件驅動、面向應用的,也稱為面向交易的處理過程。其基本特徵是前台接收的使用者資料可以立即傳送到計算中心進行處理,並在很短的時間內給出處理結果,是對使用者操作的快速響應。例如銀行類、電子商務類的交易系統就是典型的oltp系統……閱讀全文
如何快速獲得百度前二頁競爭對手標題?
標題設定對於 優化來說是至關重要的,基本所有 優化人員都接程式設計客棧觸過 標題的設定問題,特別是很多新站,在標題設定時一定要做好標題分析,除開其它的準備,很多時候我們需要去認真分析同行業競爭對手網頁的標題,搜程式設計客棧索不同關鍵詞,統計各個關鍵詞下搜尋結果頁 的標題,可以更全面的綜合這些關鍵詞下...
戴仁光 百度搜尋 認證微博 快速獲得流量?
在不久前裡整合了微博的搜尋結果,合作來自騰訊微博,網易微博,搜狐微博三家,新浪微博不在裡面,新浪單獨推出微博搜尋。但是說到搜尋,新浪微博搜尋比起搜尋來,也是九牛一毛而已。在昨天我的乙個無意舉動,發現了一種 ld程式設計客棧quo 搜尋 認證微博 的最新的seo操作,這種seo操作可能不會太長遠,但是...
談談我是如何快速衝出百度11位現象的
讓站長頭疼的並不是 沒權重或者 快照不新。最讓站長頭疼的是 排名出現11位現象。無論你怎麼高質量的更新,怎麼去做高質量外鏈,你的排名仍然如泰山一樣紋絲不動。有些童鞋說這是百www.cppcns.com度人工干涉。但是我並不這樣認為。通過調查了解很多 11位 的 我認為這絕對不是人工操作進行的排名干涉...