《數(shù)據(jù)結(jié)構(gòu)與算法之美》24——堆的應用

上一節(jié)我們學習了堆和堆排序的一些理論知識(點擊查看)役纹,今天我們就來講一講焰望,堆這種數(shù)據(jù)結(jié)構(gòu)的幾個非常重要的應用稽鞭。

應用一:優(yōu)先級隊列

優(yōu)先隊隊列避除,是一個按優(yōu)先級進出的特殊隊列,一般的隊列是先進先出翘盖,而優(yōu)先級隊列是優(yōu)先級高的先出滤否。

優(yōu)先級隊列與堆非常相似,一個堆可以看作一個優(yōu)先級隊列最仑。往優(yōu)先隊隊列插入一個元素,相當于往堆中插入一個元素炊甲;從優(yōu)先級隊列中取出優(yōu)先級最高的元素泥彤,就相當于取出堆頂元素。

例子1:合并有序小文件

合并多個有序的小文件到大文件卿啡。假設有100個文件吟吝,要合并到1個文件里,要求有序颈娜。

定義一個大小為100的小頂堆剑逃,從100個文件里取出第一行,初始化小頂堆官辽。然后取出堆頂放進大文件里蛹磺,并從此數(shù)據(jù)所在的文件里再取出一行放到堆里(重新堆化),重復這個動作同仆,直到所有文件的內(nèi)容都為空萤捆。

例子2:高性能定時器

定時器維護多個定時任務,每個任務都設置了觸發(fā)執(zhí)行的時間點。

高性能定時器

計算每個任務的時間差俗或,弄成小頂堆市怎。取堆頂元素的時間差,讓程序睡眠辛慰,睡眠時間為此時間差区匠,程序喚醒后,取出堆頂任務(刪除堆頂元素)并執(zhí)行帅腌。如果任務是重復的驰弄,再重新計算任務的時間差,并插入堆里狞膘。

應用二:利用堆求Top K

抽象成兩類問題:靜態(tài)數(shù)據(jù)集合和動態(tài)數(shù)據(jù)集合

實現(xiàn)方式:定義一個大小為K的小頂堆揩懒,順序遍歷數(shù)組,逐一與堆頂進行比較挽封,假設比它大已球,則刪除堆頂再插入后堆化。假設小于等于它辅愿,則忽略智亮。

對于動態(tài)數(shù)組,可維護一個實時的堆点待,當有數(shù)據(jù)插入數(shù)組阔蛉,與堆頂判斷,比它大則插入堆癞埠,否則忽略状原。并且插入到數(shù)組中。

時間復雜度:O(nlogk)苗踪。遍歷數(shù)組O(n)颠区,每次替換(堆化)O(logk)。

應用三:利用堆求中位數(shù)

中位數(shù)指在有序數(shù)據(jù)中處于中間位置的那個數(shù)據(jù)通铲。如果數(shù)據(jù)個數(shù)為奇數(shù)毕莱,則中位數(shù)是n/2+1位置的數(shù),如果是偶數(shù)颅夺,則是n/2和n/2+1朋截,可取其中的任意一個。

中位數(shù)

分兩種情況:靜態(tài)數(shù)據(jù)集合吧黄、動態(tài)數(shù)據(jù)集合

對于靜態(tài)數(shù)據(jù)部服,先排序,再取n/2+1拗慨。

對于動態(tài)數(shù)據(jù)饲宿,如果每次都排序厦酬,性能不好√毕耄可利用堆來實現(xiàn)仗阅。

定義兩個堆,一個大頂堆国夜,一個小頂堆减噪。大頂堆存儲前半數(shù)據(jù),小頂堆存儲后半數(shù)據(jù)车吹,并且小頂堆的數(shù)據(jù)都大于大頂堆的數(shù)據(jù)筹裕。

奇數(shù)、偶數(shù)

初始化時窄驹,對現(xiàn)有數(shù)組進行排序朝卒,把前n/2(n/2+1)個數(shù)存儲到大頂堆里,把后n/2個數(shù)存儲到小頂堆中乐埠,中位數(shù)就是大頂堆的堆頂抗斤。

對于動態(tài)插入時,把數(shù)據(jù)跟大頂堆的堆頂進行比較丈咐,如果小于等于堆頂瑞眼,則插入到大堆頂。如果大于等于小堆頂?shù)亩秧斂醚罚瑒t插入小堆頂伤疙。最后再對大頂堆和小堆頂進行平衡,保證大頂堆是n/2(n/2+1)個數(shù)據(jù)辆影,小頂堆是n/2個數(shù)據(jù)徒像。

插入

除了求中位數(shù),還能求其他百分位的數(shù)據(jù)蛙讥,例如“99%響應時間”锯蛀。實際上中位數(shù)是求50%的數(shù)據(jù),大堆頂和小堆頂各占50%键菱,對于“99%響應時間”這個問題,就是把大頂堆劃分為99%今布,小堆頂劃分為1%经备,其他實現(xiàn)跟中位數(shù)一樣。

中位數(shù)部默、99%

時間復雜度:插入數(shù)據(jù)O(logn)侵蒙、返回堆頂O(1)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市傅蹂,隨后出現(xiàn)的幾起案子纷闺,更是在濱河造成了極大的恐慌算凿,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犁功,死亡現(xiàn)場離奇詭異氓轰,居然都是意外死亡,警方通過查閱死者的電腦和手機浸卦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門署鸡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人限嫌,你說我怎么就攤上這事靴庆。” “怎么了怒医?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵炉抒,是天一觀的道長。 經(jīng)常有香客問我稚叹,道長焰薄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任入录,我火速辦了婚禮蛤奥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘僚稿。我一直安慰自己凡桥,他們只是感情好,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布蚀同。 她就那樣靜靜地躺著缅刽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蠢络。 梳的紋絲不亂的頭發(fā)上衰猛,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機與錄音刹孔,去河邊找鬼啡省。 笑死,一個胖子當著我的面吹牛髓霞,可吹牛的內(nèi)容都是我干的卦睹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼方库,長吁一口氣:“原來是場噩夢啊……” “哼结序!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起纵潦,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤徐鹤,失蹤者是張志新(化名)和其女友劉穎垃环,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體返敬,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡遂庄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了救赐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涧团。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖经磅,靈堂內(nèi)的尸體忽然破棺而出泌绣,到底是詐尸還是另有隱情,我是刑警寧澤预厌,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布阿迈,位于F島的核電站,受9級特大地震影響轧叽,放射性物質(zhì)發(fā)生泄漏苗沧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一炭晒、第九天 我趴在偏房一處隱蔽的房頂上張望待逞。 院中可真熱鬧,春花似錦网严、人聲如沸识樱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怜庸。三九已至,卻和暖如春垢村,著一層夾襖步出監(jiān)牢的瞬間割疾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工嘉栓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宏榕,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓侵佃,卻偏偏與公主長得像麻昼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子趣钱,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359