c++二叉树

二叉树进阶

​ 二叉搜索树天然就适合查找,对于满二叉树或者完全二叉树,最多搜索lgn次(就像是有序数组二分查找,每次搜索都会减少范围),极端情况简化成单链表就要走n次,即要走高度次,时间复杂度是O(N)。所以需要用时间复杂度为O(lgn)的AVL树(平衡二叉树)或者RB树(红黑树)解决。

​ 按中序遍历,得到的结果就是有序的,升序;后序删除方便很多,不用保留前面的值;拷贝不可以调用插入,否则结构会发生巨大的变化,而是使用前序来赋值 。

​ 相较于普通的二叉树,增删查改就有了意义,而有序数组二分查找是不可以的,挪动数据效率很低。

​ 二叉搜索树不允许有重复,key一般要唯一。

1.1概念

二叉搜索树又称二叉排序树它或者是一棵空树,或者是具有以下性质的二叉树:

​ 1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 ;

​ 2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 ;

​ 3.它的左右子树也分别为二叉搜索树;

2.二叉搜索树非递归模拟实现

c++ 复制代码
#pragma once
#include <cassert>
namespace BinarySearchTree
{
    template <class K>
    struct BSTreeNode
    {
        BSTreeNode(const K &key = 0) : left_(nullptr), right_(nullptr), key_(key) {}
        BSTreeNode<K> *left_;
        BSTreeNode<K> *right_;
        K key_;
    };

    template <class K>
    class BSTree
    {
        // 内嵌类型
        typedef BSTreeNode<K> node;

    public:
        // 默认成员函数
        BSTree() : root_(nullptr)
        {
        }
        ~BSTree() {}

    public:
        // 普通成员函数
        bool insert(const K &key);
        void inorder()
        {
            _inorder(root_);
        }
        void _inorder(node *root);
        bool find(const K &key);
        bool erase(const K &key);

    private:
        // 成员变量
        node *root_;
    };
    template <class K>
    bool BSTree<K>::insert(const K &key)
    {
        if (root_ == nullptr)
        {
            root_ = new node(key);
            return true;
        }
        node *cur = root_;
        node *parent = root_;
        while (cur)
        {
            if (cur->key_ == key)
            {
                return false;
            }
            else if (key > cur->key_)
            {
                parent = cur;
                cur = cur->right_;
            }
            else
            {
                parent = cur;
                cur = cur->left_;
            }
        }
        cur = new node(key);
        if (key > parent->key_)
        {
            parent->right_ = cur;
        }
        else
        {
            parent->left_ = cur;
        }
        return true;
    }
    template <class K>
    void BSTree<K>::_inorder(BSTree<K>::node *root)
    {
        if (root == nullptr)
        {
            return;
        }
        _inorder(root->left_);
        cout << root->key_ << " ";
        _inorder(root->right_);
    }
    template <class K>
    bool BSTree<K>::find(const K &key)
    {
        if (root_ == nullptr)
        {
            return false;
        }
        node *cur = root_;
        while (cur)
        {
            if (key == cur->key_)
            {
                return true;
            }
            else if (key > cur->key_)
            {
                cur = cur->right_;
            }
            else
            {
                cur = cur->left_;
            }
        }
        return false;
    }
    template <class K>
    bool BSTree<K>::erase(const K &key)
    {
        node *cur = root_;
        node *parent = cur;
        while (cur)
        {
            if (key == cur->key_)
            {
                // 找到了,托孤要考虑删root;
                // 没有孩子,托孤nullptr
                // 有一个孩子,托孤
                if (cur->left_ == nullptr)
                {
                    if (cur == root_)
                    {
                        parent = cur->right_;
                    }
                    else
                    {
                        if (key_ > parent->key_)
                        {
                            parent->right_ = cur->right_;
                        }
                        else
                        {
                            parent->left_ = cur->right_;
                        }
                    }
                }
                else if (cur->right_ == nullptr)
                {
                    if (cur == root_)
                    {
                        parent = cur->left_;
                    }
                    else
                    {
                        if (key_ > parent->key_)
                        {
                            parent->right_ = cur->left_;
                        }
                        else
                        {
                            parent->left_ = cur->left_;
                        }
                    }
                }
                else // 有两个孩子,要取左子树最右或者右子树最左
                {
                    node *leftmax = cur->left_; // 可能cur->left为leftmax
                    node *pleftmax = cur;
                    while (leftmax->right_)
                    {
                        pleftmax = leftmax;
                        leftmax = leftmax->right_;
                    }
                    std::swap(cur->key_, leftmax->key_);
                    if (pleftmax->left_ == leftmax)
                    {
                        pleftmax->left_ = leftmax->left_;
                    }
                    else
                    {
                        pleftmax->right_ = leftmax->left_;
                    }
                    cur = leftmax;
                }
                delete cur;
                return true;
            }
            else if (key > cur->key_)
            {
                parent = cur;
                cur = cur->right_;
            }
            else
            {
                parent = cur;
                cur = cur->left_;
            }
        }
        return false;
    }

}

