作式堆分析和實現

2021-07-25 05:43:07 字數 3857 閱讀 8013

介紹:

定義:

左式堆(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...