第56课 - 树中结点的删除操作

1、树中结点的删除操作 

        删除的方式 

            -基于数据元素值的删除 

                    SharedPointer< Tree<T> > remove(const T& value

            -基于结点的删除 

                    SharedPointer< Tree<T> > remove(TreeNode<T>* node


        删除操作成员函数的设计要点 

                -将被删结点所代表的子树进行删除 

                -删除函数返回—棵堆空间中的树 

                -具体返回值为 指向树的智能指针对象 


        树中结点的删除


            


                            返回智能指针对象就能对待删除子树不用时进行自动释放堆空间



        实用的设计原则 

                当需要从函数中返回堆中的对象时,使用智能 

                指针(SharedPointer)作为函数的返回值。


        下面举个例子帮助理解    

  1. int* func()  
  2. {  
  3.     return new int;  
  4. }  
  5.   
  6. int main()  
  7. {  
  8.     int* p = func();    //那么在main函数里要不要释放p所指堆空间???   
  9.       
  10.       
  11.     return 0;  
  12. }   

                站在main函数角度,不应该释放,毕竟我们曾在C/C++课程学过谁申请应该谁释放,

                然而在这里func函数提供四个字节就返回了,哪有机会释放

                那么我们可以用智能指针解决该问题

  1. SharedPointer<int> func()  
  2. {  
  3.     return new int;  
  4. }  
  5.   
  6. int main()  
  7. {  
  8.     SharedPointer<int> p = func();    //在main函数结束时自动释放堆空间   
  9.       
  10.       
  11.     return 0;  
  12. }   


        删除操作功能的定义 

            - void remove(GTreeNode<T>* node, GTree<T>*&  ret)     -->返回一个引用作为指针别名

                    将node为根结点的子树从原来的树中删除 

                    ret作为子树返回(ret指向堆空间中的树对象)


        删除功能函数的实现 

                    

2、编程实验

树结点的删除操作     remove
#ifndef GTREE_H
#define GTREE_H

#include "Tree.h"
#include"GTreeNode.h"
#include"Exception.h"


namespace DTLib
{
template < typename T >
class GTree : public Tree<T>
{
protected:
    GTreeNode<T>* find(GTreeNode<T>* node,const T& value) const
    {
        GTreeNode<T>* ret = NULL;

        if(node != NULL)
        {
            if(node->value == value)
            {
                return node;
            }
            else
            {
                for(node->child.move(0);!node->child.end() && (ret == NULL);node->child.next())     //在node子树中查找
                {
                    ret = find(node->child.current(),value);    //child里数据元素类型是GTreeNode<T>*
                }
            }
        }

        return ret;
    }

    GTreeNode<T>* find(GTreeNode<T>* node,GTreeNode<T>* obj) const
    {
        GTreeNode<T>* ret = NULL;

        if(node == obj)
        {
            return node;
        }
        else
        {
            if(node != NULL)
            {
                for(node->child.move(0);!node->child.end() && (ret == NULL);node->child.next())
                {
                    ret = find(node->child.current(),obj);
                }
            }
        }

        return ret;
    }

    void free(GTreeNode<T>* node)
    {
        if(node != NULL)
        {
            for(node->child.move(0);!node->child.end();node->child.next())
            {
                free(node->child.current());
            }

            if(node->flag())
            {
                delete node;
            }

        }
    }

    void remove(GTreeNode<T>* node,GTree<T>*& ret)
    {
        ret = new GTree<T>();

        if(ret == NULL)
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
        }
        else
        {
            if( root() == node)    //待删结点就是根结点
            {
                this->m_root = NULL;
            }
            else
            {
                LinkList< GTreeNode<T>* >& child = dynamic_cast< GTreeNode<T>* >(node->parent)->child; //child引用指向待删除结点父结点的链表

                child.remove(child.find(node)); //在父结点的链表中 将指向(结点的指针)待删孩子  的结点删除

                node->parent = NULL;    //此子树彻底地离开了树,并没有清除释放
            }

            ret->m_root = node;
        }
    }

public:
    bool insert(TreeNode<T>* node)
    {
        bool ret = true;

        if(node != NULL)
        {
            if(this->m_root == NULL)
            {
                node->parent = NULL;
                this->m_root = node;
            }
            else
            {
                GTreeNode<T>* np = find(node->parent);

                if( np != NULL )
                {
                    GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);

                    if( np->child.find(n) < 0 )  
                    {
                        np->child.insert(n);
                    }
                }
                else
                {
                    THROW_EXCEPTION(InvalidOperationException,"Invalid parent tree node ...");
                }
            }
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterException,"Parameter node cannot be NULL ...");
        }

        return ret;
    }

    bool insert(const T& value,TreeNode<T>* parent)
    {
        bool ret = true;

        GTreeNode<T>* node = GTreeNode<T>::NewNode();

        if(node)
        {
            node->value = value;
            node->parent = parent;

            insert(node);
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree node ...");
        }

        return ret;
    }

    SharedPointer< Tree<T> > remove(const T& value)
    {
        GTree<T>* ret = NULL;

        GTreeNode<T>* node = find(value);

        if(node == NULL)
        {
            THROW_EXCEPTION(InvalidParameterException,"Can not find the node via parameter value ...");
        }
        else
        {
            remove(node,ret);
        }


        return ret;
    }
    SharedPointer< Tree<T> > remove(TreeNode<T>* node)
    {
        GTree<T>* ret = NULL;

        node = find(node);

        if(node == NULL)
        {
            THROW_EXCEPTION(InvalidParameterException,"Parameter node is invalid ...");
        }
        else
        {
            remove(dynamic_cast<GTreeNode<T>*>(node),ret);
        }

        return NULL;
    }

    GTreeNode<T>* find(const T& value) const   
    {
        return find(root(),value);
    }
    GTreeNode<T>* find(TreeNode<T>* node) const
    {
        return find(root(),dynamic_cast< GTreeNode<T>* >(node));
    }
    GTreeNode<T>* root() const
    {
        return dynamic_cast< GTreeNode<T>* >(this->m_root);
    }
    int degree() const
    {
        return 0;
    }
    int count() const
    {
        return 0;
    }
    int height() const
    {
        return 0;
    }
    void clear()
    {
        free(root());
        this->m_root = NULL;
    }

    ~GTree()
    {
        clear();
    }
};

}
#endif // GTREE_H

