数据结构-----二叉搜索树(C++)

一.概念介绍

二叉搜索树,它如果不为空树,则它满足条件:1.左子树不为空,则左子树上的所有节点值小于根节点的值 2.右子树不为空,则右子树上所有节点值大于根节点的值 3.它的左右子树也分别为二叉搜索树。

如同就是一个标准的二叉搜索树:

二.对二叉搜索树代码的实现

  1. key 搜索树模型 :对节点的创建

模板 K :表示的是所储存的值为K类型。

template<class K>
struct BSTreeNode
{
    BSTreeNode<K>* _left;
    BSTreeNode<K>* _right;
    K _key;
    
    // 对节点的创建
BSTreeNode(const K& key)
    :_left(nullptr)
    , _right(nullptr)
    , _key(key)
{}
​
};

对该模型其他功能的实现:

template<class K>
class BSTree
{
    //对 命名 的简化
    typedef BSTreeNode<K>  Node;
public:
    // 创建新的节点,插入新的节点
    bool Insert(K& e)
    {
        if (_root == nullptr)
        {
            _root = new Node(e);
            return true;
        }
​
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key > e)
            {
                if (cur->_left)
                    cur = cur->_left;
                else
                    cur->_left = new Node(e), cur = nullptr;
            }
            else if (cur->_key < e)
            {
                if (cur->_right)
                    cur = cur->_right;
                else
                    cur->_right = new Node(e), cur = nullptr;
            }
            else
            {
                return false;
            }
        }
​
        return true;
    }
    // 删除key == e 的相关节点   细致讲解请看下面难点解析
    bool Erase(const K& e)
    {
        Node* parent = nullptr;
        Node* cur = _root;
​
        while (cur)
        {
            if (cur->_key < e)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > e)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                //删除
                if (cur->_left == nullptr)
                {
                    if (cur == _root)
                    {
                        _root = cur->_right;
                    }
                    else
                    {
                        if (cur == parent->_left)
                        {
                            parent->_left = cur->_right;
                        }
                        else
                        {
                            parent->_right = cur->_right;
                        }
                    }
​
                    delete cur;
                }
                else if (cur->_right == nullptr)
                {
                    if (cur == _root)
                    {
                        _root = cur->_left;
                    }
                    else
                    {
                        if (cur == parent->_left)
                        {
                            parent->_left = cur->_left;
                        }
                        else
                        {
                            parent->_right = cur->_left;
                        }
                    }
​
                    delete cur;
                }
                else
                {
                    Node* rightMinParent = cur;
                    Node* rightMin = cur->_right;
                    while (rightMin->_left)
                    {
                        rightMinParent = rightMin;
                        rightMin = rightMin->_left;
                    }
​
                    swap(cur->_key, rightMin->_key);
​
                    if (rightMinParent->_left == rightMin)
                        rightMinParent->_left = rightMin->_right;
                    else
                        rightMinParent->_right = rightMin->_right;
​
                    delete rightMin;
                }
​
                return true;
            }
​
        }
​
        return false;
    }
    //找到相关的值的节点
    bool Find(const K& e)
    {
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key < e)
            {
                cur = cur->_right;
            }
            else if (cur->_key > e)
            {
                cur = cur->_left;
            }
            else
            {
                return true;
            }
        }
​
        return false;
    }
    //中序遍历
    void InOrder()
    {
        _InOrder(_root);
    }
private:
    void _InOrder(Node* root)
    {
        if (root == nullptr)
        {
            return;
        }
​
        _InOrder(root->_left);
        cout << root->_key << " ";
        _InOrder(root->_right);
    }
private:
    Node* _root = nullptr;
};
// 附带的一组测试样例
void TestBSTree1()
{
    int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
    BSTree<int> t1;
    for (auto e : a)
    {
        t1.Insert(e);
    }
​
    t1.InOrder();
​
    t1.Erase(3);
    cout << endl;
    t1.Erase(8);
​
    t1.InOrder();
​
    for (auto e : a)
    {
        cout << endl;
        t1.Erase(e);
        t1.InOrder();
​
    }
}

三.二叉搜素树难点删除解析

四. key_value 的版本

与 key 的二叉搜素树基本类似,这里不做详细的说明:

仅仅不同的是有两个模板参数,K 与 V两个模板参数类型。

    namespace key_value
{
    //key 与 value 版本的
    template<class K, class V>
    struct BSTreeNode
    {
        BSTreeNode<K, V>* _left;
        BSTreeNode<K, V>* _right;
        K _key;
        V _value;
​
        BSTreeNode(const K& key,const V& value)
            :_left(nullptr)
            ,_right(nullptr)
            ,_key(key)
            ,_value(value)
        {}
    };
    