3.二叉搜索树优点

​ 1.查找效率高;

​ 2.可以顺便实现排序,升序;

​ 3.插入删除效率都不错;

4.二叉搜索树递归实现

c++ 复制代码
#pragma once
#include <cassert>
namespace BinarySearchTree
{
    template <class K>
    struct BSTreeNode
    {
        BSTreeNode(const K &key = 0) : left_(nullptr), right_(nullptr), key_(key) {}
        BSTreeNode<K> *left_;
        BSTreeNode<K> *right_;
        K key_;
    };

    template <class K>
    class BSTree
    {
        // 内嵌类型
        typedef BSTreeNode<K> node;

    public:
        // 默认成员函数
        BSTree() : root_(nullptr)
        {
        }
        BSTree(const BSTree<K> &t)
        {
            root_ = copy(t.root_);
        }
        BSTree<K> &operator=(BSTree<K> t)
        {
            swap(*this, t);
            return *this;
        }
        ~BSTree()
        {
            destroy(root_);
        }

    public:
        // 普通成员函数
        void swap(BSTree<K> &t);
        bool insert(const K &key)
        {
            return _insert(root_, key);
        }
        void inorder()
        {
            _inorder(root_);
            cout << endl;
        }
        bool find(const K &key)
        {
            return _find(root_, key);
        }
        bool erase(const K &key)
        {
            return _erase(root_, key);
        }

    private:
        // 私有成员
        node *copy(node *root);
        void destroy(node *&root);
        bool _insert(node *&root, const K &key);
        bool _find(node *root, const K &key);
        void _inorder(node *root);
        bool _erase(node *&root, const K &key);
        node *root_;
    };
    template <class K>
    bool BSTree<K>::_insert(node *&root, const K &key)
    {
        if (root == nullptr)
        {
            root = new node(key);
            return true;
        }
        if (key > root->key_)
        {
            return _insert(root->right_, key);
        }
        else if (key < root->key_)
        {
            return _insert(root->left_, key);
        }
        else
        {
            return false;
        }
    }
    template <class K>
    void BSTree<K>::_inorder(node *root)
    {
        if (root == nullptr)
        {
            cout << "nullptr"
                 << " ";
            return;
        }
        _inorder(root->left_);
        cout << root->key_ << " ";
        _inorder(root->right_);
    }
    template <class K>
    bool BSTree<K>::_find(node *root, const K &key)
    {
        if (root == nullptr)
        {
            return false;
        }
        if (key > root->key_)
        {
            return _find(root->right_, key);
        }
        else if (key < root->key_)
        {
            return _find(root->left_, key);
        }
        else
        {
            return true;
        }
    }
    template <class K>
    bool BSTree<K>::_erase(node *&root, const K &key)
    {
        if (root == nullptr)
        {
            return false;
        }
        if (key > root->key_)
        {
            return _erase(root->right_, key);
        }
        else if (key < root->key_)
        {
            return _erase(root->left_, key);
        }
        else
        {
            node *del = root;
            if (root->left_ == nullptr)
            {
                root = root->right_;
            }
            else if (root->right_ == nullptr)
            {
                root = root->left_;
            }
            else
            {
                node *leftmax = root->left_;
                while (leftmax->right_)
                {
                    leftmax = leftmax->right_;
                }
                std::swap(leftmax->key_, root->key_);
                return _erase(root->left_, key);
            }
            delete del;
            return true;
        }
    }
    template <class K>
    void BSTree<K>::destroy(node *&root)
    {
        if (root == nullptr)
        {
            return;
        }
        destroy(root->left_);
        destroy(root->right_);
        delete root;
        root = nullptr;
    }
    template <class K>
    typename BSTree<K>::node *BSTree<K>::copy(node *root)
    {
        if (root == nullptr)
        {
            return nullptr;
        }
        node *newnode = new node(root->key_);
        newnode->left_ = copy(root->left_);
        newnode->right_ = copy(root->right_);
        return newnode;
    }
    template <class K>
    void BSTree<K>::swap(BSTree<K> &t)
    {
        std::swap(root_, t.root_);
    }
}