main.cpp

#include <iostream>
#include"GTree.h"

using namespace std;
using namespace DTLib;


int main()
{
    GTree<char> t;
    GTreeNode<char>* node = NULL;

    GTreeNode<char> root;

    root.value = 'A';
    root.parent = NULL;

    t.insert(&root);    //将局部对象作为根结点插入

    node = t.find('A');
    t.insert('B',node);
    t.insert('C',node);
    t.insert('D',node);

    node = t.find('B');
    t.insert('E',node);
    t.insert('F',node);

    node = t.find('E');
    t.insert('K',node);
    t.insert('L',node);

    node = t.find('C');
    t.insert('G',node);

    node = t.find('D');
    t.insert('H',node);
    t.insert('I',node);
    t.insert('J',node);

    node = t.find('H');
    t.insert('M',node);

    const char* s = "KLFGMIJ";

    t.remove(t.find('B'));


    for(int i=0;i<7;i++)
    {
        TreeNode<char>* node = t.find(s[i]);

        while(node != NULL)
        {
            cout<<node->value<<" ";

            node = node->parent;
        }

        cout<<endl;
    }

    SharedPointer< Tree<char> > p = t.remove('D');

    for(int i=0;i<7;i++)
    {
        TreeNode<char>* node = p->find(s[i]);

        while(node != NULL)
        {
            cout<<node->value<<" ";

            node = node->parent;
        }

        cout<<endl;
    }


    return 0;

                        



3、小结 

            删除操作各目标结点所代表的子树移除 

            删除操作必须完善处理父结点和子结点的关系 

            删除操作的返回值为指向树的智能指针对象 

            函数中返回堆中的对象时,使用智能指针作为返回值 


4、实战预告

        To be continued ... 

        思考: 

                如何实现GTree (通用树结构)的属性操作函数? 



猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/80470742