資(zī)訊

精準傳達 • 有效溝通

從品牌網站建設到網絡營銷策劃,從策略到執行的一(yī)站式服務

Java集合與數據結構——優先級隊列(堆)

來源:公司資(zī)訊 | 2021.08.17

、二叉樹(shù)的次序存儲

1.堆的存儲方法

  使用數組保存二叉樹(shù)結構,方法即将二叉樹(shù)用層序遍曆方法放(fàng)入數組中(zhōng)。

  一(yī)般隻适合表明徹底二叉樹(shù),因爲非徹底二叉樹(shù)會有空間的糟蹋。

這種方法的主要用法就是堆的表明。




2.下(xià)标關系

已知(zhī) 雙親 (parent) 的下(xià)标,則:


左孩子(left)下(xià)标 = 2 * parent + 1;

右孩子(right)下(xià)标 = 2 * parent + 2;


已知(zhī)孩子(不區别左右)(child)下(xià)标,則:


雙親(parent)下(xià)标 = (child - 1) / 2;


二、堆(heap)

1.概念

1.堆邏輯上是一(yī)棵徹底二叉樹(shù)

2.堆物(wù)理上是保存在數組中(zhōng)

3.滿意任意結點的值都大(dà)于其子樹(shù)中(zhōng)結點的值,叫做大(dà)堆,或許大(dà)根堆,或許最大(dà)堆

4.反之,則是小(xiǎo)堆,或許小(xiǎo)根堆,或許最小(xiǎo)堆

5.堆的基本作用是,快速找集合中(zhōng)的最值


2.大(dà)/小(xiǎo) 根堆

2.1小(xiǎo)根堆


每棵樹(shù)的根節點都是小(xiǎo)于孩子節點,此時這棵樹(shù)就叫做小(xiǎo)根堆


2.2大(dà)根堆


每棵樹(shù)的根節點都是大(dà)于孩子節點的,此時這棵樹(shù)就叫做大(dà)根堆

  咱們在說 巨細根堆 時,隻說了 根節點比孩子節點大(dà),沒有說 左右孩子節點誰比誰大(dà)、誰比誰小(xiǎo).

所以得出結論

不管是 大(dà)根堆、仍是小(xiǎo)根堆,左右孩子的巨細關系是不确定的,咱們隻能确定根節點和孩子節點的關系.


3.建堆操作

  下(xià)面咱們給出一(yī)個數組,這個數組邏輯上能夠看做一(yī)顆徹底二叉樹(shù),但是還不是一(yī)個堆,現在咱們通過算法,把它構建成一(yī)個堆。


  根節點左右子樹(shù)不是堆,咱們怎麽調整呢?這裏咱們從倒數的第一(yī)個非葉子節點的子樹(shù)開(kāi)端調整,一(yī)向調整到根節點的樹(shù),就能夠調整成堆。


将一(yī)個二叉樹(shù) 調整爲一(yī)個 大(dà)根堆





這棵二叉樹(shù)調整爲 大(dà)根堆 必須将 每顆子樹(shù)都調整爲大(dà)根堆.


3.1向下(xià)調整

思想 步驟:

parent —> 根節點下(xià)标

child —> 孩子節點下(xià)标


1.從最終一(yī)棵子樹(shù)進行調整.

2.每顆子樹(shù)從根節點向下(xià)調整,假如左右孩子節點的最大(dà)值比這個根節點大(dà),那麽值互換,然後 parent 指向 child ,child = 2* parent + 1, 繼續向下(xià)調整,直到 下(xià)标child 超出二叉樹(shù) 規模.

3.重複第二步的操作,遍曆每一(yī)顆子樹(shù),直到所有子樹(shù)全部遍曆完結.


代碼實現:





咱們對這個代碼進行測驗



測驗堆中(zhōng)的結果:


時間複雜(zá)度分(fēn)析:


  粗略預算,能夠認爲是在循環中(zhōng)執行向下(xià)調整,爲 O(n * log(n))(了解)實際上是 O(n)


堆排序中(zhōng)建堆過程時間複雜(zá)度O(n)怎麽來的?




4.入隊操作

步驟

1.判斷是否滿容

2.在數組的最終插入元素

3.調整爲 大(dà)/小(xiǎo) 根堆


在這幾個步驟中(zhōng),前兩步咱們都能夠完結 ,第三步咱們要注意:


使用 向上調整 調整爲大(dà)/ 小(xiǎo)根堆


之前咱們介紹了 向下(xià)調整

這次咱們說的是向上調整,與之前向上調整的思路十分(fēn)相似~~

咱們來說一(yī)下(xià) 向上調整的思路


4.1向上調整




4.2push 入隊的完好代碼展示




5.出隊操作

  爲了避免破壞堆的結構,删去(qù)時并不是直接将堆頂元素删去(qù),而是用數組的最終一(yī)個元素與堆頂元素交流,然後通過向下(xià)調整方法重新調整成堆.


思路:


1.交流 數組首尾元素

2.usedSize- -,删去(qù)最終的元素

3.使用向下(xià)調整 ,調整爲大(dà)/小(xiǎo) 根堆


5.1pop 出隊代碼徹底展示



6.檢查堆頂元素

回來 下(xià)标爲0的數組元素.回來堆頂元素.





現在咱們來看一(yī)個 堆的 使用


7.TOK 問題

咱們在這裏 提出一(yī)個問題:


在一(yī)千萬個數據中(zhōng)找到 前 10個最大(dà)的 數據,請問如何查找

咱們有 幾個想法


1.基本反應,給1000萬個數據排序,取10個最大(dà) 的,咱們直接 Arrays.sort () ;

  這種排序方法當然也不是不能夠,隻不過時間複雜(zá)度非常大(dà),在面試中(zhōng)寫出這樣的排序思路會落得劣勢.


2.将這1000個數據 建成一(yī)個大(dà)堆,每次将最大(dà)的取出,然後調整,取出10個即可.

  這種方法的缺陷則是, 堆太大(dà)了,咱們建立的堆也會是 1000萬,假如這個數據更大(dà),那麽堆也會更大(dà),每次調整的複雜(zá)度也很大(dà).


3.建立一(yī)個巨細爲 K 的小(xiǎo)堆.




以上面這個數組爲例,找出這組數據中(zhōng)的前三個最大(dà)的元素.


3.1 将當時數據的前三個 建立爲小(xiǎo)堆

3.2 遍曆剩餘的元素,順次和堆頂元素進行比較. 假如當時 i 下(xià)标元素 比堆頂元素大(dà),就把i下(xià)标入隊.



  堆頂元素一(yī)定是最小(xiǎo)的,每次都與堆頂元素進行比較,每次都将最小(xiǎo)的那個除掉,最終遍曆完,剩餘的就是 最大(dà)的幾個數據了嘛~

根據上面的這個 思路,咱們同理能夠解決許多相似的問題

 

—— 靈通雲微信公衆号 ——

熱門标簽

上一(yī)條———————

下(xià)一(yī)條———————

十七年 建站經驗

多一(yī)份參考,總有益處

聯系靈通雲,免費(fèi)獲得專屬《策劃方案》及報價

咨詢相關問題或預約面談,可以通過以下(xià)方式與我(wǒ)們聯系

業務熱線:400-688-6062 / 大(dà)客戶專線   南(nán)通:15818561755