zoukankan      html  css  js  c++  java
  • 数据结构开发(23):二叉树中结点的查找、插入、删除与清除操作

    0.目录

    1.二叉树中结点的查找操作

    2.二叉树中结点的插入操作

    3.二叉树中结点的删除操作

    4.二叉树中结点的清除操作

    5.小结

    1.二叉树中结点的查找操作

    查找的方式:

    • 基于数据元素值的查找
      1. BTreeNode<T>* find(const T& value) const
    • 基于结点的查找
      1. BTreeNode<T>* find(TreeNode<T>* node) const

    树中数据元素和结点的查找:

    基于数据元素值的查找:

    • 定义功能:find(node, value)
      1. node 为根结点的二叉树中查找 value 所在的结点

    在BTree.h中实现基于数据元素值的查找:

    protected:
        virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
        {
            BTreeNode<T>* ret = NULL;
    
            if( node != NULL )
            {
                if( node->value == value )
                {
                    return node;
                }
                else
                {
                    if( ret == NULL )
                    {
                        ret = find(node->left, value);
                    }
    
                    if( ret == NULL )
                    {
                        ret = find(node->right, value);
                    }
                }
            }
    
            return ret;
        }
    public:
        BTreeNode<T>* find(const T& value) const
        {
            return find(root(), value);
        }
    

    基于结点的查找:

    • 定义功能:find(node, obj)
      1. node 为根结点的二叉树中查找是否存在 obj 结点

    在BTree.h中实现基于结点的查找:

    protected:
        virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
        {
            BTreeNode<T>* ret = NULL;
    
            if( node == obj )
            {
                return node;
            }
            else
            {
                if( node != NULL )
                {
                    if( ret == NULL )
                    {
                        ret = find(node->left, obj);
                    }
    
                    if( ret == NULL )
                    {
                        ret = find(node->right, obj);
                    }
                }
            }
    
            return ret;
        }
    public:
        BTreeNode<T>* find(TreeNode<T>* node) const
        {
            return find(root(), dynamic_cast<BTreeNode<T>*>(node));
        }
    

    2.二叉树中结点的插入操作

    需要考虑的问题:

    • 是否能够在二叉树的任意结点处插入子结点?
    • 是否需要指定新数据元素 ( 新结点 ) 的插入位置?

    二叉树结点的位置枚举类型:

    插入的方式

    • 插入新结点
      1. bool insert(TreeNode<T>* node)
      2. bool insert(TreeNode<T>* node, BTNodePos pos)
    • 插入数据元素
      1. bool insert(const T& value, TreeNode<T>* parent)
      2. bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)

    新结点的插入:

    指定位置的结点插入:

    插入新结点:

    插入数据元素:

    在BTreeNode.h中实现BTNodePos枚举类型:

    #ifndef BTREENODE_H
    #define BTREENODE_H
    
    #include "TreeNode.h"
    
    namespace StLib
    {
    
    enum BTNodePos
    {
        ANY,
        LEFT,
        RIGHT
    };
    
    template <typename T>
    class BTreeNode : public TreeNode<T>
    {
    public:
        BTreeNode<T>* left;
        BTreeNode<T>* right;
    
        BTreeNode()
        {
            left = NULL;
            right = NULL;
        }
    
        static BTreeNode<T>* NewNode()
        {
            BTreeNode<T>* ret = new BTreeNode<T>();
    
            if( ret != NULL )
            {
                ret->m_flag = true;
            }
    
            return ret;
        }
    };
    
    }
    
    #endif // BTREENODE_H
    

    在BTree.h中实现结点的插入操作:

    protected:
        virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
        {
            bool ret = true;
    
            if( pos == ANY )
            {
                if( np->left == NULL )
                {
                    np->left = n;
                }
                else if( np->right == NULL )
                {
                    np->right = n;
                }
                else
                {
                    ret = false;
                }
            }
            else if( pos == LEFT )
            {
                if( np->left == NULL )
                {
                    np->left = n;
                }
                else
                {
                    ret = false;
                }
            }
            else if( pos == RIGHT )
            {
                if( np->right == NULL )
                {
                    np->right = n;
                }
                else
                {
                    ret = false;
                }
            }
            else
            {
                ret = false;
            }
    
            return ret;
        }
    public:
        bool insert(TreeNode<T>* node)
        {
            return insert(node, ANY);
        }
    
        virtual bool insert(TreeNode<T>* node, BTNodePos pos)
        {
            bool ret = true;
    
            if( node != NULL )
            {
                if( this->m_root == NULL )
                {
                    node->parent = NULL;
                    this->m_root = node;
                }
                else
                {
                    BTreeNode<T>* np = find(node->parent);
    
                    if( np != NULL )
                    {
                        ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
                    }
                    else
                    {
                        THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node ...");
                    }
                }
            }
            else
            {
                THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
            }
    
            return ret;
        }
    
        bool insert(const T& value, TreeNode<T>* parent)
        {
            return insert(value, parent, ANY);
        }
    
        virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
        {
            bool ret = true;
            BTreeNode<T>* node = BTreeNode<T>::NewNode();
    
            if( node == NULL )
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
            }
            else
            {
                node->value = value;
                node->parent = parent;
    
                ret = insert(node, pos);
    
                if( !ret )
                {
                    delete node;
                }
            }
    
            return ret;
        }
    

    mian.cpp测试这棵树:

    #include <iostream>
    #include "BTree.h"
    
    using namespace std;
    using namespace StLib;
    
    int main()
    {
        BTree<int> bt;
        BTreeNode<int>* n = NULL;
    
        bt.insert(1, NULL);
    
        n = bt.find(1);
        bt.insert(2, n);
        bt.insert(3, n);
    
        n = bt.find(2);
        bt.insert(4, n);
        bt.insert(5, n);
    
        n = bt.find(4);
        bt.insert(8, n);
        bt.insert(9, n);
    
        n = bt.find(5);
        bt.insert(10, n);
    
        n = bt.find(3);
        bt.insert(6, n);
        bt.insert(7, n);
    
        n = bt.find(6);
        bt.insert(11, n, LEFT);
    
        int a[] = {8, 9, 10, 11, 7};
    
        for(int i=0; i<5; i++)
        {
            TreeNode<int>* node = bt.find(a[i]);
    
            while( node )
            {
                cout << node->value << " ";
                node = node->parent;
            }
    
            cout << endl;
        }
    
        return 0;
    }
    

    运行结果为:

    8 4 2 1 
    9 4 2 1 
    10 5 2 1 
    11 6 3 1 
    7 3 1 
    

    3.二叉树中结点的删除操作

    删除的方式:

    • 基于数据元素值的删除
      1. SharedPointer< Tree<T> > remove(const T& value)
    • 基于结点的删除
      1. SharedPointer< Tree<T> > remove(TreeNode<T>* node)

    二叉树中的结点删除:

    删除操作功能的定义:

    • void remove(BTreeNode<T>* node, BTree<T>*& ret)
      1. 将 node 为根结点的子树从原来的二叉树中删除
      2. ret 作为子树返回 ( ret 指向堆空间中的二叉树对象 )

    删除功能函数的实现:

    在BTree.h中实现结点的删除操作:

    protected:
        virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
        {
            ret = new BTree<T>();
    
            if( ret == NULL )
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
            }
            else
            {
                if( root() == node )
                {
                    this->m_root = NULL;
                }
                else
                {
                    BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
    
                    if( parent->left == node )
                    {
                        parent->left = NULL;
                    }
                    else if( parent->right == node )
                    {
                        parent->right = NULL;
                    }
    
                    node->parent = NULL;
                }
    
                ret->m_root = node;
            }
        }
    public:
        SharedPointer< Tree<T> > remove(const T& value)
        {
            BTree<T>* ret = NULL;
            BTreeNode<T>* node = find(value);
    
            if( node == NULL )
            {
                THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
            }
            else
            {
                remove(node, ret);
            }
    
            return ret;
        }
    
        SharedPointer< Tree<T> > remove(TreeNode<T>* node)
        {
            BTree<T>* ret = NULL;
    
            node = find(node);
    
            if( node == NULL )
            {
                THROW_EXCEPTION(InvalidParameterException, "Parameter node is invalid ...");
            }
            else
            {
                remove(dynamic_cast<BTreeNode<T>*>(node), ret);
            }
    
            return ret;
        }
    

    mian.cpp测试:

    #include <iostream>
    #include "BTree.h"
    
    using namespace std;
    using namespace StLib;
    
    int main()
    {
        BTree<int> bt;
        BTreeNode<int>* n = NULL;
    
        bt.insert(1, NULL);
    
        n = bt.find(1);
        bt.insert(2, n);
        bt.insert(3, n);
    
        n = bt.find(2);
        bt.insert(4, n);
        bt.insert(5, n);
    
        n = bt.find(4);
        bt.insert(8, n);
        bt.insert(9, n);
    
        n = bt.find(5);
        bt.insert(10, n);
    
        n = bt.find(3);
        bt.insert(6, n);
        bt.insert(7, n);
    
        n = bt.find(6);
        bt.insert(11, n, LEFT);
    
        int a[] = {8, 9, 10, 11, 7};
    
        SharedPointer< Tree<int> > sp = bt.remove(3);
    
        for(int i=0; i<5; i++)
        {
            TreeNode<int>* node = sp->find(a[i]);
    
            while( node )
            {
                cout << node->value << " ";
                node = node->parent;
            }
    
            cout << endl;
        }
    
        return 0;
    }
    

    运行结果为:

    
    
    
    11 6 3 
    7 3 
    

    4.二叉树中结点的清除操作

    清除操作的定义:

    • void clear()
      1. 将二叉树中的所有结点清除 ( 释放堆中的结点 )

    二叉树中结点的清除:

    清除操作功能的定义:

    • free(node)
      1. 清除 node 为根结点的二叉树
      2. 释放二叉树中的每一个结点

    在BTree.h中实现结点的清除操作:

    protected:
        virtual void free(BTreeNode<T>* node)
        {
            if( node != NULL )
            {
                free(node->left);
                free(node->right);
    
                if( node->flag() )
                {
                    delete node;
                }
            }
        }
    public:
        void clear()
        {
            free(root());
    
            this->m_root = NULL;
        }
    

    5.小结

    • 二叉树的插入操作需要指明插入的位置
    • 插入操作必须正确处理指向父结点的指针
    • 插入数据元素时需要从堆空间中创建结点
    • 当数据元素插入失败时需要释放结点空间

    • 删除操作将目标结点所代表的子树移除
    • 删除操作必须完善处理父结点和子结点的关系
    • 清除操作用于销毁树中的每个结点
    • 销毁结点时判断是否释放对应的内存空间 ( 工厂模式 )

    最终的BTree.h代码:
    BTree.h

    #ifndef BTREE_H
    #define BTREE_H
    
    #include "Tree.h"
    #include "BTreeNode.h"
    #include "Exception.h"
    #include "LinkQueue.h"
    
    namespace StLib
    {
    
    template <typename T>
    class BTree : public Tree<T>
    {
    protected:
        virtual BTreeNode<T>* find(BTreeNode<T>* node, const T& value) const
        {
            BTreeNode<T>* ret = NULL;
    
            if( node != NULL )
            {
                if( node->value == value )
                {
                    return node;
                }
                else
                {
                    if( ret == NULL )
                    {
                        ret = find(node->left, value);
                    }
    
                    if( ret == NULL )
                    {
                        ret = find(node->right, value);
                    }
                }
            }
    
            return ret;
        }
    
        virtual BTreeNode<T>* find(BTreeNode<T>* node, BTreeNode<T>* obj) const
        {
            BTreeNode<T>* ret = NULL;
    
            if( node == obj )
            {
                return node;
            }
            else
            {
                if( node != NULL )
                {
                    if( ret == NULL )
                    {
                        ret = find(node->left, obj);
                    }
    
                    if( ret == NULL )
                    {
                        ret = find(node->right, obj);
                    }
                }
            }
    
            return ret;
        }
    
        virtual bool insert(BTreeNode<T>* n, BTreeNode<T>* np, BTNodePos pos)
        {
            bool ret = true;
    
            if( pos == ANY )
            {
                if( np->left == NULL )
                {
                    np->left = n;
                }
                else if( np->right == NULL )
                {
                    np->right = n;
                }
                else
                {
                    ret = false;
                }
            }
            else if( pos == LEFT )
            {
                if( np->left == NULL )
                {
                    np->left = n;
                }
                else
                {
                    ret = false;
                }
            }
            else if( pos == RIGHT )
            {
                if( np->right == NULL )
                {
                    np->right = n;
                }
                else
                {
                    ret = false;
                }
            }
            else
            {
                ret = false;
            }
    
            return ret;
        }
    
        virtual void remove(BTreeNode<T>* node, BTree<T>*& ret)
        {
            ret = new BTree<T>();
    
            if( ret == NULL )
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new tree ...");
            }
            else
            {
                if( root() == node )
                {
                    this->m_root = NULL;
                }
                else
                {
                    BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
    
                    if( parent->left == node )
                    {
                        parent->left = NULL;
                    }
                    else if( parent->right == node )
                    {
                        parent->right = NULL;
                    }
    
                    node->parent = NULL;
                }
    
                ret->m_root = node;
            }
        }
    
        virtual void free(BTreeNode<T>* node)
        {
            if( node != NULL )
            {
                free(node->left);
                free(node->right);
    
                if( node->flag() )
                {
                    delete node;
                }
            }
        }
    public:
        bool insert(TreeNode<T>* node)
        {
            return insert(node, ANY);
        }
    
        virtual bool insert(TreeNode<T>* node, BTNodePos pos)
        {
            bool ret = true;
    
            if( node != NULL )
            {
                if( this->m_root == NULL )
                {
                    node->parent = NULL;
                    this->m_root = node;
                }
                else
                {
                    BTreeNode<T>* np = find(node->parent);
    
                    if( np != NULL )
                    {
                        ret = insert(dynamic_cast<BTreeNode<T>*>(node), np, pos);
                    }
                    else
                    {
                        THROW_EXCEPTION(InvalidParameterException, "Invalid parent tree node ...");
                    }
                }
            }
            else
            {
                THROW_EXCEPTION(InvalidParameterException, "Parameter node can not be NULL ...");
            }
    
            return ret;
        }
    
        bool insert(const T& value, TreeNode<T>* parent)
        {
            return insert(value, parent, ANY);
        }
    
        virtual bool insert(const T& value, TreeNode<T>* parent, BTNodePos pos)
        {
            bool ret = true;
            BTreeNode<T>* node = BTreeNode<T>::NewNode();
    
            if( node == NULL )
            {
                THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create new node ...");
            }
            else
            {
                node->value = value;
                node->parent = parent;
    
                ret = insert(node, pos);
    
                if( !ret )
                {
                    delete node;
                }
            }
    
            return ret;
        }
    
        SharedPointer< Tree<T> > remove(const T& value)
        {
            BTree<T>* ret = NULL;
            BTreeNode<T>* node = find(value);
    
            if( node == NULL )
            {
                THROW_EXCEPTION(InvalidParameterException, "Can not find the tree node via value ...");
            }
            else
            {
                remove(node, ret);
            }
    
            return ret;
        }
    
        SharedPointer< Tree<T> > remove(TreeNode<T>* node)
        {
            BTree<T>* ret = NULL;
    
            node = find(node);
    
            if( node == NULL )
            {
                THROW_EXCEPTION(InvalidParameterException, "Parameter node is invalid ...");
            }
            else
            {
                remove(dynamic_cast<BTreeNode<T>*>(node), ret);
            }
    
            return ret;
        }
    
        BTreeNode<T>* find(const T& value) const
        {
            return find(root(), value);
        }
    
        BTreeNode<T>* find(TreeNode<T>* node) const
        {
            return find(root(), dynamic_cast<BTreeNode<T>*>(node));
        }
    
        BTreeNode<T>* root() const
        {
            return dynamic_cast<BTreeNode<T>*>(this->m_root);
        }
    
        int degree() const
        {
            return NULL;
        }
    
        int count() const
        {
            return NULL;
        }
    
        int height() const
        {
            return NULL;
        }
    
        void clear()
        {
            free(root());
    
            this->m_root = NULL;
        }
    
        ~BTree()
        {
            clear();
        }
    };
    
    }
    
    #endif // BTREE_H
    
  • 相关阅读:
    HDU4507 吉哥系列故事――恨7不成妻(数位dp)
    UCF Local Programming Contest 2017 G题(dp)
    ICPC Latin American Regional Contests 2019 I题
    UCF Local Programming Contest 2017 H题(区间dp)
    HDU2089 不要62
    AcWing1084 数字游戏II(数位dp)
    UCF Local Programming Contest 2017 F题(最短路)
    Google Code Jam 2019 Round 1A Pylons(爆搜+贪心)
    AcWing1083 Windy数(数位dp)
    Vue
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10163819.html
Copyright © 2011-2022 走看看