    template<class K,class V>
    class BSTree
    {
        typedef BSTreeNode<K, V> Node;
    public:
        bool Insert(const K& key, const V& value)
        {
            if (_root == nullptr)
            {
                _root = new Node(key,value);
                return true;
            }
    
            Node* cur = _root;
            while (cur)
            {
                if (cur->_key > key)
                {
                    if (cur->_left)
                        cur = cur->_left;
                    else
                        cur->_left = new Node(key,value), cur = nullptr;
                }
                else if (cur->_key < key)
                {
                    if (cur->_right)
                        cur = cur->_right;
                    else
                        cur->_right = new Node(key,value), cur = nullptr;
                }
                else
                {
                    return false;
                }
            }
    
            return true;
        }
​
​
        Node* Find(const K& key)
        {
            Node* cur = _root;
            while (cur)
            {
                if (cur->_key < key)
                {
                    cur = cur->_right;
                }
                else if (cur->_key > key)
                {
                    cur = cur->_left;
                }
                else
                {
                    return cur;
                }
            }
    
            return cur;
        }
    
        bool Erase(const K& key)
        {
            Node* cur = _root;
            Node* parent = nullptr;
    
            while (cur)
            {
                if (cur->_key > key)
                {
                    parent = cur;
                    cur = cur->_left;
                }
                else if(cur->_key <key)
                {
                    parent = cur;
                    cur = cur->_right;
                }
                else
                {
                    if (cur->_left == nullptr)
                    {
                        if (_root == cur)
                        {
                            _root = _root->_right;
                        }
                        else
                        {
                            if (cur == parent->_left)
                            {
                                parent->_left = cur->_right;
                            }
                            else
                            {
                                parent->_right = cur->_right;
                            }
                        }
    
                        delete cur;
                    }
                    else if (cur->_right == nullptr)
                    {
                        if (_root == cur)
                        {
                            _root = _root->_left;
                        }
                        else
                        {
                            if (cur == parent->_left)
                            {
                                parent->_left = cur->_left;
                            }
                            else
                            {
                                parent->_right = cur->_left;
                            }
                        }
    
                        delete cur;
                    }
                    else
                    {
                        Node* leftMax = cur->_left;
                        Node* leftMaxP = cur;
                        while (leftMax ->_right!= nullptr)
                        {
                            leftMaxP = leftMax;
                            leftMax = leftMax->_right;
                        }
    
                        swap(cur->_key, leftMax->_key);
                        swap(cur->_value, leftMax->_value);
​
​
•               
​
                        if (leftMaxP->_right == leftMax)
                        {
                            leftMaxP->_right = leftMax->_left;
                        }
                        else
                        {
                            leftMaxP->_left = leftMax->_left;
                        }
    
                        delete leftMax;
                    }
    
                    return true;
                }
            }
    
            return false;
            
        }
    
        void InOrder()
        {
            _InOrder(_root);
            cout << endl;
        }
    private:
            void _InOrder(Node* root)
            {
                if (root == nullptr)
                {
                    return;
                }
    
                _InOrder(root->_left);
                cout << root->_key << ":" << root->_value << endl;
                _InOrder(root->_right);
            }
    private:
        Node* _root = nullptr;
    };
    
    void TestBSTree2()
    {
        BSTree<string, string> dict;
        dict.Insert("string", "字符串");
        dict.Insert("left", "左边");
        dict.Insert("insert", "插入");
    
        string str;
        while (cin >> str)
        {
            BSTreeNode<string, string>* ret = dict.Find(str);
            if (ret)
            {
                cout << ret->_value << endl;
            }
            else
            {
                cout << "无此单词,请重新输入" << endl;
            }
        }
    }
    
    void TestBSTree3()
    {
        // 统计次数
        string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
​
"苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };
        BSTree<string, int> countTree;
        for (const auto& str : arr)
        {
            auto ret = countTree.Find(str);
            if (ret == nullptr)
            {
                countTree.Insert(str, 1);
            }
            else
            {
                ret->_value++;
            }
        }
    countTree.InOrder();
}
​
void TestBSTree4()
{
    BSTree<string, string> dict;
    dict.Insert("string", "字符串");
    dict.Insert("left", "左边");
    dict.Insert("insert", "插入");
    dict.Insert("hello", "你好");
    dict.Insert("love", "爱你");
    dict.Insert("rain", "雨");
    dict.Insert("banana", "香蕉");
    dict.Insert("ant", "蚂蚁");
    dict.Insert("zabro", "斑马");
    dict.Insert("yoyo", "悠悠球");
​
    dict.InOrder();
    dict.Erase("left");
    dict.Erase("love");
    dict.InOrder();
}
​
}

五. 总结

        二叉搜素树非常重要对于C++的学习来说,之后设计到的容器set 和 map 所依赖的基础都是 二叉搜索树,二叉搜素树的删除是相对难的重点,插入的时候是有去重操作的,对于插入重复的值是不能够成功插入的。希望大家能好好吸收这一章所讲述的内容,仔细研究代码,自己画图进行理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值