BSTree二叉搜索树的基本实现

BSTree的定义

struct BSTreeNode {
    BSTreeNode<K> *_left;
    BSTreeNode<K> *_right;
    K _key;

    BSTreeNode(const K &key)
            : _left(nullptr), _right(nullptr), _key(key) {}
};
class BSTree {
    typedef BSTreeNode<K> Node;
public:
private:
    Node *_root = nullptr;
};

和普通二叉树一样的数据结构,只不过二叉搜索树是有序的,即左子树节点的key值都比根节点key值小,右子树节点的key值都比根节点大,且以下所有子树的节点都依照这个规律,形成二叉搜索树

注意:二叉搜索树中没有重复的节点key值,即每个节点的值都是独一无二的。

在这里插入图片描述

中序遍历这棵树即是升序:1 2 3 4 5 6 7 8 9 10

插入新节点

bool Insert(const K &key)
    {
        if (_root == nullptr)
        {
            _root = new Node(key);
            return true;
        }

        Node *parent = nullptr;
        Node *cur = _root;
        while (cur)
        {
            if (key > cur->_key)//插入值大于key时,往右走
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)//插入值小于key时,往左走
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }

        cur = new Node(key);//新建插入值节点
        // 链接
        if (key > parent->_key)
        {
            parent->_right = cur;
        }
        else
        {
            parent->_left = cur;
        }

        return true;
    }

插入和普通二叉树的区别就是,它需要找到key值的合适位置来插入,当插入值大于节点值时,往节点右边走,插入值小于节点值时,往节点左边走,当插入值不大于且不小于时,不插入,因为二叉搜索树中的节点值不能有重复值。

找到合适位置后,创建新节点并链接到目标节点的左或右,大于目标节点链接右边,小于链接左边。

删除节点

删除节点要考虑三种不同的情况:

bool Erase(const K &key)
    {
        Node* parent = _root;
        Node* cur = _root;

        while (cur)
        {
            if (key > cur->_key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                // 删除
                // 1、左为空
                if (cur->_left == nullptr)
                {
                    if (parent->_left == cur)
                    {
                        parent->_left = cur->_right;
                    }
                    else
                    {
                        parent->_right = cur->_right;
                    }

                    delete cur;

                } // 2、右为空
                else if (cur->_right == nullptr)
                {
                    if (parent->_left == cur)
                    {
                        parent->_left = cur->_left;
                    }
                    else
                    {
                        parent->_right = cur->_left;
                    }

                    delete cur;
                }
                else
                {
                    // 找右树最小节点替代,也可以是左树最大节点替代
                    Node* prev=cur;
                    Node* minRight=cur->_right;
                    while(minRight->_left)
                    {
                        prev=minRight;
                        minRight=minRight->_left;
                    }
                    swap(cur->_key,minRight->_key);
                    if(prev->_left==minRight)
                    {
                        prev->_left=minRight->_right;
                    }
                    else
                    {
                        prev->_right=minRight->_right;
                    }
                    delete minRight;
                }

                return true;
            }
        }

        return false;
    }

1、叶子节点 (节点9)

在这里插入图片描述

parent的右边是需要删除的节点,那么直接链接cur的右边,即nullptr。

2、左右其中一个为空,另一个不为空 (节点8或节点2)

在这里插入图片描述

节点8:目标节点cur左边为空,如果cur在parent右边,那么就把cur的右节点“托孤”给parent的右边

节点2:目标节点cur右边为空,如果cur在patent左边,那么就把cur的左节点”托孤“给parent的左边

托孤完成后delete目标节点cur即可。

3、左右都不为空

找到要删除的节点cur后,找它右子树最小的节点,让右子树最小的节点来代替它的位置。

在这里插入图片描述

先交换key值,如果prev右边是最小节点,那么让最小节点的右边继承给prev右边。

在这里插入图片描述
如果prev左边边是最小节点,那么让最小节点的右边继承给prev左边。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值