• 左偏树


    首先声明,我的代码基本是照着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 }
  • 相关阅读:
    常用字段类型
    触发事件中的sender
    $符号基本用法$() ${} $(())
    expect语法
    apt 和 apt-get的区别
    python字符串中 r'', b'', u'', f'' 的含义
    linux正则表达式
    Linux下apt-get命令详解(安装、卸载、更新、查询软件包)
    创建linux service服务
    Ubuntu下deb包的解包、打包
  • 原文地址:https://www.cnblogs.com/schsb/p/8595071.html
Copyright © 2020-2023  润新知