• 第六十九课 二叉树的线索化实现


    在工程中,很多时候二叉树一旦建立就不会轻易改动,这样的二叉树就用于遍历,我们讲了先序遍历、中序遍历、后续遍历三种方式,都是递归完成的,在工程中,如果对一棵二叉树反复的执行遍历,效率很低,递归的效率是比较低的。

    改进的做法就是将遍历的结果保存下来,下一次遍历时直接用这个结果。

    在工程中另一种需求就是,在中序遍历下,需要知道某一个节点的前驱是谁,后继是谁,需要这三个节点来判断是否执行后续的操作。这个时候又需要遍历了。每次都递归的进行遍历,效率太低了。

    为了效率,我们使用线索化二叉树的方法,将二叉树转换为一个线性结构,这样效率就高了。

     

     

    初始准备两个队列,tmp队列用于层次遍历,出队的时候将元素放到queue中,queue队列负责线索化。

    新添加层次遍历函数的流程如下:

     添加层次遍历函数:

     1 void levelOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
     2     {
     3         if( node != NULL )
     4         {
     5             LinkQueue<BTreeNode<T>*> tmp;
     6 
     7             tmp.add(node);
     8 
     9             while( tmp.length() > 0 )
    10             {
    11                 BTreeNode<T>* n = tmp.front();
    12 
    13                 if( n->left != NULL )
    14                 {
    15                     tmp.add(n->left);
    16                 }
    17 
    18                 if( n->right != NULL )
    19                 {
    20                     tmp.add(n->right);
    21                 }
    22 
    23                 tmp.remove();
    24                 queue.add(n);
    25             }
    26         }
    27     }

     添加连接操作和线索化操作:

      1 #ifndef BTREE_H
      2 #define BTREE_H
      3 
      4 #include "Tree.h"
      5 #include "BTreeNode.h"
      6 #include "Exception.h"
      7 #include "LinkQueue.h"
      8 #include "DynamicArray.h"
      9 
     10 
     11 namespace DTLib
     12 {
     13 
     14 enum BTTraversal
     15 {
     16     PreOrder,
     17     InOrder,
     18     PostOrder,
     19     LevelOrder
     20 };
     21 
     22 template < typename T >
     23 class BTree : public Tree<T>
     24 {
     25 protected:
     26     LinkQueue<BTreeNode<T>*> m_queue;
     27     //定义递归功能函数
     28     virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
     29     {
     30         BTreeNode<T>* ret = NULL;
     31 
     32         if( node != NULL )
     33         {
     34             if( node->value == value )
     35             {
     36                 ret = node;
     37             }
     38             else
     39             {
     40                 if( ret == NULL )
     41                 {
     42                     ret = find(node->left, value);
     43                 }
     44 
     45                 if( ret == NULL )
     46                 {
     47                     ret = find(node->right, value);
     48                 }
     49             }
     50         }
     51 
     52         return ret;
     53     }
     54 
     55     virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
     56     {
     57         BTreeNode<T>* ret = NULL;
     58 
     59         if( node == obj )
     60         {
     61             ret = node;
     62         }
     63         else
     64         {
     65             if( node != NULL )
     66             {
     67                 if( ret == NULL )
     68                 {
     69                     ret = find(node->left, obj);
     70                 }
     71 
     72                 if( ret == NULL )
     73                 {
     74                     ret = find(node->right, obj);
     75                 }
     76             }
     77         }
     78 
     79         return ret;
     80     }
     81 
     82     virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
     83     {
     84         bool ret = true;
     85 
     86         if( pos == ANY )
     87         {
     88             if( np->left == NULL )
     89             {
     90                 np->left = n;
     91             }
     92             else if( np->right == NULL )
     93             {
     94                 np->right = n;
     95             }
     96             else
     97             {
     98                 ret = false;
     99             }
    100         }
    101         else if( pos == LEFT )
    102         {
    103             if( np->left == NULL )
    104             {
    105                 np->left = n;
    106             }
    107             else
    108             {
    109                 ret = false;
    110             }
    111         }
    112         else if( pos == RIGHT )
    113         {
    114             if( np->right == NULL )
    115             {
    116                 np->right = n;
    117             }
    118             else
    119             {
    120                 ret = false;
    121             }
    122         }
    123         else
    124         {
    125             ret = false;
    126         }
    127 
    128         return ret;
    129     }
    130 
    131     virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
    132     {
    133         ret = new BTree<T>();
    134 
    135         if( ret == NULL )
    136         {
    137             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create btree...");
    138         }
    139         else
    140         {
    141             if( root() == node )
    142             {
    143                 this->m_root = NULL;
    144             }
    145             else
    146             {
    147                 BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
    148 
    149                 if( parent->left == node )
    150                 {
    151                     parent->left = NULL;
    152                 }
    153                 else if( parent->right == node )
    154                 {
    155                     parent->right = NULL;
    156                 }
    157 
    158                 node->parent = NULL;
    159             }
    160 
    161             ret->m_root = node;  //作为子树返回
    162         }
    163     }
    164 
    165     virtual void free(BTreeNode<T>* node)
    166     {
    167         if( node != NULL )
    168         {
    169             free(node->left);
    170             free(node->right);
    171 
    172             if( node->flag() )
    173             {
    174                 delete node;
    175             }
    176         }
    177     }
    178     #if 0
    179     int count(BTreeNode<T>* node) const
    180     {
    181         int ret = 0;
    182 
    183         if( node != NULL )
    184         {
    185             ret = count(node->left) + count(node->right) + 1;
    186         }
    187 
    188         return ret;
    189     }
    190     #endif
    191 
    192     int count(BTreeNode<T>* node) const
    193     {
    194         return (node != NULL) ? (count(node->left) + count(node->right) + 1) : 0;
    195     }
    196 
    197     int height(BTreeNode<T>* node) const
    198     {
    199         int ret = 0;
    200 
    201         if( node != NULL )
    202         {
    203             int lh = height(node->left);
    204             int rh = height(node->right);
    205 
    206             ret = ((lh > rh) ? lh : rh) + 1;;
    207         }
    208 
    209         return ret;
    210     }
    211 
    212 #if 0
    213     int degree(BTreeNode<T>* node) const
    214     {
    215         int ret = 0;
    216 
    217         if( node != NULL )
    218         {
    219             int dl = degree(node->left);
    220             int dr = degree(node->right);
    221 
    222             ret = (!!node->left + !!node->right);
    223 
    224             if( ret < dl )
    225             {
    226                 ret = dl;
    227             }
    228 
    229             if( ret < dr )
    230             {
    231                 ret = dr;
    232             }
    233         }
    234 
    235         return ret;
    236     }
    237 #endif
    238 //二叉树的最大度数为2,上面的实现效率太低
    239     int degree(BTreeNode<T>* node) const
    240     {
    241         int ret = 0;
    242 
    243         if( node != NULL )
    244         {
    245             BTreeNode<T>* child[] = {node->left, node->right};
    246 
    247             ret = (!!node->left + !!node->right);
    248 
    249             for( int i = 0; (i < 2) && (ret < 2); i++)
    250             {
    251                 int d = degree(child[i]);
    252 
    253                 if( ret < d )
    254                 {
    255                     ret = d;
    256                 }
    257             }
    258         }
    259 
    260         return ret;
    261     }
    262 
    263     void preOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
    264     {
    265         if( node != NULL )
    266         {
    267             queue.add(node);
    268             preOrderTraversal(node->left, queue);
    269             preOrderTraversal(node->right, queue);
    270         }
    271     }
    272 
    273     void inOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
    274     {
    275         if( node != NULL )
    276         {
    277             inOrderTraversal(node->left, queue);
    278             queue.add(node);
    279             inOrderTraversal(node->right, queue);
    280         }
    281     }
    282 
    283     void postOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
    284     {
    285         if( node != NULL )
    286         {
    287             postOrderTraversal(node->left, queue);
    288             postOrderTraversal(node->right, queue);
    289             queue.add(node);
    290         }
    291     }
    292 
    293     void levelOrderTraversal(BTreeNode<T>* node, LinkQueue<BTreeNode<T>*>& queue)
    294     {
    295         if( node != NULL )
    296         {
    297             LinkQueue<BTreeNode<T>*> tmp;
    298 
    299             tmp.add(node);
    300 
    301             while( tmp.length() > 0 )
    302             {
    303                 BTreeNode<T>* n = tmp.front();
    304 
    305                 if( n->left != NULL )
    306                 {
    307                     tmp.add(n->left);
    308                 }
    309 
    310                 if( n->right != NULL )
    311                 {
    312                     tmp.add(n->right);
    313                 }
    314 
    315                 tmp.remove();
    316                 queue.add(n);
    317             }
    318         }
    319     }
    320 
    321     BTreeNode<T>* clone(BTreeNode<T>* node) const
    322     {
    323         BTreeNode<T>* ret = NULL;
    324 
    325         if( node != NULL )
    326         {
    327             ret = BTreeNode<T>::NewNode();
    328 
    329             if( ret != NULL )
    330             {
    331                 ret->value = node->value;
    332 
    333                 ret->left = clone(node->left);
    334                 ret->right = clone(node->right);
    335 
    336                 if( ret->left != NULL )
    337                 {
    338                     ret->left->parent = ret;
    339                 }
    340 
    341                 if( ret->right != NULL )
    342                 {
    343                     ret->right->parent = ret;
    344                 }
    345             }
    346             else
    347             {
    348                 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node...");
    349             }
    350         }
    351 
    352         return ret;
    353     }
    354 
    355     bool equal(BTreeNode<T>* lh, BTreeNode<T>* rh) const
    356     {
    357         if( lh == rh )
    358         {
    359             return true;
    360         }
    361         else if( (lh != NULL) && (rh != NULL) )
    362         {
    363             return (lh->value == rh->value) && equal(lh->left, rh->left) && equal(lh->right, rh->right);
    364         }
    365         else
    366         {
    367             return false;
    368         }
    369     }
    370 
    371     BTreeNode<T>* add(BTreeNode<T>* lh, BTreeNode<T>* rh) const
    372     {
    373         BTreeNode<T>* ret = NULL;
    374 
    375         if( (lh == NULL) && (rh != NULL) )
    376         {
    377             ret = clone(rh);
    378         }
    379         else if( (lh != NULL) && (rh == NULL) )
    380         {
    381             ret = clone(lh);
    382         }
    383         else if( (lh != NULL) && (rh != NULL) )
    384         {
    385             ret = BTreeNode<T>::NewNode();
    386 
    387             if( ret != NULL )
    388             {
    389                 ret->value = lh->value + rh->value;
    390 
    391                 ret->left = add(lh->left, rh->left);
    392                 ret->right = add(lh->right, rh->right);
    393 
    394                 if( ret->left != NULL )
    395                 {
    396                     ret->left->parent = ret;
    397                 }
    398 
    399                 if( ret->right != NULL )
    400                 {
    401                     ret->right->parent = ret;
    402                 }
    403             }
    404             else
    405             {
    406                 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create tree...");
    407             }
    408         }
    409 
    410         return ret;
    411     }
    412 
    413     //重载一个traversal函数
    414     void traversal(BTTraversal order, LinkQueue< BTreeNode<T>*>& queue)
    415     {
    416         switch( order )
    417         {
    418             case PreOrder:
    419                 preOrderTraversal(root(), queue);
    420                 break;
    421             case InOrder:
    422                 inOrderTraversal(root(), queue);
    423                 break;
    424             case PostOrder:
    425                 postOrderTraversal(root(), queue);
    426                 break;
    427             case LevelOrder:
    428                 levelOrderTraversal(root(), queue);
    429                 break;
    430             default:
    431                 THROW_EXCEPTION(InvalidParameterException, "parameter is invalid...");
    432                 break;
    433         }
    434     }
    435 
    436     BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)
    437     {
    438         BTreeNode<T>* ret = NULL;
    439 
    440         if( queue.length() > 0 )
    441         {
    442             ret = queue.front();
    443 
    444             BTreeNode<T>* slider = queue.front();
    445 
    446             queue.remove();
    447 
    448             slider->left = NULL;
    449 
    450             while( queue.length() > 0 )
    451             {
    452                 slider->right = queue.front();
    453                 queue.front()->left = slider;
    454 
    455                 slider = queue.front();
    456                 queue.remove();
    457             }
    458 
    459             slider->right = NULL;
    460         }
    461 
    462         return ret;
    463     }
    464 public:
    465     bool insert(TreeNode<T>* node)
    466     {
    467         return insert(node, ANY);
    468     }
    469 
    470     virtual bool insert(TreeNode<T>* node, BTNodePos pos)
    471     {
    472         bool ret = true;
    473 
    474         if( node != NULL )
    475         {
    476             if( this->m_root == NULL )  //空树
    477             {
    478                 node->parent = NULL;
    479                 this->m_root = node;
    480             }
    481             else
    482             {
    483                 BTreeNode<T>* np = find(node->parent);
    484 
    485                 if( np != NULL )
    486                 {
    487                     ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
    488                 }
    489                 else
    490                 {
    491                     THROW_EXCEPTION(InvalidParameterException, "invalid parent tree node...");
    492                 }
    493             }
    494         }
    495         else
    496         {
    497             THROW_EXCEPTION(InvalidParameterException, "parameter node can not be null...");
    498         }
    499 
    500         return ret;
    501     }
    502 
    503     bool insert(const T& value, TreeNode<T>* parent)
    504     {
    505         return insert(value, parent, ANY);
    506     }
    507 
    508     virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
    509     {
    510         bool ret = true;
    511         BTreeNode<T>* node = BTreeNode<T>::NewNode();
    512 
    513         if( node == NULL )
    514         {
    515             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node...");
    516         }
    517         else
    518         {
    519             node->value = value;
    520             node->parent = parent;
    521 
    522             ret = insert(node, pos);
    523 
    524             if( !ret )
    525             {
    526                 delete node;
    527             }
    528         }
    529 
    530         return ret;
    531     }
    532 
    533     SharedPointer< Tree<T> > remove(TreeNode<T>* node) //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,//这样有机会对里面的元素做进一步操作
    534     {
    535         BTree<T>* ret = NULL;
    536 
    537         node = find(node);
    538 
    539         if( node == NULL )
    540         {
    541             THROW_EXCEPTION(InvalidParameterException, "parameter is invalid...");
    542         }
    543         else
    544         {
    545             remove(dynamic_cast<BTreeNode<T>*>(node), ret);
    546 
    547             m_queue.clear();
    548         }
    549 
    550         return ret;
    551     }
    552 
    553     SharedPointer< Tree<T> > remove(const T& value)
    554     {
    555         BTree<T>* ret = NULL;
    556 
    557         BTreeNode<T>* node = find(value);
    558 
    559         if( node == NULL )
    560         {
    561             THROW_EXCEPTION(InvalidParameterException, "can not find node via value...");
    562         }
    563         else
    564         {
    565             remove(node, ret);
    566 
    567             m_queue.clear();
    568         }
    569 
    570         return ret;
    571     }
    572 
    573     BTreeNode<T>* find(const T& value) const
    574     {
    575         return find(root(), value);
    576     }
    577 
    578     BTreeNode<T>* find(TreeNode<T>* node) const
    579     {
    580         return find(root(), dynamic_cast<BTreeNode<T>*>(node));
    581     }
    582 
    583     BTreeNode<T>* root() const
    584     {
    585         return dynamic_cast<BTreeNode<T>*>(this->m_root);
    586     }
    587 
    588     int degree() const
    589     {
    590         return degree(root());
    591     }
    592 
    593     int count() const
    594     {
    595         return count(root());
    596     }
    597 
    598     int height() const
    599     {
    600         return height(root());
    601     }
    602 
    603     void clear()
    604     {
    605         free(root());
    606 
    607         m_queue.clear();
    608 
    609         this->m_root = NULL;
    610     }
    611 
    612     bool begin()
    613     {
    614         bool ret = ( root() != NULL );
    615 
    616         if( ret )
    617         {
    618             m_queue.clear();
    619             m_queue.add(root());
    620         }
    621 
    622         return ret;
    623     }
    624 
    625     bool end()
    626     {
    627         return (m_queue.length() == 0);
    628     }
    629 
    630     bool next()
    631     {
    632         bool ret = (m_queue.length() > 0);
    633 
    634         if( ret )
    635         {
    636             BTreeNode<T>* node = m_queue.front();
    637 
    638             m_queue.remove();  //将对头元素出队,相当于移动游标
    639 
    640             if( node->left != NULL )
    641             {
    642                 m_queue.add(node->left);
    643             }
    644 
    645             if( node->right )
    646             {
    647                 m_queue.add(node->right);
    648             }
    649         }
    650 
    651         return ret;
    652     }
    653 
    654     T current()
    655     {
    656         if( !end() )  //遍历的过程当中调用current函数才有意义
    657         {
    658             return m_queue.front()->value;
    659         }
    660         else
    661         {
    662             THROW_EXCEPTION(InvalidOperationException, "No value at current position...");
    663         }
    664     }
    665 
    666     SharedPointer< Array<T> > traversal(BTTraversal order)
    667     {
    668         DynamicArray<T>* ret = NULL;
    669         LinkQueue<BTreeNode<T>*> queue;
    670 
    671         traversal(order, queue);
    672 
    673         ret = new DynamicArray<T>(queue.length());
    674         //遍历完将结果保存到动态数组中去
    675         if( ret != NULL )
    676         {
    677             for(int i = 0; i < ret->length(); i++, queue.remove())
    678             {
    679                 ret->set(i, queue.front()->value);
    680             }
    681         }
    682         else
    683         {
    684             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create array...");
    685         }
    686 
    687         return ret;
    688     }
    689 
    690     SharedPointer< BTree<T> > clone() const
    691     {
    692         BTree<T>* ret = new BTree<T>();
    693 
    694         if( ret != NULL )
    695         {
    696             ret->m_root = clone(root());
    697         }
    698         else
    699         {
    700             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new btree...");
    701         }
    702 
    703         return ret;
    704     }
    705 
    706     bool operator == (const BTree<T>& btree)
    707     {
    708         return equal(root(), btree.root());
    709     }
    710 
    711     bool operator != (const BTree<T>& btree)
    712     {
    713         return !(*this == btree);
    714     }
    715 
    716     SharedPointer< BTree<T> > add(const BTree<T>& btree) const
    717     {
    718         BTree<T>* ret = new BTree<T>();
    719 
    720         if( ret != NULL )
    721         {
    722             ret->m_root = add(root(), btree.root());
    723         }
    724         else
    725         {
    726             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree...");
    727         }
    728 
    729         return ret;
    730     }
    731 
    732     BTreeNode<T>* thread(BTTraversal order)
    733     {
    734         BTreeNode<T>* ret = NULL;
    735         LinkQueue<BTreeNode<T>*> queue;
    736 
    737         traversal(order, queue);
    738 
    739         ret = connect(queue);
    740 
    741         this->m_root = NULL;
    742 
    743         m_queue.clear();
    744 
    745         return ret;
    746     }
    747 
    748     ~BTree()
    749     {
    750         clear();
    751     }
    752 };
    753 
    754 }
    755 
    756 #endif // BTREE_H

    测试程序如下:

     1 #include <iostream>
     2 #include "GTree.h"
     3 #include "GTreeNode.h"
     4 #include "BTree.h"
     5 #include "BTreeNode.h"
     6 
     7 
     8 using namespace std;
     9 using namespace DTLib;
    10 
    11 
    12 int main()
    13 {
    14     BTree<int> bt;
    15     BTreeNode<int>* n = NULL;
    16 
    17     bt.insert(1, NULL);
    18 
    19     n = bt.find(1);
    20     bt.insert(2, n);
    21     bt.insert(3, n);
    22 
    23     n = bt.find(2);
    24     bt.insert(4, n);
    25     bt.insert(5, n);
    26 
    27     n = bt.find(4);
    28     bt.insert(8, n);
    29     bt.insert(9, n);
    30 
    31     n = bt.find(5);
    32     bt.insert(10, n);
    33 
    34     n = bt.find(3);
    35     bt.insert(6, n);
    36     bt.insert(7, n);
    37 
    38 
    39     cout << bt.count() << endl;
    40     cout << bt.height() << endl;
    41     cout << bt.degree() << endl;
    42 
    43 
    44     SharedPointer< Array<int> > tr = bt.traversal(LevelOrder);
    45 
    46     for(int i = 0; i < tr->length(); i++)
    47     {
    48         cout << (*tr)[i] << " ";
    49     }
    50 
    51     cout << endl;
    52 
    53     BTreeNode<int>* head = bt.thread(LevelOrder);
    54 
    55     while( head->right != NULL )
    56     {
    57         head = head->right;
    58     }
    59 
    60     while( head != NULL )
    61     {
    62         cout << head->value << " ";
    63         head = head->left;
    64     }
    65 
    66     cout << endl;
    67 
    68     return 0;
    69 }

    结果如下:

    小结:

  • 相关阅读:
    C# 微信 生活助手 空气质量 天气预报等 效果展示 数据抓取 (二)
    2014年个人总结
    是去是留?这是个问题
    电信限制ip的解决方案
    机械学习
    mac-mysql
    如何使用代码生成工具
    如何使用自定义表单和自定义流程
    test
    编程小问题001
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9695438.html
Copyright © 2020-2023  润新知