排序演算法 快速排序

2021-09-25 01:41:27 字數 2829 閱讀 8647

快速排序為什麼快的乙個主要原因就是:通過選主元,進行過子集劃分,主元一次性就被放到了正確的位置上了

演算法思想與步驟

1.選主元,藏一邊

2.進行子集劃分,劃分過程中會進行交換,保證主元左側元素比主元小,右側元素比主元大

3.對子集進行遞迴呼叫

問題1

關於這個問題,我一開始認為最好情況是初始就是有序的,實際上初始有序,主元要是選一端的話時間複雜度會是o(n^2),原因可見下圖:(這裡的時間複雜度分析是按照遞推的方法進行的,其中o(n)指每次選主元的都要遍歷下資料,所以為o(n)).也就是說原先是有序的,且每次主元都選在了一端(子集劃分時偏向一側).反而是最壞的情況.

最好的情況:每次選的主元都能將序列大致等分

問題2

為什麼呢?

舉乙個極端的例子,如果乙個序列都是相等的,比如十個1,

如果交換,那麼壞處是:進行了很多無畏的交換;好處:每次交換完成後,首尾的指標都會繼續前進,最後兩個子串行基本都是等分的,這樣時間複雜度就會是o(nlog(n))

如果不交換,那麼好處就是,不用進行無畏的交換了,壞處就是,主元每次都選在了一端,時間複雜度就是o(n^2)

問題3、小規模資料處理問題

快速排序的乙個問題是:它使用了遞迴演算法,遞迴演算法層層壓棧,小規模資料效能並不好.

第一種是限制遞迴深度。一旦遞迴過深,超過了我們事先設定的閾值,就停止遞迴。

第二種是通過在堆上模擬實現乙個函式呼叫棧,手動模擬遞迴壓棧、出棧的過程,這樣就沒有了系統棧大小的限制

namespace quicksort

if(a[mid]

(a[mid]

>a[right]

)// cout<

(a[mid]

,a[right-1]

);//將主元藏在右側(倒數第二個元素) 目的:方便後面做子集劃分

// dump(a,10," median3 after : ");//除錯**

return a[right-1]

;}void

qsort

(int a,

int left,

int right)

//1.選主元

int pivot=

median3

(a,left,right)

;//2.子集劃分(細節1)

int l=left;

//最左側肯定比主元小了,不用考慮了,所以下面是++l

int r=right-1;

//最右側肯定比主元大,倒數第二個是主元,都不用考慮了,所以下面是--r

while(1

)while

(a[--r]

>=pivot && l

if(l

else

} 將主元放在正確的位置(細節3,交換的是a[right-1]小心不能寫作pivot)

swap

(a[right-1]

,a[l]);

// cout<

//3 遞迴呼叫左右兩側(細節4,都寫成l,)

qsort

(a,left,l)

;//這裡是l,不能是l-1

qsort

(a,l+

1,right)

;//這裡這裡是l+1,或l都可

}void

func

(int a,

int size)

qsort

(a,0

,size-1)

;}}namespace test

;int arr2=

;int arr3=

;int arr4=

;int arr5=

;void

quicksorttest()

}int

main()

參考:

資料結構mooc課程

排序演算法 快速排序演算法

網際網路的大型公司還在火熱招聘中,參與了一次又一次的筆試,都不通過,我還是太菜!作為程式設計人員,需要邁過去 資料結構與演算法 這個坎,畢竟,筆試不會真的很虧,加油吧,少些水,多點實操。一 快速排序演算法思想 從一組資料中找出乙個基準值,一般是選擇中間值作為基準值,然後從左到右將值與基準值進行比較,...

演算法 排序演算法 快速排序

快速排序是對冒泡法排序的一種改進。快速排序演算法 的基本思想是 將所要進行排序的數分為左右兩個部分,其中一部分的所有資料都比另外一 部分的資料小,然後將所分得的兩部分資料進行同樣的劃分,重複執行以上的劃分操作,直 到所有要進行排序的資料變為有序為止。可能僅根據基本思想對快速排序的認識並不深,接下來以...

排序演算法 快速排序

快速排序使用分治法 divide and conquer 策略來把乙個序列 list 分為兩個子串行 sub lists 步驟為 1.從數列中挑出乙個元素,稱為 基準 pivot 2.重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面 相同的數可以到任一邊 在這個分...