zoukankan      html  css  js  c++  java
  • 第五十五课 树中节点的清除操作

    如果一个节点没有子树,那就直接清除这个节点,这就是出口。

    添加free函数:

      1 #ifndef GTREE_H
      2 #define GTREE_H
      3 
      4 #include "Tree.h"
      5 #include "GTreeNode.h"
      6 #include "Exception.h"
      7 
      8 namespace DTLib
      9 {
     10 
     11 template < typename T >
     12 class GTree : public Tree<T>
     13 {
     14 protected:
     15     GTreeNode<T>* find(GTreeNode<T>* node, const T& value) const
     16     {
     17         GTreeNode<T>* ret = NULL;
     18 
     19         if( node != NULL )
     20         {
     21             if( node->value == value )
     22             {
     23                 return node;
     24             }
     25             else
     26             {
     27                 for(node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
     28                 {
     29                     ret = find(node->child.current(), value);
     30                 }
     31             }
     32         }
     33 
     34         return ret;
     35     }
     36 
     37     GTreeNode<T>* find(GTreeNode<T>* node,  GTreeNode<T>* obj) const
     38     {
     39         GTreeNode<T>* ret = NULL;
     40 
     41         if( node == obj )
     42         {
     43             return node;
     44         }
     45         else
     46         {
     47             if( node != NULL )
     48             {
     49                 for( node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
     50                 {
     51                     ret = find(node->child.current(), obj);
     52                 }
     53             }
     54         }
     55 
     56         return ret;
     57     }
     58 
     59     void free(GTreeNode<T>* node)
     60     {
     61         if( node != NULL )
     62         {
     63             for(node->child.move(0); !node->child.end(); node->child.next())
     64             {
     65                 free(node->child.current());
     66             }
     67 
     68             delete node;
     69         }
     70     }
     71 public:
     72     bool insert(TreeNode<T>* node)
     73     {
     74         bool ret = true;
     75 
     76         if( node != NULL )
     77         {
     78             if( this->m_root == NULL ) //如果待插入节点的父节点为空,则这个节点将为根节点
     79             {
     80                 node->parent = NULL;
     81                 this->m_root = node;
     82             }
     83             else
     84             {
     85                 GTreeNode<T>* np = find(node->parent);
     86 
     87                 if( np != NULL )
     88                 {
     89                     GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
     90 
     91                     if( np->child.find(n) < 0 )
     92                     {
     93                         np->child.insert(n);
     94                     }
     95                 }
     96                 else
     97                 {
     98                     THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node...");
     99                 }
    100             }
    101         }
    102         else
    103         {
    104             THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ...");
    105         }
    106 
    107         return ret;
    108     }
    109 
    110     bool insert(const T& value, TreeNode<T>* parent)
    111     {
    112         bool ret = true;
    113 
    114         GTreeNode<T>* node = new GTreeNode<T>();
    115 
    116         if( node != NULL )
    117         {
    118             node->value = value;
    119             node->parent = parent;
    120 
    121             insert(node);
    122         }
    123         else
    124         {
    125             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
    126         }
    127 
    128         return ret;
    129     }
    130 
    131     //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,这样有机会对里面的元素做进一步操作
    132     SharedPointer< Tree<T> > remove(const T& value)
    133     {
    134         return NULL;
    135     }
    136 
    137     SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    138     {
    139         return NULL;
    140     }
    141 
    142     GTreeNode<T>* find(const T& value) const  // 返回GTreeNode,赋值兼容性
    143     {
    144         return find(root(), value);
    145     }
    146 
    147     GTreeNode<T>* find(TreeNode<T>* node) const
    148     {
    149         return find(root(), dynamic_cast<GTreeNode<T>*>(node));
    150     }
    151 
    152     GTreeNode<T>* root() const
    153     {
    154         return dynamic_cast<GTreeNode<T>*>(this->m_root);
    155     }
    156 
    157     int degree() const
    158     {
    159         return 0;
    160     }
    161     int count() const
    162     {
    163         return 0;
    164     }
    165 
    166     int height() const
    167     {
    168         return 0;
    169     }
    170 
    171     void clear()
    172     {
    173         free(root());
    174 
    175         this->m_root = NULL;
    176     }
    177 
    178     ~GTree()
    179     {
    180         clear();
    181     }
    182 };
    183 
    184 }
    185 
    186 #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     t.clear();
    46 
    47     //用链表来验证我们的插入操作,从下至上遍历
    48 
    49     char* s = "KLFGMIJ";
    50 
    51     for( int i = 0; i < 7; i++ )
    52     {
    53         TreeNode<char>* node = t.find(s[i]);
    54 
    55         while( node != NULL )
    56         {
    57             cout << node->value << " ";
    58 
    59             node = node->parent;
    60         }
    61         cout << endl;
    62     }
    63 
    64 
    65     return 0;
    66 }

    现在我们插入的根节点是在栈上,而在释放时却用了delete。

    我们的程序比较小,delete栈中的对象暂时没有体现出bug,但是大型程序这样做是不允许的。

     改进GTreeNode.h文件如下:

     1 #ifndef GTREENODE_H
     2 #define GTREENODE_H
     3 
     4 #include "TreeNode.h"
     5 #include "LinkList.h"
     6 
     7 namespace DTLib
     8 {
     9 
    10 template < typename T >
    11 class GTreeNode : public TreeNode<T>
    12 {
    13 protected:
    14     bool m_flag;
    15 
    16     void* operator new(unsigned int size) throw()
    17     {
    18         return Object::operator new(size);
    19     }
    20 public:
    21     LinkList<GTreeNode<T>*> child;
    22 
    23     GTreeNode()
    24     {
    25         m_flag = false;
    26     }
    27 
    28     bool flag()
    29     {
    30         return m_flag;
    31     }
    32 
    33     static GTreeNode<T>* NewNode()
    34     {
    35         GTreeNode<T>* ret = new GTreeNode<T>();
    36 
    37         if( ret != NULL )
    38         {
    39             ret->m_flag = true;
    40         }
    41 
    42         return ret;
    43     }
    44 };
    45 
    46 }
    47 
    48 #endif // GTREENODE_H

    GTree.h改进如下:

      1 #ifndef GTREE_H
      2 #define GTREE_H
      3 
      4 #include "Tree.h"
      5 #include "GTreeNode.h"
      6 #include "Exception.h"
      7 
      8 namespace DTLib
      9 {
     10 
     11 template < typename T >
     12 class GTree : public Tree<T>
     13 {
     14 protected:
     15     GTreeNode<T>* find(GTreeNode<T>* node, const T& value) const
     16     {
     17         GTreeNode<T>* ret = NULL;
     18 
     19         if( node != NULL )
     20         {
     21             if( node->value == value )
     22             {
     23                 return node;
     24             }
     25             else
     26             {
     27                 for(node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
     28                 {
     29                     ret = find(node->child.current(), value);
     30                 }
     31             }
     32         }
     33 
     34         return ret;
     35     }
     36 
     37     GTreeNode<T>* find(GTreeNode<T>* node,  GTreeNode<T>* obj) const
     38     {
     39         GTreeNode<T>* ret = NULL;
     40 
     41         if( node == obj )
     42         {
     43             return node;
     44         }
     45         else
     46         {
     47             if( node != NULL )
     48             {
     49                 for( node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
     50                 {
     51                     ret = find(node->child.current(), obj);
     52                 }
     53             }
     54         }
     55 
     56         return ret;
     57     }
     58 
     59     void free(GTreeNode<T>* node)
     60     {
     61         if( node != NULL )
     62         {
     63             for(node->child.move(0); !node->child.end(); node->child.next())
     64             {
     65                 free(node->child.current());
     66             }
     67 
     68             if( node->flag() )
     69             {
     70                 delete node;
     71             }
     72         }
     73     }
     74 public:
     75     bool insert(TreeNode<T>* node)
     76     {
     77         bool ret = true;
     78 
     79         if( node != NULL )
     80         {
     81             if( this->m_root == NULL ) //如果待插入节点的父节点为空,则这个节点将为根节点
     82             {
     83                 node->parent = NULL;
     84                 this->m_root = node;
     85             }
     86             else
     87             {
     88                 GTreeNode<T>* np = find(node->parent);
     89 
     90                 if( np != NULL )
     91                 {
     92                     GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
     93 
     94                     if( np->child.find(n) < 0 )
     95                     {
     96                         np->child.insert(n);
     97                     }
     98                 }
     99                 else
    100                 {
    101                     THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node...");
    102                 }
    103             }
    104         }
    105         else
    106         {
    107             THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ...");
    108         }
    109 
    110         return ret;
    111     }
    112 
    113     bool insert(const T& value, TreeNode<T>* parent)
    114     {
    115         bool ret = true;
    116 
    117         GTreeNode<T>* node = GTreeNode<T>::NewNode();
    118 
    119         if( node != NULL )
    120         {
    121             node->value = value;
    122             node->parent = parent;
    123 
    124             insert(node);
    125         }
    126         else
    127         {
    128             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
    129         }
    130 
    131         return ret;
    132     }
    133 
    134     //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,这样有机会对里面的元素做进一步操作
    135     SharedPointer< Tree<T> > remove(const T& value)
    136     {
    137         return NULL;
    138     }
    139 
    140     SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    141     {
    142         return NULL;
    143     }
    144 
    145     GTreeNode<T>* find(const T& value) const  // 返回GTreeNode,赋值兼容性
    146     {
    147         return find(root(), value);
    148     }
    149 
    150     GTreeNode<T>* find(TreeNode<T>* node) const
    151     {
    152         return find(root(), dynamic_cast<GTreeNode<T>*>(node));
    153     }
    154 
    155     GTreeNode<T>* root() const
    156     {
    157         return dynamic_cast<GTreeNode<T>*>(this->m_root);
    158     }
    159 
    160     int degree() const
    161     {
    162         return 0;
    163     }
    164     int count() const
    165     {
    166         return 0;
    167     }
    168 
    169     int height() const
    170     {
    171         return 0;
    172     }
    173 
    174     void clear()
    175     {
    176         free(root());
    177 
    178         this->m_root = NULL;
    179     }
    180 
    181     ~GTree()
    182     {
    183         clear();
    184     }
    185 };
    186 
    187 }
    188 
    189 #endif // GTREE_H

    小结:

  • 相关阅读:
    Codeforces Round #694 (Div.1, Div.2)题解(2A-1D)(1E-1F待填)
    【Luogu日报#294】OI中你可能会用到的一些不等式及其证明 | 习题题解
    SP10570 LONGCS
    Unity 数字孪生笔记 工具介绍
    Unity3D 最佳数字孪生插件(一个基于Unity的自动化概念设计,仿真,虚拟调试和3D HMI的框架)
    Unity 数字孪生笔记 PiXYZ快速入门
    数据结构:堆排序
    HDU 4704 Sum (欧拉降幂+二项式公式+快速幂)
    Codeforces Goodbye2020部分题解
    Apache架构师的30条设计原则
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9691014.html
Copyright © 2011-2022 走看看