選擇第K大元素(快排 快選以及k 選取比較)

2021-10-05 02:12:51 字數 2936 閱讀 2174

先看執行結果

按照書中所給的快排、快選以及k-選取演算法分別寫出函式檢測執行結果以及時間

發現不出所料的直接快排演算法會慢很多,但預想更穩定的k-選取演算法的耗時比預期設想要大,而相對不太穩定的快選演算法卻是三者之中最快的,為了避免偶然性,又重複做了多組實驗,並將n的範圍擴大到100~1000000,實驗結果如下:

但是之前查過資料,k-選取方法應該是線性的,quickselect演算法平均情況是線性的,但最壞的情況下,也會達到o(n2),但在實驗中,我卻發現quickselect演算法的效能元好於k-選取演算法。

同時,我也注意到k-選取耗時和quickselect耗時也都比較符合線性遞增的規律。所以,二者在資料集都比較雜亂隨機的情況下,線性時間複雜度是符合理論推導的。

但為什麼更加穩定的k-選取演算法會比quickselect慢那麼多呢?二者同是運用減而治之,逐步逼近的策略啊!

再次觀察**,我們不難發現,在k-選取演算法中,它有以下幾個缺點:

對於陣列中的幾乎所有元素都有分類排序,雖然是每一小分組內的排序,但是確實是會消耗更多的時間,就算是用快排實現這樣的組內排序也是耗時頗多;o(n)耗時

每組分好後,我們同樣需要再對分出組的中位數再次這樣的排序,當然,這裡的耗時會相對小很多

找出中位數後,我們又需要根據中位數的位置再次分類取值,這裡有會是o(n)的時間

之後才能根據位置進行「減」

綜上:此演算法雖然穩定,但屬實繁瑣

而在快速選取演算法中,我們始終只分大組,迴圈不會層層巢狀式深入,遍歷一遍之後就可以迅速分組,從而加快尋找的步伐!(但確實如果運氣不好,分組太不均勻的話,著實會變成o(n2)的複雜度)。

總結:資料無序度高,且資料量龐大的情況下,個人認為,要實現選擇第k大的元素,快選的綜合實用效率更好一些。

void

quicksort

(int low,

int high,

int* a)

int middle=

partition

(low,high,a);if

(middle> low)

quicksort

(low,middle-

1,a);if

(middle< high)

quicksort

(middle+

1,high,a)

;}

隨機選取劃分
int

partition

(int low,

int high,

int* a)

a[low]

=pivot;

return low;

}

int

linearselect

(int k,

int low,

int high,

int* a)

for(

int i=

0;i<

(high-low-4)

/5;i++

)//找所有中位數的中位數

int x=

linearselect

((high-low-4)

/10,low,low+

(high-low-4)

/5,a);

//以相對於m的大小,分集合

int m=

partition

(low,high,x,a);if

(k>m)

return

linearselect

(k-m-

1,m+

1,high,a);if

(kreturn

linearselect

(k,low,m-

1,a)

;return a[k+low]

;}

根據指定值劃分
int

partition

(int low,

int high,

int x,

int* a)

}int pivot=a[low]

;while

(low

a[low]

=pivot;

return low;

}

int

quickselect

(int k,

int low,

int high,

int* a)

a[i]

=pivot;

if(k

else

if(i

else

return a[i];}

return a[k]

;}

#### 最後呢,針對清華大學出版的《資料結構》指出乙個問題

在[lo, hi-1]內構造軸點,會導致hi位的資料從此**之後不會變,這樣層層遞迴下去,分組進行的根本不徹底,會出現大量異常排序的點,進而導致排序失敗

基於快排求無序陣列的第K大元素

package other pratice 怎麼最快的求無序陣列的第k大元素。author sxy 我們知道快排的排序是從大到小,還是從小到大取決於分割槽那個函式是如何寫的,本題是在陣列中尋找第幾大元素 所以需要在陣列的大小的順序要是從大到小 快速排序每次排序完找的 基準點即是第幾大元素。如果 如果...

如何用快排思想在O n 內查詢第K大元素?

如果要排序乙個陣列,我們先把陣列從中間分成前後兩部分,然後對前後兩部分分別排序,再將排好序的兩部分合併在一起,這樣整個陣列就都有序了。我們申請乙個臨時陣列 tmp,大小與 a p r 相同。我們用兩個游標 i 和 j,分別指向 a p q 和 a q 1 r 的第乙個元素。比較這兩個元素 a i 和...

快排思想之陣列中的第K個最大元素

在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。示例 1 輸入 3,2,1,5,6,4 和 k 2 輸出 5示例 2 輸入 3,2,3,1,2,4,5,5,6 和 k 4 輸出 4class solution object ...