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
    
  • 相关阅读:
    MySQL的max()函数使用时遇到的小问题
    scp命令需要指定端口时要紧跟在scp后
    linux系统之间基于密钥对免输入密码登陆
    c++的引用用法
    预测模型
    mysql出现ERROR 1366 (HY000):的解决办法
    R语言可视化--颜色
    R语言可视化--ggplot函数
    R语言可视化--qplot函数
    R语言可视化二
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10163819.html
Copyright © 2011-2022 走看看