左偏树

首先声明,我的代码基本是照着www.cnblogs.com/skywang12345/p/3638342.html打的,感谢分享。

不过我的疑问是在实现merge时提供的形参为何要加引用,一开始傻乎乎地觉得这样才能真正改动内部指针成员,知道去掉引用run了一把才知道不加引用也能实现合并,加引用除了减少拷贝指针的开销其实没有其他好处了,当然只是我个人的想法,望轻喷。传值调用也能改变内部指针指向的原因是这两条语句,mRoot=rhs->mRoot;x->right=merge(x->right,y);

虽然改变的是局部指针的指向,但由于又进行了一次赋值操作,所以实参pointer也被改变了指向。相当于创建两个局部指针作为实参的拷贝,merge后形成一颗新的左偏树再传给实参。虽然cppprimer还没看到后面,也通过上面的博客大概知道了用法,再表感激。下面贴自己搬运后略微修改的代码:

  1 #include <iomanip>
  2 #include <iostream>
  3 
  4 using namespace std;
  5 
  6 template <class T>
  7 class LeftistNode {
  8 public:
  9     T key;
 10     int npl;
 11     LeftistNode* left;
 12     LeftistNode* right;
 13 
 14     LeftistNode(T value = -1, LeftistNode* l = 0, LeftistNode* r = 0) ://key值默认为-1
 15         key(value), left(l), right(r), npl(0) {}
 16 };
 17 
 18 template <class T>
 19 class LeftistHeap {
 20 private:
 21     LeftistNode<T> *mRoot;
 22 public:
 23     //构造函数
 24     LeftistHeap() :mRoot(0) {}
 25     ~LeftistHeap();//析构函数
 26 
 27     void preOrder();//前序遍历“左倾堆”
 28 
 29     void merge(LeftistHeap<T>* other);//将自己与other堆合并
 30     void insert(T key);
 31     void remove();//只支持删除堆顶
 32     void destroy();
 33     // 打印左倾堆
 34     void print();
 35 
 36 private:
 37     void preOrder(LeftistNode<T>* heap)const;
 38     //如果不解引用指针与其他类型的swap无区别
 39     void swapNode(LeftistNode<T>* &x, LeftistNode<T>* &y);
 40     LeftistNode<T>* merge(LeftistNode<T>* x, LeftistNode<T>* y);
 41     LeftistNode<T>* insert(LeftistNode<T>* heap, T key);
 42     LeftistNode<T>* remove(LeftistNode<T>* heap);
 43 
 44     void destroy(LeftistNode<T>* heap);
 45     // 打印左倾堆
 46     void print(LeftistNode<T>* heap, T key, int direction);
 47 };
 48 
 49 template<class T>
 50 LeftistHeap<T>::~LeftistHeap() { destroy(); }
 51 
 52 template<class T>
 53 void LeftistHeap<T>::preOrder(LeftistNode<T>* heap)const {
 54     if (heap) {
 55         cout << heap->key << endl;
 56         preOrder(heap->left);
 57         preOrder(heap->right);
 58     }
 59 }
 60 
 61 template<class T>
 62 void LeftistHeap<T>::preOrder() {
 63     preOrder(mRoot);
 64 }
 65 
 66 template<class T>
 67 void LeftistHeap<T>::swapNode(LeftistNode<T>* &x, LeftistNode<T>* &y) {
 68     LeftistNode<T>* tmp = x;
 69     x = y;
 70     y = tmp;
 71 }
 72 
 73 template <class T>
 74 LeftistNode<T>* LeftistHeap<T>::merge(LeftistNode<T>* x, LeftistNode<T>* y) {
 75     if (x == NULL)return y;
 76     if (y == NULL)return x;
 77 
 78     if (x->key > y->key)swapNode(x, y);
 79     x->right = merge(x->right, y);
 80 
 81     if (x->left == 0 || x->left->npl < x->right->npl)swapNode(x->left, x->right);//保证左偏
 82 
 83     if (x->right == 0)x->npl = 0;
 84     else x->npl = x->right->npl + 1;
 85 
 86     return x;
 87 }
 88 
 89 template<class T>
 90 void LeftistHeap<T>::merge(LeftistHeap<T>*rhs) {
 91     mRoot = merge(mRoot, rhs->mRoot);//
 92 }
 93 
 94 template<class T>
 95 LeftistNode<T>* LeftistHeap<T>::insert(LeftistNode<T>* heap, T key) {
 96     LeftistNode<T>* node = new LeftistNode<T>(key, 0, 0);
 97     if (node == 0) {
 98         cout << "create node failed!" << endl;
 99         return heap;
100     }
101 
102     return merge(heap, node);
103 }
104 
105 template <class T>
106 void LeftistHeap<T>::insert(T key) {
107     mRoot = insert(mRoot, key);
108 }
109 
110 template<class T>
111 LeftistNode<T>* LeftistHeap<T>::remove(LeftistNode<T>* heap) {
112     LeftistNode<T>* l = heap->left;
113     LeftistNode<T>* r = heap->right;
114 
115     delete heap;
116     //heap = 0;//置空
117     return merge(l, r);
118 }
119 
120 template<class T>
121 void LeftistHeap<T>::remove() { mRoot = remove(mRoot); }
122 
123 template<class T>
124 void LeftistHeap<T>::destroy(LeftistNode<T>* heap) {
125     if (heap == 0)return;
126 
127     destroy(heap->left);
128     destroy(heap->right);
129 
130     delete heap;
131 }
132 
133 template <class T>
134 void LeftistHeap<T>::print(LeftistNode<T>* heap, T key, int direction)
135 {
136     if (heap != NULL)
137     {
138         if (direction == 0)    // heap是根节点
139             cout << setw(2) << heap->key << "(" << heap->npl << ") is root" << endl;
140         else                // heap是分支节点
141             cout << setw(2) << heap->key << "(" << heap->npl << ") is " << setw(2) << key << "'s " << setw(12) << (direction == 1 ? "right child" : "left child") << endl;
142 
143         print(heap->left, heap->key, -1);
144         print(heap->right, heap->key, 1);
145     }
146 }
147 
148 template <class T>
149 void LeftistHeap<T>::print()
150 {
151     if (mRoot != NULL)
152         print(mRoot, mRoot->key, 0);
153 }
154 
155 
156 template<class T>
157 void LeftistHeap<T>::destroy() { destroy(mRoot); }
158 
159 int main(void) {
160     int i;
161     int a[] = { 10,40,24,30,36,20,12,16 };
162     int b[] = { 17,13,11,15,19,21,23 };
163     int alen = sizeof(a) / sizeof(a[0]);
164     int blen = sizeof(b) / sizeof(b[0]);
165     LeftistHeap<int>* ha = new LeftistHeap<int>();
166     LeftistHeap<int>* hb = new LeftistHeap<int>();
167 
168     cout << "== 左倾堆(ha)中依次添加: ";
169     for (i = 0; i<alen; i++)
170     {
171         cout << a[i] << " ";
172         ha->insert(a[i]);
173     }
174     cout << "
== 左倾堆(ha)的详细信息: " << endl;
175     ha->print();
176 
177 
178     cout << "
== 左倾堆(hb)中依次添加: ";
179     for (i = 0; i<blen; i++)
180     {
181         cout << b[i] << " ";
182         hb->insert(b[i]);
183     }
184     cout << "
== 左倾堆(hb)的详细信息: " << endl;
185     hb->print();
186 
187 
188     // 将"左倾堆hb"合并到"左倾堆ha"中。
189     ha->merge(hb);
190     cout << "
== 合并ha和hb后的详细信息: " << endl;
191     ha->print();
192 
193 
194     // 销毁
195     ha->destroy();
196 
197     return 0;
198 
199 }
原文地址:https://www.cnblogs.com/schsb/p/8595071.html