左式堆的合併

2021-07-28 05:20:58 字數 1459 閱讀 1394

二叉堆對於合併操作是困難的,因為需要把乙個陣列拷貝到另乙個陣列。

左式堆可以高效的地支援合併操作, 左式堆與二叉樹之間唯一區別是,左式堆不是平衡的,可能非常趨向不平衡。

// 左式堆的結構

typedef

struct treenode leftistheap;

任一節點x的零路徑長npl(x)定義為從x到乙個沒有兩個兒子的節點的最短路徑。

左式堆的性質:對於堆中每乙個節點x,左兒子的零路徑長至少與右兒子的零路徑長一樣大,即

x->left->npl >= x->right->npl;
可以這樣理解

// 求npl

int npl(leftistheap x)

有乙個左式樹的定理

在右路徑上有r個節點的左式樹必然有 2r

−1個節點

首先右路徑是這棵樹的最右邊的那一條路徑(不是右子樹的節點,摔,在這裡犯混了),我們用遞迴的思想去驗證,

考慮最右邊的節點,根據性質一棵樹的右節點必定有左節點與之匹配,所以這棵樹至少有r個(可能左兄弟還有左兒子)左兒子,

所以樹上至少有 2r

−1個節點。

現在開始思考左式堆的合併操作了,那麼肯定就要用到它的性質

x->left->npl >= x->right->npl;

根據上面的定理,乙個含有n個節點的左式樹有一條右路徑至多含有 lo

g(n+

1)個節點,這樣可以確保樹的右路徑的長度,所以對每次合併操作都是對樹的右節點進行操作,朝著右路徑進行,總結起來就是兩棵樹先從樹根開始比較,值更大的節點成為值更小的節點的右兒子,同時滿足小根堆的特點(兒子比父節點的值更大,反之則反),終止條件是一棵樹到達了兩棵樹的右路徑的最後乙個節點,中間過程有左兒子npl小於右兒子npl的時候,交換左右兒子。

// 合併左式堆的驅動例程(就是控制該把哪棵樹合併到另外一棵樹下)

leftistheap merge(leftistheap h1, leftistheap h2)

// 合併的實際例程

static leftistheap merge(leftistheap h1, leftistheap h2)

return h1;

}

左式堆的插入操作為建立乙個節點即只有乙個根節點的樹與需要插入的樹進行merge操作。

刪除操作,最小(大)的元素處在樹根的位置,只需要把根節點刪除就可以,然後對左右子樹進行merge操作。

// 前幾天看到網上的很多部落格都乙個樣子,定下心來自己理解後,寫下這篇部落格, 沒有把所有**都貼上來,把主要的思想和部分**寫在這裡。

左式堆實現

左式堆是為了方便合併操作實現的。左式堆性質 任意節點x的零路徑長是x到任意沒有兩個兒子的節點的最短路徑。任意乙個節點的零路徑長比他兒子的零路徑長的最大值大1,null的零路徑長是 1 對於x來說,他的左兒子的零路徑長要大於等於右兒子。通過遞迴實現 如下 public class leftisthea...

左式堆的實現與詳解

定義 左式堆 leftist heaps 又稱作最左堆 左傾堆,是計算機語言中較為常用的乙個資料結構。左式堆作為堆的一種,保留了堆的一些屬性。第1,左式堆仍然以二叉樹的形式構建 第2,左式堆的任意結點的值比其子樹任意結點值均小 最小堆的特性 但和一般的二叉堆不同,左式堆不再是一棵完全二叉樹 comp...

資料結構 左式堆

左式堆 同二叉堆一樣具有結構性和堆序性。惟一的區別是 左式堆不是理想平衡的,而實際上是趨於不平衡的。零路徑長 npl x 從節點x到乙個沒有兩個兒子節點的最短路徑長。左式堆要求對於堆中的每乙個節點x,左兒子的零路徑長至少與右兒子的零路徑長一樣大。左式堆的結構宣告 struct treenode ty...