資料結構與演算法 左偏樹(堆)的實現

2021-06-03 17:57:26 字數 2165 閱讀 1121

左偏樹,也可以稱之為左式堆。稱其為樹,是因為其儲存結構通常採用二叉樹,所以可以認為是一種特殊的二叉樹。稱其為堆,是因為在邏輯結構上,它屬於可合併堆的一種。其實資料結構中最欣欣向榮的兩個分支就是:平衡樹可合併堆。高階樹結構的核心都是圍繞如何使樹到達平衡而展開,高階堆結構的核心就是如何有效地進行合併。

這裡先介紹可合併堆中一種十分好用的資料結構:左式堆。人們熟悉或者常聽說的堆主要有:(二叉)堆、左式堆、斜堆、二項堆、斐波納契堆。其中二叉堆是最為常用的,一般的優先佇列都可以考慮用二叉堆實現,而stl中優先佇列,更是方便了大家的使用,如果自己程式設計主要注意sift down 和 sift up 這兩個核心操作的實現。

二叉堆左式堆

斜堆二項堆

斐波納契堆

insert

o(log n)

o(log n)

o(log n)

o(log n)

o(1)

extract-min

o(log n)

o(log n)

o(log n)

o(log n)

o(log n)

merge

o(m + n)

o(log n)

o(log n)

o(log n)

o(1)

程式設計複雜度

簡單較簡單

較簡單較複雜複雜

左式堆由於使用二叉鍊錶的儲存結構,對動態操作支援良好,在需要合併操作的場合,是極佳的選擇。二項堆(使用孩子兄弟儲存模式)和斐波納契堆(使用樹型結構配合雙向迴圈鍊錶模式)由於程式設計的複雜性和比較大的常數因子,所以使用的很少。

下面進入主題leftist tree:

首先看左偏樹的性質:

1.【堆性質】:任意節點的關鍵字大於等於其孩子節點的關鍵字

2.【左偏性質】:定義到最近的孩子的距離為節點距離dist,那麼任意節點的左孩子的距離大於右孩子的距離。

a->lchild->dist >= a->rchild->dist

堆性質是為了讓最小的結點始終在根的位置,這是所有堆都有的性質。

而左偏性質,則是為了讓樹狀儲存的堆,樹的深度不能過大,且利於合併

那麼這個性質是怎麼完成這兩個功能的呢?左偏性質使樹的左側的深度始終大於等於右側的深度,這一點從名字上就能體會到,也可以畫幾棵左偏的樹試試。而左偏樹在實現插入操作時總是從右側插入,也就是總是讓短的一側生長,如果右側長於了左側,那麼把左右側交換一下,繼續從短的一側生長。其實如果不考慮具體的細節,那麼這樣的直觀理解可以看到左偏樹的一些本質內涵,一顆樹有兩個分支,每次要生長的時候,總是讓短的一側先生長,那麼這棵樹,最後是不是就能夠比較對稱呢?自然常識和嚴密的技術邏輯有時候是一致的。

下面給出左偏樹的具體實現(做過簡單測試,但不保證沒有bug。如果發現bug請告知,我會及時修改,謝謝):

/*基本的儲存結構*/

struct ltnode

;/*交換操作,為了方便後面的實現*/

templateinline void swap(t &a,t &b)

/*簡單的中序遍歷操作,方便除錯用的*/

void inorder(ltnode *t)

}/*核心操作,一定要小心實現*/

ltnode* merge(ltnode* &a,ltnode* &b)

a->rchild = merge(a->rchild,b); /*新來個左偏樹始終合併到右側*/

/*由於新結點合併到右側,右側結點現在一定存在了,但左側不一定*/

if(a->lchild==null || /*左側為空,一定小於右側*/

a->rchild->dist > a->lchild->dist)/*右側大於了左側*/

swap(a->lchild,a->rchild);

if(a->rchild==null) /*右子樹為空*/

else

return a;

}void insert(ltnode *&t,int x)

ltnode* extractmin(ltnode* &t)

其實比較複雜和需要一些理解的也就只有merge操作,其實並不比二叉樹實現的二叉堆複雜多少是嗎?

資料結構 可合併堆 左偏樹

剛剛又看了一遍左偏樹的內容,為了加深理解,自己也寫一篇,夾雜著許許多多的借鑑。左偏樹是可合併的二叉堆,首先滿足所有的堆的性質,其外,它還可以合併。左偏樹的樹節點需要儲存的資訊有 1.左右子樹節點編號 2.此節點到有空子結點的結點的最短距離 len 3.自身權值 首先解釋一下什麼是有空子節點的節點,就...

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

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

資料結構 左偏樹

今天學了左偏樹,看了一天,一些細節還是不太明白。有點混亂。做題的時候也不是很明白方法。先來介紹左偏樹 見 資料結構 9 左偏樹 見例題 判斷是否認識,並查集。因為要用到合併,而且輸出最強壯值,二叉堆不能合併,所有要用到能夠合併的資料結構 左偏樹。這題能夠好好理解左偏樹的實現方法。include in...