資料結構 可合併堆 左偏樹

2021-07-04 15:56:37 字數 1964 閱讀 1476

剛剛又看了一遍左偏樹的內容,為了加深理解,自己也寫一篇,夾雜著許許多多的借鑑。

左偏樹是可合併的二叉堆,首先滿足所有的堆的性質,其外,它還可以合併。

左偏樹的樹節點需要儲存的資訊有: 1.

左右子樹節點編號 2.

此節點到有空子結點的結點的最短距離

len

3.自身權值

首先解釋一下什麼是有空子節點的節點,就是子節點數不足

2個的節點,空,就是沒有的意思。

左偏樹除了堆的所有性質,它還要滿足的重要的性質就是「左偏

」,這個性質保證了它的操作都是

o(logn)的。

左偏就是每個節點的左子節點的

len不小於右子節點的

len(但並不代表左子節點數一定不小於右子節點數),那麼可知

len[i] =len[rc[i]]+1

,下面附上一張圖會方便理解。

len值。

**完性質之後,我們來看看它的操作。

堆可以做到的是:插入(

o(logn)

),查詢最值(

o(1)

),刪除堆頂(

o(logn));

對於左偏樹,這些操作都是基於合併的(除了查詢最值),而且複雜度都仍然是

o(logn)。

左偏樹合併操作合併的是兩棵左偏樹,對於堆的插入,就是合併一棵樹和乙個節點,對於堆的刪除,就是合併根的兩棵子樹。

那麼我們就只需要知道左偏樹的合併過程就可以了。

以小根堆為例,假如要合併

a, b

兩個堆並且

a < b

(這個不滿足的話只需要交換一下就可以),而且還要求兩棵樹的節點沒有包含關係,就是沒有相同的節點。在遞迴的過程中,比較b和

a的右子樹大小,如果

b的右子樹,那麼交換b和

a的右子樹,接著將

b看成剛剛的

a,繼續交換;如果

b>a

的右子樹,那麼繼續找這顆樹的右子樹。而這樣可能會破壞左偏的性質,所以需要在回溯的過程中維護左偏性質,通過交換左右子樹完成。總的來說,左偏樹的核心操作,合併,是在右子樹上進行的,又因為要保證每個節點的左子節點的

len不小於右子節點的

len,而且有

len[i] =len[rc[i]]+1

,所以知道一棵左偏樹的最大

len是

logn

級別的,即使它是一條鏈,由於左偏性質,它會變成向左偏的一條鏈,而

len的最大值是

0,合併的複雜度很低。下面附上圖會理解得更清晰:

//經過實踐與進一步思考,證明原來自己寫的模板有很大問題,最後還是決定按照大家通用的寫法寫一遍

// 左偏樹模板, 以大根堆為例

//結構體

struct nodet[m];

//核心操作 :合併(函式返回值:樹根)

int merge(int a, int b)

//插入

void insert(int a, int x)

//刪除

void del(int a)

資料結構 左偏樹(可並堆)

模板 可並堆 可並堆真的很好寫!可並堆真的很好寫!可並堆真的很好寫!只有乙個合併操作,插入都是用合併實現的,最多再來乙個並查集,真的簡單到爆好嗎。include define ll long long using namespace std const int maxn 200001 struct ...

左偏樹(可並堆)

左偏樹其實是一種可並堆,它可以 o log2 n o l og2n 合併兩個堆。那左偏?也就是說他左邊肯定有什麼東西比右邊大 別著急,在左偏樹上有乙個叫距離的東西 個點的距離,被定義為它子樹中離他最近的外節點到這個節點的距離 這與樹的深度不同 其中我們定義乙個節點為外節點,當且僅當這個節點的左子樹和...

可並堆 左偏樹

題目描述 如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 ...