5.二叉搜索树的应用场景

5.1key的搜索模型(在不在的场景)

​ 门禁系统、车辆输入系统、查找单词是否拼写错误,将词库放到一颗搜索树之中,然后find。

5.1key/value的搜索模型(通过一个值找另外一个值)

​ 手机号找快递信息、停车场(按时计费)、身份证检票查找车票信息,不用制造车票并往车票里写入信息;

c++ 复制代码
namespace key_value
{
    template <class K, class V>
    struct BSTreeNode
    {
        BSTreeNode(const K &key = K(), const V &value = V()) : left_(nullptr), right_(nullptr), key_(key), value_(value) {}
        BSTreeNode<K, V> *left_;
        BSTreeNode<K, V> *right_;
        K key_;
        V value_;
    };

    template <class K, class V>
    class BSTree
    {
        // 内嵌类型
        public:
        typedef BSTreeNode<K, V> node;

        public:
        // 默认成员函数
        BSTree() : root_(nullptr)
        {
        }

        ~BSTree()
        {
        }

        public:
        // 普通成员函数
        bool insert(const K &key, const V &value)
        {
            return _insert(root_, key, value);
        }
        void inorder()
        {
            _inorder(root_);
            cout << endl;
        }
        node *find(const K &key)
        {
            return _find(root_, key);
        }
        bool erase(const K &key)
        {
            return _erase(root_, key);
        }

        private:
        // 私有成员
        bool _insert(node *&root, const K &key, const V &value);
        node *_find(node *root, const K &key);
        void _inorder(node *root);
        bool _erase(node *&root, const K &key);
        node *root_;
    };
    template <class K, class V>
    bool BSTree<K, V>::_insert(node *&root, const K &key, const V &value)
    {
        if (root == nullptr)
        {
            root = new node(key, value);
            return true;
        }
        if (key > root->key_)
        {
            return _insert(root->right_, key, value);
        }
        else if (key < root->key_)
        {
            return _insert(root->left_, key, value);
        }
        else
        {
            return false;
        }
    }
    template <class K, class V>
    void BSTree<K, V>::_inorder(node *root)
    {
        if (root == nullptr)
        {
            return;
        }
        _inorder(root->left_);
        cout << root->key_ << " : " << root->value_ << "  ";
        _inorder(root->right_);
    }
    template <class K, class V>
    typename BSTree<K, V>::node *BSTree<K, V>::_find(node *root, const K &key)
    {
        if (root == nullptr)
        {
            return nullptr;
        }
        if (key > root->key_)
        {
            return _find(root->right_, key);
        }
        else if (key < root->key_)
        {
            return _find(root->left_, key);
        }
        else
        {
            return root;
        }
    }
    template <class K, class V>
    bool BSTree<K, V>::_erase(node *&root, const K &key)
    {
        if (root == nullptr)
        {
            return false;
        }
        if (key > root->key_)
        {
            return _erase(root->right_, key);
        }
        else if (key < root->key_)
        {
            return _erase(root->left_, key);
        }
        else
        {
            node *del = root;
            if (root->left_ == nullptr)
            {
                root = root->right_;
            }
            else if (root->right_ == nullptr)
            {
                root = root->left_;
            }
            else
            {
                node *leftmax = root->left_;
                while (leftmax->right_)
                {
                    leftmax = leftmax->right_;
                }
                std::swap(leftmax->key_, root->key_);
                return _erase(root->left_, key);
            }
            delete del;
            return true;
        }
    }
}
相关推荐
StrokeAce1 小时前
linux桌面软件(wps)内嵌到主窗口后的关闭问题
linux·c++·qt·wps·窗口内嵌
一颗花生米。2 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼2 小时前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐012 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
通信仿真实验室3 小时前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&3 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
家有狸花4 小时前
VSCODE驯服日记(三):配置C++环境
c++·ide·vscode
dengqingrui1235 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝5 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O5 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树