• 第五十八课 树形结构的层次遍历


    通用树结构是一种容器,里面装有数据元素,我们有遍历元素的需求。

     非线性决定了树中的每个结点没有固定的编号方式。

    将队列中队首的指针定义成遍历时的游标,根节点进入队列后,游标指向根节点。

    队头元素弹出,队首的指针就指向了别的元素,这就相当于移动了游标。

    添加遍历相关的程序:

      1 #ifndef GTREE_H
      2 #define GTREE_H
      3 
      4 #include "Tree.h"
      5 #include "GTreeNode.h"
      6 #include "Exception.h"
      7 #include "LinkQueue.h"
      8 
      9 namespace DTLib
     10 {
     11 
     12 template < typename T >
     13 class GTree : public Tree<T>
     14 {
     15 protected:
     16     LinkQueue<GTreeNode<T>*> m_queue;
     17 
     18     GTree(const GTree<T>&);
     19     GTree<T>& operator = (const GTree<T>&);
     20 
     21     GTreeNode<T>* find(GTreeNode<T>* node, const T& value) const
     22     {
     23         GTreeNode<T>* ret = NULL;
     24 
     25         if( node != NULL )
     26         {
     27             if( node->value == value )
     28             {
     29                 return node;
     30             }
     31             else
     32             {
     33                 for(node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
     34                 {
     35                     ret = find(node->child.current(), value);
     36                 }
     37             }
     38         }
     39 
     40         return ret;
     41     }
     42 
     43     GTreeNode<T>* find(GTreeNode<T>* node,  GTreeNode<T>* obj) const
     44     {
     45         GTreeNode<T>* ret = NULL;
     46 
     47         if( node == obj )
     48         {
     49             return node;
     50         }
     51         else
     52         {
     53             if( node != NULL )
     54             {
     55                 for( node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
     56                 {
     57                     ret = find(node->child.current(), obj);
     58                 }
     59             }
     60         }
     61 
     62         return ret;
     63     }
     64 
     65     void free(GTreeNode<T>* node)
     66     {
     67         if( node != NULL )
     68         {
     69             for(node->child.move(0); !node->child.end(); node->child.next())
     70             {
     71                 free(node->child.current());
     72             }
     73 
     74             if( node->flag() )
     75             {
     76                 delete node;
     77             }
     78         }
     79     }
     80 
     81     void remove(GTreeNode<T>* node, GTree<T>*& ret)
     82     {
     83         ret = new GTree<T>();
     84 
     85         if( ret == NULL )
     86         {
     87             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create tree...");
     88         }
     89         else
     90         {
     91             if( root() == node )
     92             {
     93                 this->m_root = NULL;
     94             }
     95             else
     96             {
     97                 LinkList<GTreeNode<T>*>& child = dynamic_cast<GTreeNode<T>*>(node->parent)->child;
     98 
     99                 child.remove(child.find(node));
    100 
    101                 node->parent = NULL;
    102             }
    103 
    104             ret->m_root = node;
    105         }
    106     }
    107 
    108     int count(GTreeNode<T>* node) const
    109     {
    110         int ret = 0;
    111 
    112         if( node != NULL )
    113         {
    114             ret = 1;
    115 
    116             //node如果没有孩子,则for不执行
    117             for(node->child.move(0); !node->child.end(); node->child.next())
    118             {
    119                 ret += count(node->child.current());
    120             }
    121         }
    122 
    123         return ret;
    124     }
    125 
    126     int height(GTreeNode<T>* node) const
    127     {
    128         int ret = 0;
    129 
    130         if( node != NULL )
    131         {
    132             for(node->child.move(0); !node->child.end(); node->child.next())
    133             {
    134                 int h = height(node->child.current());
    135 
    136                 if( ret < h )
    137                 {
    138                     ret = h;
    139                 }
    140             }
    141 
    142             ret = ret + 1;
    143         }
    144 
    145         return ret;
    146     }
    147 
    148     int degree(GTreeNode<T>* node) const
    149     {
    150         int ret = 0;
    151 
    152         if( node != NULL )
    153         {
    154             ret = node->child.length();  //根节点的度数
    155 
    156             for(node->child.move(0); !node->child.end(); node->child.next())
    157             {
    158                 int d = degree(node->child.current());
    159 
    160                 if( ret < d )
    161                 {
    162                     ret = d;
    163                 }
    164             }
    165         }
    166 
    167         return ret;
    168     }
    169 public:
    170     GTree()
    171     {
    172 
    173     }
    174     bool insert(TreeNode<T>* node)
    175     {
    176         bool ret = true;
    177 
    178         if( node != NULL )
    179         {
    180             if( this->m_root == NULL ) //如果待插入节点的父节点为空,则这个节点将为根节点
    181             {
    182                 node->parent = NULL;
    183                 this->m_root = node;
    184             }
    185             else
    186             {
    187                 GTreeNode<T>* np = find(node->parent);
    188 
    189                 if( np != NULL )
    190                 {
    191                     GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
    192 
    193                     if( np->child.find(n) < 0 )
    194                     {
    195                         np->child.insert(n);
    196                     }
    197                 }
    198                 else
    199                 {
    200                     THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node...");
    201                 }
    202             }
    203         }
    204         else
    205         {
    206             THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ...");
    207         }
    208 
    209         return ret;
    210     }
    211 
    212     bool insert(const T& value, TreeNode<T>* parent)
    213     {
    214         bool ret = true;
    215 
    216         GTreeNode<T>* node = GTreeNode<T>::NewNode();
    217 
    218         if( node != NULL )
    219         {
    220             node->value = value;
    221             node->parent = parent;
    222 
    223             insert(node);
    224         }
    225         else
    226         {
    227             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
    228         }
    229 
    230         return ret;
    231     }
    232 
    233     //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,这样有机会对里面的元素做进一步操作
    234     SharedPointer< Tree<T> > remove(const T& value)
    235     {
    236         GTree<T>* ret = NULL;
    237 
    238         GTreeNode<T>* node = find(value);
    239 
    240         if( node == NULL )
    241         {
    242             THROW_EXCEPTION(InvalidParameterException, "can not find the node ...");
    243         }
    244         else
    245         {
    246             remove(node, ret);
    247 
    248             m_queue.clear();
    249         }
    250 
    251         return ret;
    252     }
    253 
    254     SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    255     {
    256         GTree<T>* ret = NULL;
    257 
    258         node = find(node);
    259 
    260         if( node == NULL )
    261         {
    262             THROW_EXCEPTION(InvalidParameterException, "parameter node is invalid ...");
    263         }
    264         else
    265         {
    266             remove(dynamic_cast<GTreeNode<T>*>(node), ret);
    267 
    268             m_queue.clear();
    269         }
    270 
    271         return ret;
    272     }
    273 
    274     GTreeNode<T>* find(const T& value) const  // 返回GTreeNode,赋值兼容性
    275     {
    276         return find(root(), value);
    277     }
    278 
    279     GTreeNode<T>* find(TreeNode<T>* node) const
    280     {
    281         return find(root(), dynamic_cast<GTreeNode<T>*>(node));
    282     }
    283 
    284     GTreeNode<T>* root() const
    285     {
    286         return dynamic_cast<GTreeNode<T>*>(this->m_root);
    287     }
    288 
    289     int degree() const
    290     {
    291         return degree(root());
    292     }
    293     int count() const
    294     {
    295         return count(root());
    296     }
    297 
    298     int height() const
    299     {
    300         return height(root());
    301     }
    302 
    303     void clear()
    304     {
    305         free(root());
    306 
    307         this->m_root = NULL;
    308 
    309         m_queue.clear();
    310     }
    311 
    312     bool begin()
    313     {
    314         bool ret = ( root() != NULL );
    315 
    316         if( ret )
    317         {
    318             m_queue.clear();
    319             m_queue.add(root());
    320         }
    321 
    322         return ret;
    323     }
    324 
    325     bool end()
    326     {
    327         return (m_queue.length() == 0);
    328     }
    329 
    330     bool next()
    331     {
    332         bool ret = (m_queue.length() > 0);
    333 
    334         if( ret )
    335         {
    336             GTreeNode<T>* node = m_queue.front();
    337 
    338             m_queue.remove();  //将对头元素出队,相当于移动游标
    339 
    340             for(node->child.move(0); !node->child.end(); node->child.next())
    341             {
    342                 m_queue.add(node->child.current());
    343             }
    344         }
    345 
    346         return ret;
    347     }
    348 
    349     T current()
    350     {
    351         if( !end() )  //遍历的过程当中调用current函数才有意义
    352         {
    353             return m_queue.front()->value;
    354         }
    355         else
    356         {
    357             THROW_EXCEPTION(InvalidOperationException, "No value at current position...");
    358         }
    359     }
    360 
    361     ~GTree()
    362     {
    363         clear();
    364     }
    365 };
    366 
    367 }
    368 
    369 #endif // GTREE_H

    测试程序如下:

     1 #include <iostream>
     2 #include "GTree.h"
     3 #include "GTreeNode.h"
     4 
     5 
     6 using namespace std;
     7 using namespace DTLib;
     8 
     9 
    10 int main()
    11 {
    12     GTree<char> t;
    13     GTreeNode<char>* node = NULL;
    14     GTreeNode<char> root;
    15 
    16     root.value = 'A';
    17     root.parent = NULL;
    18 
    19     t.insert(&root);
    20 
    21     node = t.find('A');
    22     t.insert('B', node);
    23     t.insert('C', node);
    24     t.insert('D', node);
    25 
    26     node = t.find('B');
    27     t.insert('E', node);
    28     t.insert('F', node);
    29 
    30     node = t.find('E');
    31     t.insert('K', node);
    32     t.insert('L', node);
    33 
    34     node = t.find('C');
    35     t.insert('G', node);
    36 
    37     node = t.find('D');
    38     t.insert('H', node);
    39     t.insert('I', node);
    40     t.insert('J', node);
    41 
    42     node = t.find('H');
    43     t.insert('M', node);
    44 
    45     cout << t.degree() << endl;
    46 
    47     for(t.begin(); !t.end(); t.next())
    48     {
    49         cout << t.current() << endl;
    50     }
    51 
    52     return 0;
    53 }

    结果如下:

    小结:

  • 相关阅读:
    &与&&的区别
    jsp之response方法
    一个数组先按照某个属性的大小排序,如果大小一样的就按照名称排序
    CSS内部div设置上min-height或max-height滚动条就会出现在父元素上
    300行代码手写简单vue.js,彻底弄懂MVVM底层原理
    JavaScript简单手写观察者模式
    javascript中replace还可以这样玩
    VUE中通过改变key去更新局部dom
    element中select的change方法如何传多个参数
    react打包中不想要sourceMap,但是在命令里加'GENERATE_SOURCEMAP=false'后windows下报错'GENERATE_SOURCEMAP' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9692498.html
Copyright © 2020-2023  润新知