最大堆 最小堆Java實現,解決TOP K問題

2021-09-23 05:43:46 字數 2340 閱讀 1644

最大堆,最小堆類似,以下以最小堆為例進行講解。

最小堆是滿足以下條件的資料結構:

它是一棵完全二叉樹

所有父節點的值小於或等於兩個子節點的值

除了最後一層之外的其他每一層都被完全填充,並且所有結點都保持向左對齊。

對於topk問題,解決方法有很多:

方法一:對源資料中所有資料進行排序,取出前k個資料,就是topk。

但是當資料量很大時,只需要k個最大的數,整體排序很耗時,效率不高。

方法二:維護乙個k長度的陣列a,先讀取源資料中的前k個放入陣列,對該陣列進行公升序排序,再依次讀取源資料第k個以後的資料,和陣列中最小的元素(a[0])比較,如果小於a[0]直接pass,大於的話,就丟棄最小的元素a[0],利用二分法找到其位置,然後該位置前的陣列元素整體向前移位,直到源資料讀取結束。

這比方法一效率會有很大的提高,但是當k的值較大的時候,長度為k的資料整體移位,也是非常耗時的。

對於這種問題,效率比較高的解決方法是使用最小堆。

最小堆(小根堆)是一種資料結構,它首先是一棵完全二叉樹,並且,它所有父節點的值小於或等於兩個子節點的值。

最小堆的儲存結構(物理結構)實際上是乙個陣列。如下圖:

堆有幾個重要操作:

buildheap:將普通陣列轉換成堆,轉換完成後,陣列就符合堆的特性:所有父節點的值小於或等於兩個子節點的值。

heapify(int i):當元素i的左右子樹都是小根堆時,通過heapify讓i元素下降到適當的位置,以符合堆的性質。

回到上面的取topk問題上,用最小堆的解決方法就是:先去源資料中的k個元素放到乙個長度為k的陣列中去,再把陣列轉換成最小堆。再依次取源資料中的k個之後的資料和堆的根節點(陣列的第乙個元素)比較,根據最小堆的性質,根節點一定是堆中最小的元素,如果小於它,則直接pass,大於的話,就替換掉跟元素,並對根元素進行heapify,直到源資料遍歷結束。

最小堆的實現:

public

class

minheap

// 將陣列轉換成最小堆

private

void

buildheap()

}private

void

heapify

(int i)

// 獲取右結點的陣列下標

private

intright

(int i)

// 獲取左結點的陣列下標

private

intleft

(int i)

// 交換元素位置

private

void

swap

(int i,

int j)

// 獲取對中的最小的元素,根元素

public

intgetroot()

// 替換根元素,並重新heapify

public

void

setroot

(int root)

}

利用最小堆獲取topk:

public

class

topk

;// 獲取top5

int[

] top5 =

topk

(data,5)

;for

(int i=

0;i<

5;i++)}

// 從data陣列中獲取最大的k個數

private

static

int[

]topk

(int

data,

int k)

// 轉換成最小堆

minheap heap =

newminheap

(topk)

;// 從k開始,遍歷data

for(

int i= k;i

return topk;

}}

前面在介紹最小堆解決topk問題的時候,已經涉及到建堆、新增元素的過程,接下來介紹最小堆的刪除過程。

操作原理是:當刪除節點的數值時,原來的位置就會出現乙個孔,填充這個孔的方法就是,

把最後的葉子的值賦給該孔並下調到合適位置,最後把該葉子刪除。

如圖中要刪除72,先用堆中最後乙個元素來35替換72,再將35下沉到合適位置,最後將葉子節點刪除。

「結點下沉」

最大堆 最小堆

堆是一種經過排序的完全二叉樹,其中任一非終端節點的資料值均不大於 或不小於 其左孩子和右孩子節點的值。最大堆和最小堆是 二叉堆的兩種形式。最大堆 根結點的鍵值是所有堆結點鍵值中最大者。最小堆 根結點的鍵值是所有堆結點鍵值中最小者。而最大 最小堆集結了最大堆和最小堆的優點,這也是其名字的由來。最大 最...

最大堆 最小堆

堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點分別是節點i的左...

最大堆 最小堆

堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點分別是節點i的左...