日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

堆之左式堆和斜堆

發(fā)布時間:2025/3/19 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 堆之左式堆和斜堆 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

d-堆

類似于二叉堆,但是它有d個兒子,此時,d-堆比二叉堆要淺很多,因此插入操作更快了,但是相對的刪除操作更耗時。因為,需要在d個兒子中找到最大的,但是很多算法中插入操作要遠(yuǎn)多于刪除操作,因此,這種加速是現(xiàn)實的。

除了不能執(zhí)行find去查找一般的元素外,兩個堆的合并也很困難。

左式堆

左式堆可以有效的解決上面說的堆合并的問題。合并就涉及插入刪除,很顯然使用數(shù)組不合適,因此,左式堆使用指針來實現(xiàn)。左式堆和二叉堆的區(qū)別:左式堆是不平衡的。它兩個重要屬性:鍵值和零距離

零距離(英文名NPL,即Null Path Length)則是從一個節(jié)點到一個沒有兩個兒子的節(jié)點(只有0個或1個兒子的節(jié)點)的路徑長度。具有0個或1個兒子的節(jié)點的NPL為0,NULL節(jié)點的NPL為-1。

  • 節(jié)點的左孩子的NPL >= 右孩子的NPL。
  • 節(jié)點的NPL = 它的右孩子的NPL + 1。
  • 在有路徑上有r個節(jié)點的左式堆必然至少有2^r - 1個節(jié)點。
typedef int Type;typedef struct _LeftistNode{Type val;int npl; // 零路經(jīng)長度(Null Path Length)struct _LeftistNode *left; // 左孩子struct _LeftistNode *right; // 右孩子 }LeftistNode, *LeftistHeap;

?

合并

合并操作是左傾堆的重點。插入式合并的特殊情況。

合并兩個左傾堆(最小堆)的基本思想如下:

  • 如果一個空左傾堆與一個非空左傾堆合并,返回非空左傾堆。
  • 如果兩個左傾堆都非空,那么比較兩個根節(jié)點,取較小堆的根節(jié)點為新的根節(jié)點。將"較小堆的根節(jié)點的右孩子"和"較大堆"進行合并;該合并過程和上面的過程一樣,這樣遞歸合并下去,最終兩個堆合并完成。 但是新推可能不再滿足左式堆的性質(zhì),需要調(diào)整:(調(diào)整的過程是在合并的同時完成的)
    • 如果新堆的右孩子的NPL > 左孩子的NPL,則交換左右孩子。
    • 設(shè)置新堆的根節(jié)點的NPL = 右子堆NPL + 1

實現(xiàn)時,通過遞歸自底向上合并并調(diào)整使得滿足左式堆的性質(zhì)。

LeftistNode* mergeLeftist(LeftistHeap x, LeftistHeap y){if (x == nullptr)return y;if (y == nullptr)return x;LeftistHeap l, r;//以l為根,l較小if (x->val < y->val){l = x;r = y;}else {l = y;r = x;}l->right = mergeLeftist(l->right,r);//合并l->right和rif (!l->left || l->left->npl < l->right->npl){//判斷是否需要交換左右子樹LeftistHeap temp = l->left;l->left = l->right;l->right = temp;}//更新nplif (!l->right || !l->left)l->npl = 0;else l->npl = l->left->npl > l->right->npl ? l->right->npl + 1 : l->left->npl + 1;return l; }

合并左式堆的操作可以看出來,它的時間復(fù)雜度和有路徑的長成正比,因此復(fù)雜度O(logn)

添加節(jié)點就可以看做是一個左式堆和一個單點的左式堆合并;

刪除樹根節(jié)點可以看做是刪除樹根后,左右子樹的兩個左式堆合并;

因此,他們都可以通過合并來實現(xiàn)。它對應(yīng)的復(fù)雜度也是O(logn)

插入和刪除的實現(xiàn):

?

斜堆

斜堆是左式堆的自調(diào)節(jié)形式,左式堆和斜堆的關(guān)系類似于伸展樹和AVL樹的關(guān)系。斜堆具有堆序的性質(zhì),但是沒有結(jié)構(gòu)的限制,這樣的話一次的操作最壞的情況時O(n),但是連續(xù)m次操作總的復(fù)雜度O(mlogn)。

與左式堆相同,斜堆的基本操作也是合并操作。但是斜堆沒有零距離的屬性,合并的方法也有區(qū)別:

  • 如果一個空斜堆與一個非空斜堆合并,返回非空斜堆。
  • 如果兩個斜堆都非空,那么比較兩個根節(jié)點,取較小堆的根節(jié)點為新的根節(jié)點。將"較小堆的根節(jié)點的右孩子"和"較大堆"進行合并。
  • 合并后,交換新堆根節(jié)點的左孩子和右孩子。
    • 這一步是斜堆和左傾堆的合并操作差別的關(guān)鍵所在,如果是左傾堆,則合并后要比較左右孩子的零距離大小,若右孩子的零距離 > 左孩子的零距離,則交換左右孩子;最后,在設(shè)置根的零距離。

斜堆的結(jié)構(gòu)

typedef int Type;typedef struct _SkewNode{Type val;struct _SkewNode *left; // 左孩子struct _SkewNode *right; // 右孩子 }SkewNode, *SkewHeap;

合并的實現(xiàn)

SkewNode* mergeSkewHeap(SkewHeap x, SkewHeap y){if (x == nullptr)return y;if (y == nullptr)return x;SkewHeap l, r;//以l為根,l較小if (x->val < y->val){l = x;r = y;}else {l = y;r = x;}SkewNode* temp = mergeSkewHeap(l->right, r);//合并l->right和r l->right = l->left;//交換左右子樹l->left = temp;return l; }

同樣的道理,插入和刪除根節(jié)點的操作都可以使用合并來實現(xiàn)。

轉(zhuǎn)載于:https://www.cnblogs.com/yeqluofwupheng/p/7450643.html

總結(jié)

以上是生活随笔為你收集整理的堆之左式堆和斜堆的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。