zoukankan      html  css  js  c++  java
  • 第五十六课 树中结点的删除操作

    返回的指针谁来负责释放呢?我们采取的措施是使用智能指针来管理这棵树的生命周期。

    返回一棵子树的好处是在某些场合,我们能够将H、I、J、M重组,并将它们重新的加回原来的树中。

    示例:

    main函数使用了p指针指向的内存,但是不负责释放,因为从main函数的角度来看,这片内存不是main函数申请的,而从func函数的角度来看,这片内存是申请给main函数用的,func返回之后就无法控制这片内存了。而C++本身又没有内存释放机制。因此,这片内存处于三不管地带,我们要用智能指针来管理。

    于是改造成如下的形式:

    main函数返回的时候,内存自动被智能指针释放。

     

    添加删除操作:

      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 
     75     void remove(GTreeNode<T>* node, GTree<T>*& ret)
     76     {
     77         ret = new GTree<T>();
     78 
     79         if( ret == NULL )
     80         {
     81             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create tree...");
     82         }
     83         else
     84         {
     85             if( root() == node )
     86             {
     87                 this->m_root = NULL;
     88             }
     89             else
     90             {
     91                 LinkList<GTreeNode<T>*>& child = dynamic_cast<GTreeNode<T>*>(node->parent)->child;
     92 
     93                 child.remove(child.find(node));
     94 
     95                 node->parent = NULL;
     96             }
     97 
     98             ret->m_root = node;
     99         }
    100     }
    101 public:
    102     bool insert(TreeNode<T>* node)
    103     {
    104         bool ret = true;
    105 
    106         if( node != NULL )
    107         {
    108             if( this->m_root == NULL ) //如果待插入节点的父节点为空,则这个节点将为根节点
    109             {
    110                 node->parent = NULL;
    111                 this->m_root = node;
    112             }
    113             else
    114             {
    115                 GTreeNode<T>* np = find(node->parent);
    116 
    117                 if( np != NULL )
    118                 {
    119                     GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);
    120 
    121                     if( np->child.find(n) < 0 )
    122                     {
    123                         np->child.insert(n);
    124                     }
    125                 }
    126                 else
    127                 {
    128                     THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node...");
    129                 }
    130             }
    131         }
    132         else
    133         {
    134             THROW_EXCEPTION(InvalidParameterException, "Parameter node cannot be NULL ...");
    135         }
    136 
    137         return ret;
    138     }
    139 
    140     bool insert(const T& value, TreeNode<T>* parent)
    141     {
    142         bool ret = true;
    143 
    144         GTreeNode<T>* node = GTreeNode<T>::NewNode();
    145 
    146         if( node != NULL )
    147         {
    148             node->value = value;
    149             node->parent = parent;
    150 
    151             insert(node);
    152         }
    153         else
    154         {
    155             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
    156         }
    157 
    158         return ret;
    159     }
    160 
    161     //删除的节点的子节点我们还需要处理,因此要返回删除节点的指针,这样有机会对里面的元素做进一步操作
    162     SharedPointer< Tree<T> > remove(const T& value)
    163     {
    164         GTree<T>* ret = NULL;
    165 
    166         GTreeNode<T>* node = find(value);
    167 
    168         if( node == NULL )
    169         {
    170             THROW_EXCEPTION(InvalidParameterException, "can not find the node ...");
    171         }
    172         else
    173         {
    174             remove(node, ret);
    175         }
    176 
    177         return ret;
    178     }
    179 
    180     SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    181     {
    182         GTree<T>* ret = NULL;
    183 
    184         node = find(node);
    185 
    186         if( node == NULL )
    187         {
    188             THROW_EXCEPTION(InvalidParameterException, "parameter node is invalid ...");
    189         }
    190         else
    191         {
    192             remove(dynamic_cast<GTreeNode<T>*>(node), ret);
    193         }
    194 
    195         return ret;
    196     }
    197 
    198     GTreeNode<T>* find(const T& value) const  // 返回GTreeNode,赋值兼容性
    199     {
    200         return find(root(), value);
    201     }
    202 
    203     GTreeNode<T>* find(TreeNode<T>* node) const
    204     {
    205         return find(root(), dynamic_cast<GTreeNode<T>*>(node));
    206     }
    207 
    208     GTreeNode<T>* root() const
    209     {
    210         return dynamic_cast<GTreeNode<T>*>(this->m_root);
    211     }
    212 
    213     int degree() const
    214     {
    215         return 0;
    216     }
    217     int count() const
    218     {
    219         return 0;
    220     }
    221 
    222     int height() const
    223     {
    224         return 0;
    225     }
    226 
    227     void clear()
    228     {
    229         free(root());
    230 
    231         this->m_root = NULL;
    232     }
    233 
    234     ~GTree()
    235     {
    236         clear();
    237     }
    238 };
    239 
    240 }
    241 
    242 #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.remove('D');
    46 
    47     //用链表来验证我们的插入操作,从下至上遍历
    48 
    49     const 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 }

    结果如下:

    第二个测试程序:

     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     SharedPointer<Tree<char>> p = t.remove(t.find('D'));
    46 
    47     //用链表来验证我们的插入操作,从下至上遍历
    48 
    49     const char* s = "KLFGMIJ";
    50 
    51     for( int i = 0; i < 7; i++ )
    52     {
    53         TreeNode<char>* node = p->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 }

    结果如下:

    可以看到返回了子树,子树中的结点我们都能访问到。

    小结:

  • 相关阅读:
    邮件与短信
    面向对象--第二部分
    #实现一个文件的拷贝功能,注意:大文件的问题
    link标签和script标签跑到body下面,网页顶部有空白
    svn利用TortoiseSVN忽略文件或文件夹
    CS6破解
    获得指定元素的透明度值
    IE6不支持position:fixed属性
    jQuery获取自身HTML
    margin负值
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9691944.html
Copyright © 2011-2022 走看看