標籤:中序遍曆 nbsp 關鍵字 erro 設定 new col remove 解析
一、斜堆的介紹
斜堆(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和節點y39 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的key14 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、【堆】斜堆