浅谈优先队列
淺談優(yōu)先隊(duì)列
一道面試題
如果你被問到:
“編寫一個程序,從 10 億個元素的整數(shù)數(shù)組中找出前10個最大的數(shù)。”
你會怎么回答?
我想,最最簡單的回答就是蠻力法:先對這10億個數(shù)排序(比如用時間復(fù)雜度為 O(nlogn)O(nlog?n) 的快速排序),然后選出前10個最大的。
請問有更好的方法嗎?
優(yōu)先隊(duì)列是什么
普通的隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu):從隊(duì)尾追加元素,從隊(duì)首刪除元素。
在優(yōu)先隊(duì)列中,元素被賦予優(yōu)先級。出隊(duì)時,具有最高優(yōu)先級的元素被刪除,也就是說,優(yōu)先隊(duì)列具有最高優(yōu)先級先出(largest-in,first-out)的行為特征。
優(yōu)先隊(duì)列支持兩種基本操作:
對于本文開始的問題,如果你知道了有“優(yōu)先隊(duì)列”這么一說,則很容易想到下面的解決辦法:
此外,上述方案可以并行方式運(yùn)行,最后合并結(jié)果。
除了上面的例子,優(yōu)先隊(duì)列還有一些重要的應(yīng)用場景。
比如作業(yè)(或者說任務(wù))調(diào)度,當(dāng)一個作業(yè)完成后,需要在所有等待調(diào)度的作業(yè)中選擇一個優(yōu)先級最高的作業(yè)來執(zhí)行,并且也可以添加一個或多個新的作業(yè)到優(yōu)先隊(duì)列中。
再比如排序,通過插入一系列元素,然后一個個地刪除其中最小的元素,就可以實(shí)現(xiàn)從小到大的排序。一種名為“堆排序”的重要排序算法正是利用了基于“堆”實(shí)現(xiàn)的優(yōu)先隊(duì)列。
優(yōu)先隊(duì)列的實(shí)現(xiàn)
用無序數(shù)組實(shí)現(xiàn)
對于入隊(duì)操作,直接把元素追加到數(shù)組尾部。時間復(fù)雜度為 O(1)。
對于出隊(duì)操作,需要遍歷數(shù)組,找出優(yōu)先級最高的元素,并刪除之,空缺的位置由后面的元素依次補(bǔ)上。因此,出隊(duì)的時間復(fù)雜度為 O(n)。
用有序數(shù)組實(shí)現(xiàn)
對于入隊(duì)操作,由于要求數(shù)組有序,所以在插入元素的時候需要遍歷數(shù)組以找到適合的位置,然后在該位置插入,同時此位置后面的元素要依次向后移動,時間復(fù)雜度為 O(n)。
對于出隊(duì),由于序列是有序的,所以時間復(fù)雜度為 O(1)。
用鏈表實(shí)現(xiàn)
用鏈表實(shí)現(xiàn)和數(shù)組類似,也可分為無序和有序兩種,不同的是采用鏈?zhǔn)酱鎯Y(jié)構(gòu),省去了移動元素的麻煩。
用堆實(shí)現(xiàn)
上面三種實(shí)現(xiàn)思路其實(shí)都不怎么好,不是入隊(duì)的時間復(fù)雜度為 O(n),就是出隊(duì)的時間復(fù)雜度為 O(n). 有沒有更好的實(shí)現(xiàn)呢?有一種數(shù)據(jù)結(jié)構(gòu)叫“堆”,基于堆實(shí)現(xiàn)的優(yōu)先隊(duì)列,出隊(duì)和入隊(duì)的時間復(fù)雜度都為 O(logN).
堆到底是什么,都有哪些性質(zhì),具體怎么實(shí)現(xiàn)……這一系列的問題,咱們下回聊。
【未完待續(xù)】
參考資料
https://allenwind.github.io/2017/09/12/%E4%BC%98%E5%85%88%E9%98%9F%E5%88%97%E7%9A%84%E4%BA%94%E7%A7%8D%E5%AE%9E%E7%8E%B0/
總結(jié)
- 上一篇: python 弹出对话框_python+
- 下一篇: xpath安装与下载