先看執行結果
按照書中所給的快排、快選以及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 ...