11、【堆】斜堆
阿新 • • 發佈:2018-10-14
print str template new oid 以及 roo cout 當前
一、斜堆的介紹
斜堆(Skew heap)也叫自適應堆(self-adjusting heap),它是左傾堆的一個變種。和左傾堆一樣,它通常也用於實現優先隊列。它的合並操作的時間復雜度也是O(lg n)。
相比於左傾堆,斜堆的節點沒有"零距離"這個屬性。除此之外,它們斜堆的合並操作也不同。斜堆的合並操作算法如下:
(1) 如果一個空斜堆與一個非空斜堆合並,返回非空斜堆。
(2) 如果兩個斜堆都非空,那麽比較兩個根節點,取較小堆的根節點為新的根節點。將"較小堆的根節點的右孩子"和"較大堆"進行合並。
(3) 合並後,交換新堆根節點的左孩子和右孩子。
第(03)步是斜堆和左傾堆的合並操作差別的關鍵所在,如果是左傾堆,則合並後要比較左右孩子的零距離大小,若右孩子的零距離 > 左孩子的零距離,則交換左右孩子;最後,在設置根的零距離。
二、斜堆的解析
1. 基本定義
1 template <class T> 2 class SkewNode{ 3 public: 4 T key; // 關鍵字(鍵值) 5 SkewNode *left; // 左孩子 6 SkewNode *right; // 右孩子 7 8 SkewNode(T value, SkewNode *l, SkewNode *r): 9 key(value), left(l),right(r) {}10 };
SkewNode是斜堆對應的節點類。
1 template <class T> 2 class SkewHeap { 3 private: 4 SkewNode<T> *mRoot; // 根結點 5 6 public: 7 SkewHeap(); 8 ~SkewHeap(); 9 10 // 前序遍歷"斜堆" 11 void preOrder(); 12 // 中序遍歷"斜堆" 13 void inOrder();14 // 後序遍歷"斜堆" 15 void postOrder(); 16 17 // 將other的斜堆合並到this中。 18 void merge(SkewHeap<T>* other); 19 // 將結點(key為節點鍵值)插入到斜堆中 20 void insert(T key); 21 // 刪除結點(key為節點鍵值) 22 void remove(); 23 24 // 銷毀斜堆 25 void destroy(); 26 27 // 打印斜堆 28 void print(); 29 private: 30 31 // 前序遍歷"斜堆" 32 void preOrder(SkewNode<T>* heap) const; 33 // 中序遍歷"斜堆" 34 void inOrder(SkewNode<T>* heap) const; 35 // 後序遍歷"斜堆" 36 void postOrder(SkewNode<T>* heap) const; 37 38 // 交換節點x和節點y 39 void swapNode(SkewNode<T> *&x, SkewNode<T> *&y); 40 // 合並"斜堆x"和"斜堆y" 41 SkewNode<T>* merge(SkewNode<T>* &x, SkewNode<T>* &y); 42 43 // 銷毀斜堆 44 void destroy(SkewNode<T>* &heap); 45 46 // 打印斜堆 47 void print(SkewNode<T>* heap, T key, int direction); 48 };
SkewHeap是斜堆類,它包含了斜堆的根節點,以及斜堆的操作。
2. 合並
1 /* 2 * 合並"斜堆x"和"斜堆y" 3 */ 4 template <class T> 5 SkewNode<T>* SkewHeap<T>::merge(SkewNode<T>* &x, SkewNode<T>* &y) 6 { 7 if(x == NULL) 8 return y; 9 if(y == NULL) 10 return x; 11 12 // 合並x和y時,將x作為合並後的樹的根; 13 // 這裏的操作是保證: x的key < y的key 14 if(x->key > y->key) 15 swapNode(x, y); 16 17 // 將x的右孩子和y合並, 18 // 合並後直接交換x的左右孩子,而不需要像左傾堆一樣考慮它們的npl。 19 SkewNode<T> *tmp = merge(x->right, y); 20 x->right = x->left; 21 x->left = tmp; 22 23 return x; 24 } 25 26 /* 27 * 將other的斜堆合並到this中。 28 */ 29 template <class T> 30 void SkewHeap<T>::merge(SkewHeap<T>* other) 31 { 32 mRoot = merge(mRoot, other->mRoot); 33 }
merge(x, y)是內部接口,作用是合並x和y這兩個斜堆,並返回得到的新堆的根節點。
merge(other)是外部接口,作用是將other合並到當前堆中
3. 添加
1 /* 2 * 新建鍵值為key的結點並將其插入到斜堆中 3 * 4 * 參數說明: 5 * heap 斜堆的根結點 6 * key 插入的結點的鍵值 7 * 返回值: 8 * 根節點 9 */ 10 template <class T> 11 void SkewHeap<T>::insert(T key) 12 { 13 SkewNode<T> *node; // 新建結點 14 15 // 新建節點 16 node = new SkewNode<T>(key, NULL, NULL); 17 if (node==NULL) 18 { 19 cout << "ERROR: create node failed!" << endl; 20 return ; 21 } 22 23 mRoot = merge(mRoot, node); 24 }
insert(key)的作用是新建鍵值為key的節點,並將其加入到當前斜堆中。
4. 刪除
1 /* 2 * 刪除結點 3 */ 4 template <class T> 5 void SkewHeap<T>::remove() 6 { 7 if (mRoot == NULL) 8 return NULL; 9 10 SkewNode<T> *l = mRoot->left; 11 SkewNode<T> *r = mRoot->right; 12 13 // 刪除根節點 14 delete mRoot; 15 // 左右子樹合並後的新樹 16 mRoot = merge(l, r); 17 }
remove()的作用是刪除斜堆的最小節點。
11、【堆】斜堆