介紹:
定義:
左式堆(leftist heaps)又稱作最左堆、左傾堆,是
計算機語言
中較為常用的乙個資料結構。左式堆作為堆的一種,保留了堆的一些屬性。第1,左式堆仍然以二叉樹的形式構建;第2,左式堆的任意結點的值比其子樹任意結點值均小(最小堆的特性)。但和一般的二叉堆不同,左式堆不再是一棵完全二叉樹(complete tree),而且是一棵極不平衡的樹。
那麼為什麼要使用左式堆,左式堆同樣是優先佇列,並且實現的時候使用了指標,不支援直接訪問元素。看起來效果與二叉堆相同,並且實現變得複雜了。使用指標,既可以是缺點,同樣也可以是優點。有了指標之後,就可以支援合併操作了。使用左式堆的目的就是為了能夠支援合併優先佇列。
左式堆的特性:
零路徑長:從x到乙個不具有兩個兒子的結點的最短路徑的長。
1. 任一結點的零路徑長比他的諸兒子結點的零路徑長的最小值多1
2. 父節點屬性值小於子節點屬性值;
3. 堆中的任何節點,其左兒子的零路徑長》=右兒子的零路徑長的二叉樹。
左式堆的複雜度
左式堆的操作都是基於合併,而合併僅對右路做合併,而右路結點的數量為總數量的對數關係,所以左式堆的三個操作(合併,刪除,插入)所花的時間為
o(logn).
基本操作:
合併:
左式堆的合併操作基於遞迴完成,演算法如下:
1.如果有一棵樹是空樹,則返回另一棵樹;否則遞迴地合併根結點較小的堆的右子樹和根結點較大的堆。
2.使形成的新堆作為較小堆的右子樹。
3.如果違反了左式堆的特性,交換兩個子樹的位置。
4.更新npl。
刪除最小值/最大值:
刪除操作的做法相當的簡單,刪除左式堆的根節點,合併左右子樹即可。
插入:
將需要插入的節點當做一棵左式堆樹,進行合併即可。
編碼實現:
左式堆定義:
左式堆的實現依賴指標,那麼首先是與基礎的二叉樹相同。因為需要維護npl值,所以每個節點裡需要新增npl。
.h檔案定義如下:
[cpp]view plain
copy
print?
#ifndef _leftist_heap
#define _leftist_heap
struct treenode;
typedef treenode * priorityqueue;
typedef
int elementtype;
priorityqueue merge(priorityqueue h1, priorityqueue h2);
elementtype findmin(priorityqueue h);
int isempty(priorityqueue h);
priorityqueue deletemin(priorityqueue h);
priorityqueue insert(elementtype x, priorityqueue h);
void printtree(priorityqueue t);
void printtree(priorityqueue t, int depth);
void printdepth(elementtype a, int depth);
#endif
struct treenode
;
#ifndef _leftist_heap
#define _leftist_heap
struct treenode;
typedef treenode * priorityqueue;
typedef int elementtype;
priorityqueue merge(priorityqueue h1, priorityqueue h2);
elementtype findmin(priorityqueue h);
int isempty(priorityqueue h);
priorityqueue deletemin(priorityqueue h);
priorityqueue insert(elementtype x, priorityqueue h);
void printtree(priorityqueue t);
void printtree(priorityqueue t, int depth);
void printdepth(elementtype a, int depth);
#endif
struct treenode
;
合併操作:合併操作的基本方式就如上演算法所描述,可以使用遞迴的方式也可以使用非遞迴的方式。在這裡我使用遞迴的方式實現。
[cpp]view plain
copy
print?
priorityqueue merge(priorityqueue h1, priorityqueue h2)
priorityqueue merge1(priorityqueue h1, priorityqueue h2)
return h1;
}
priorityqueue merge(priorityqueue h1, priorityqueue h2)
priorityqueue merge1(priorityqueue h1, priorityqueue h2)
return h1;
}
插入:在優先佇列裡插入是不檢查是否有重複資料的。
[cpp]view plain
copy
print?
/*左式堆插入不檢查是否有重複的資料*/
priorityqueue insert(elementtype x, priorityqueue h)
/*左式堆插入不檢查是否有重複的資料*/
priorityqueue insert(elementtype x, priorityqueue h)
刪除最小值:如上所述,注意檢查是否為空樹即可。
[cpp]view plain
copy
print?
priorityqueue deletemin(priorityqueue h)
priorityqueue deletemin(priorityqueue h)
測試截圖:第一部分是插入0-20資料的左式堆,第二部分是進行了4次刪除最小值的左式堆。
總結:
左式堆的實現還是相當的容易,只有合併操作的地方需要稍微花點功夫理解就行了。在左式堆的基礎上還可以實現斜堆。只需要去除npl值,並且在每次合併之後互動左右孩子即可(不保證左式堆性質)。斜堆的實現與左式堆基本相同,在這裡就不贅述了。
左式堆實現
左式堆是為了方便合併操作實現的。左式堆性質 任意節點x的零路徑長是x到任意沒有兩個兒子的節點的最短路徑。任意乙個節點的零路徑長比他兒子的零路徑長的最大值大1,null的零路徑長是 1 對於x來說,他的左兒子的零路徑長要大於等於右兒子。通過遞迴實現 如下 public class leftisthea...
優先佇列之左式堆 JAVA實現
1.零路徑長度 某節點的零路徑長度為該節點到沒有兩個兒子的節點最短距離。2.左式堆性質 1.合併 左式堆的合併操作基於遞迴實現,演算法思路如下 若有一棵樹是空樹,則返回另一棵樹 否則將根節點較大的堆與根節點較小的堆的右子樹合併。使形成的新堆作為較小堆的右子樹。如果違反了左式堆的特性,交換兩個子樹的位...
左式堆的實現與詳解
定義 左式堆 leftist heaps 又稱作最左堆 左傾堆,是計算機語言中較為常用的乙個資料結構。左式堆作為堆的一種,保留了堆的一些屬性。第1,左式堆仍然以二叉樹的形式構建 第2,左式堆的任意結點的值比其子樹任意結點值均小 最小堆的特性 但和一般的二叉堆不同,左式堆不再是一棵完全二叉樹 comp...