二叉搜索树的增删查(递归与非递归)实现

本文详细介绍了二叉搜索树的插入、删除和查找操作,包括递归和非递归实现。在插入操作中,通过维护当前节点和父节点避免了重复元素。查找操作简单直接,根据节点值的大小决定方向。删除操作则分为左、右子树为空和都不为空三种情况,确保树保持二叉搜索树性质。文章还提到了中序遍历和实现key-value树的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉搜索树(BinarySearchTree):
二叉搜索树性质:
1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。
2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
4. 左右子树都是二叉搜索树。

如图:是一个二叉搜索树
第三方

本文将实现二叉搜索树的插入删除查找

我们先定义一个二叉搜索树的结点结构体

template<class K>
struct BinarySearchTreeNode
{
   
    BinarySearchTreeNode<K>* _left;
    BinarySearchTreeNode<K>* _right;

    K _key;
    BinarySearchTreeNode(const K& key)
        :_left(NULL)
        , _right(NULL)
        , _key(key)
    {}
};

插入

插入的返回类型为bool,因为有可能会插入失败
搜索二叉树还有一个特点就是不能有重复的数,因为有重复的数会导致冗余

思想(非递归):我们完成插入的函数需要定义两个结点,cur和parent,我们需要用parent来记录cur的父亲,进入函数首先判断这棵树是否为空,若为空,直接新建结点,并且返回值为true,我们将_root给cur,我们首先要遍历一下这棵树,比根小的向左边走,比根大的向右边走,在这里每次走之前都要先将cur的值给parent,如果相等则返回false(二叉搜索树不能有重复的结点,会冗余),
找到key放的位置后,我们要判断key在parent的左边还是右边,如果在左边,则让parent->_left等于存放key值的结点,反之让parent->_right等于存放key的结点。最后返回true,这样我们的非递归插入就实现好了。(注意:在这里的插入不能用我们下面实现的Find()函数,因为Find()函数只能返回当前结点,而当前节点的parent找不到。没有parent我们Insert()就无法判断结点放左边还是右边)

bool Insert(const K& key)
    {
        if (_root == NULL)
        {
            _root = new Node(key);
            return true;
        }
        Node* parent = NULL;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }

        if (parent->_key > key)
        {
            Node* tmp = new Node(key);
            parent->_left = tmp;
        }
        else
        {
            Node* tmp = new Node(key);
            parent->_right = tmp;
        }
        return true;

    }

插入(递归实现)思想:
插入的递归实现主要是利用了root的引用,在这里root有两层含义,一个是当前的值,一个是上一层的值也就是当前值的parent。递归实现代码相对简单,但是不太容易理解。

    bool _InsertR(Node* &root, const K& key)
    {
        if (root == NULL)
        {
            root = new Node(key);
            return true;
        }
        if (root->_key > key)
        {
            _InsertR(root->_left,key);
        }
        else if (root->_key < key)
        {
            _InsertR(root->_right,key);
        }
        else
        {
            return false;
        }

    }

查找
思想:查找的函数思想就很简单了,只要cur为真就进入循环:比根小的向左边走,比根大的向右边走等于根就返回cur.

Node* Find(const K& key)
    {
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key < key)
            {
                cur = cur->_right;
            }
            else if (cur->_key > key)
            {
                cur = cur->_right;
            }
            else
            {
                return cur;
            }
        }
        return NULL;
    }

删除
二叉搜索树的删除是在这里最重要的
删除可以分为三种情况:
1,左为空
2,右为空
3,两边都不为空。

删除的非递归思想:
我们先遍历一下这棵树,找到要删除的结点,我们把当前要删除的结点给del,先看左为空,
先判断当前要删除的结点是不是根,是根的话就把根给根的右孩子。
不是根的话,我们需要判断的是cur在parent的左边还是右边
用一幅图来讲解
的

右为空的情况跟作左为空是相似的,就还是用图直白的解释一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值