定義:左式堆(Leftist Heaps)又稱作最左堆、左傾堆,是計算機語言中較為常用的一個數據結構。左式堆作為堆的一種,保留了堆的一些屬性。第1,左式堆仍然以二叉樹的形式構建;第2,左式堆的任意結點的值比其子樹任意結點值均小(最小堆的特性)。但和一般的二叉堆不同,左式堆不再是一棵完全二叉樹(Complete tree),而且是一棵極不平衡的樹。
性質:
零路徑長:從X到一個不具有兩個兒子的結點的最短路徑的長。
1. 任一結點的零路徑長比他的諸兒子結點的零路徑長的最小值多1
2. 父節點屬性值小於子節點屬性值;
3. 堆中的任何節點,其左兒子的零路徑長>=右兒子的零路徑長的二叉樹。
操作:
左式堆的操作都是基於合並,而合並僅對右路做合並,而右路結點的數量為總數量的對數關系,所以左式堆的三個操作(合並,刪除,插入)所花的時間為O(logN).
左式堆的合並操作基於遞歸完成,算法如下:
1.如果有一棵樹是空樹,則返回另一棵樹;否則遞歸地合並根結點較小的堆的右子樹和根結點較大的堆。
2.使形成的新堆作為較小堆的右子樹。
3.如果違反了左式堆的特性,交換兩個子樹的位置。
4.更新Npl。
刪除最小值/最大值:
刪除操作的做法相當的簡單,刪除左式堆的根節點,合並左右子樹即可。
插入:將需要插入的節點當做一棵左式堆樹,進行合並即可。
下面給出左式堆的c++類模板實現
1 #include <iostream> 2 using namespace std; 3 4 template <typename Comparable> 5 class LeftistHeap 6 { 7 public: 8 LeftistHeap() :root(NULL){} 9 LeftistHeap(const LeftistHeap &rhs) 10 { 11 *this = rhs; 12 } 13 ~LeftistHeap() 14 { 15 MakeEmpty(); 16 } 17 18 bool IsEmpty() const; 19 const Comparable &FindMin() const; 20 21 void Insert(const Comparable &x); 22 void DeleteMin(); 23 void DeleteMin(Comparable &minItem); 24 void MakeEmpty(); 25 void Merge(LeftistHeap &rhs); 26 27 const LeftistHeap &operator=(const LeftistHeap &rhs); 28 29 private: 30 struct LeftistNode 31 { 32 Comparable element; 33 LeftistNode *left; 34 LeftistNode *right; 35 int npl; 36 37 LeftistNode(const Comparable &theElement, LeftistNode *lt = NULL, LeftistNode *rt = NULL, int np = 0) : 38 element(theElement), left(lt), right(rt), npl(np){} 39 }; 40 LeftistNode *root; 41 42 LeftistNode *Merge(LeftistNode *h1, LeftistNode *h2); 43 LeftistNode *Merge1(LeftistNode *h1, LeftistNode *h2); 44 45 void SwapChildren(LeftistNode *t); 46 void ReclaimMemory(LeftistNode *t); 47 LeftistNode *Clone(LeftistNode *t) const 48 { 49 if (t == NULL) 50 return NULL; 51 else 52 return new LeftistNode(t->element, clone(t->left), clone(t->right)); 53 } 54 55 }; 56 57 58 59 template <typename Comparable> 60 bool LeftistHeap<Comparable>::IsEmpty() const 61 { 62 return root == NULL; 63 } 64 65 template <typename Comparable> 66 void LeftistHeap<Comparable>::Insert(const Comparable &x) 67 { 68 root = Merge(new LeftistNode(x), root); 69 } 70 71 template <typename Comparable> 72 void LeftistHeap<Comparable>::Merge(LeftistHeap &rhs) 73 { 74 if (this == &rhs)//避免和自己合並 75 return; 76 root = Merge(root, rhs.root); 77 rhs.root = NULL; 78 } 79 80 template <typename Comparable> 81 void LeftistHeap<Comparable>::SwapChildren(LeftistNode *t) 82 { 83 LeftistNode *tmp = t->left; 84 t->left = t->right; 85 t->right = tmp; 86 } 87 88 template <typename Comparable> 89 typename LeftistHeap<Comparable>::LeftistNode *LeftistHeap<Comparable>::Merge1(LeftistNode *h1, LeftistNode *h2) 90 { 91 if (h1->left == NULL) 92 h1->left = h2; 93 else 94 { 95 h1->right = Merge(h1->right, h2); 96 if (h1->left->npl < h1->right->npl) 97 SwapChildren(h1); 98 h1->npl = h1->right->npl + 1; 99 } 100 return h1; 101 } 102 103 template <typename Comparable> 104 typename LeftistHeap<Comparable>::LeftistNode *LeftistHeap<Comparable>::Merge(LeftistNode *h1, LeftistNode *h2) 105 { 106 if (h1 == NULL) 107 return h2; 108 if (h2 == NULL) 109 return h1; 110 if (h1->element < h2->element) 111 return Merge1(h1, h2); 112 else 113 return Merge1(h2, h1); 114 } 115 116 117 118 119 120 template <typename Comparable> 121 void LeftistHeap<Comparable>::DeleteMin() 122 { 123 if (IsEmpty()) 124 return; 125 LeftistNode *oldRoot = root; 126 root = Merge(root->left, root->right); 127 delete oldRoot; 128 } 129 130 131 template <typename Comparable> 132 void LeftistHeap<Comparable>::DeleteMin(Comparable &minItem) 133 { 134 minItem = FindMin(); 135 DeleteMin(); 136 } 137 138 template <typename Comparable> 139 const Comparable & LeftistHeap<Comparable>::FindMin() const 140 { 141 if (!IsEmpty()) 142 return root->element; 143 } 144 145 146 template <typename Comparable> 147 void LeftistHeap<Comparable>::ReclaimMemory(LeftistNode *t) 148 { 149 if (t != NULL) 150 { 151 ReclaimMemory(t->left); 152 ReclaimMemory(t->right); 153 delete t; 154 } 155 } 156 157 158 template <typename Comparable> 159 void LeftistHeap<Comparable>::MakeEmpty() 160 { 161 ReclaimMemory(root); 162 root = NULL; 163 }
1 #include "LeftistHeap.h" 2 3 4 int main() 5 { 6 LeftistHeap<int> leftistHeap1, leftistHeap2; 7 int m, n, num; 8 cin >> m; 9 for (int i = 0; i < m; ++i) 10 { 11 cin >> num; 12 leftistHeap1.Insert(num); 13 } 14 15 cin >> n; 16 for (int i = 0; i < n; ++i) 17 { 18 cin >> num; 19 leftistHeap2.Insert(num); 20 } 21 22 leftistHeap1.Merge(leftistHeap2); 23 cout << "min num is " << leftistHeap1.FindMin() << endl; 24 if (leftistHeap1.IsEmpty()) 25 { 26 cout << "leftistHeap1 is Empty!" << endl; 27 } 28 else 29 { 30 cout << "leftistHeap1 is not empty!" << endl; 31 } 32 33 int t; 34 while (leftistHeap1.IsEmpty() == false) 35 { 36 leftistHeap1.DeleteMin(t); 37 cout << t << " "; 38 } 39 cout << endl; 40 if (leftistHeap1.IsEmpty()) 41 { 42 cout << "leftistHeap1 is empty!" << endl; 43 } 44 else 45 { 46 cout << "leftistHeap1 is not empty!" << endl; 47 } 48 49 }