首先声明,我的代码基本是照着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 }