Binary Search Tree代码实现

这篇博客详细介绍了如何在二叉搜索树中进行插入、查找和删除操作。删除操作的实现重点在于找到要删除节点的前驱节点来替代它。博客提供了完整的C++代码实现,并通过示例展示了插入和删除过程,同时包含了一个用于检查树结构的辅助函数。

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

插入查找都很简单,主要是删除
  • 删除思路:
  • 从要删除的结点左子树中找到最右边的结点(要删除结点的前驱,这个结点是要删除的结点的左子树中值最大的结点),替代要删除的结点。代码中用get_max_left()函数实现
  • 特殊情况:
  • ①要删除的点是根节点的情况,记得更新根结点
  • ② 要删除的结点没有左子树,那么直接用右子树代替要删除的结点的位置,(右子树也为空,说明要删除结点是叶子节点,也可以用空右子树(nullptr)代替)
代码入下
/*
删除
①找到目标结点 否则报错
②如果有左儿子,找左子树最右边的点替代当前结点,如果没有左儿子,把这棵树的右儿子顶替它的位置
④注意如果删除结点是root记得修改root

 */

/*
插入
①找到目标位置,如果这个数据已经有了,就不插入,数据没有,那么插入
 */

/*

查找while
返回指针
 */

#include <bits/stdc++.h>
using namespace std;

struct ty
{
    ty(int x, ty *lnext = nullptr, ty *rnext = nullptr) : val(x), left(lnext), right(rnext) {}
    int val; //值
    int row; //在树的那一层,帮助遍历
    ty *left;
    ty *right;
};

ty *root = nullptr;

//返回指针,如果没查到返回nullptr
ty *search(ty *now, int val)
{
    while (now != nullptr)
    {
        if (val > now->val)
            now = now->right;
        else if (val < now->val)
            now = now->left;
        else
            return now;
    }

    return now;
}

void insert(ty *now, int val)
{
    if (root == nullptr)
    {
        root = new ty(val);
        return;
    }
    while (true)
    {
        if (now->val == val)
        {
            cout << "值" << val << "已有" << endl;
            return;
        }
        if (now->val > val)
        {
            if (now->left == nullptr)
            {
                now->left = new ty(val);
                return;
            }
            now = now->left;
        }
        else
        {
            if (now->right == nullptr)
            {
                now->right = new ty(val);
                return;
            }
            now = now->right;
        }
    }
};

//传入要删除的点 取出左子树 最右边的点,如果没有左儿子就返回nullptr
ty *get_max_left(ty *father)
{
    ty *now = father->left;

    if (now == nullptr) //如果要删除结点没有左儿子
        return now;
    if (now->right == nullptr) //左儿子结点没有右儿子,那么它自己就是最右边的点
    {
        father->left = now->left; // 左儿子把左子树返回给父节点
        now->left = nullptr;      //割断左儿子和它左子树
        return now;               //返回左儿子(最右边的结点)
    }

    while (now->right != nullptr) //不断的找最右边的结点
    {
        father = now;
        now = now->right;
    }
    father->right = now->left; //最右边结点把左子树返回给父节点
    now->left = nullptr;       //割断最右边结点和它左子树的关系
    return now;                //返回最右边的结点
}

//思路:从要删除的结点左子树中找到最右边的结点(要删除结点的前驱),替代要删除的结点
//特殊情况:①要删除的点是根节点的情况,记得更新根结点② 要删除的结点没有左子树,那么直接用右子树代替要删除的结点的位置,(右子树也为空,说明要删除结点是叶子节点,也可以用空右子树(nullptr)代替)

void erase(ty *now, int val)
{
    ty *father = nullptr;
    //先找到目标结点
    while (now != nullptr)
    {
        if (now->val > val)
        {
            father = now;
            now = now->left;
        }
        else if (now->val < val)
        {
            father = now;
            now = now->right;
        }
        else
            break;
    }

    //说明没有该结点
    if (now == nullptr)
    {
        cout << "BST中不存在值为" << val << "的结点" << endl;
        return;
    }

    ty *max_left = get_max_left(now); //取出目标结点左子树最右边的点

    if (max_left == nullptr) //左子树是空的 从左子树找不到替代要删除的结点,那么就让右子树替代要删除的结点
    {

        if (father == nullptr) //要删除结点是根
        {
            root = now->right; //右子树是新的根
            delete now;
        }
        else //要删除结点不是根
        {
            //用val 判断要删除的结点是父节点的左儿子还是右儿子
            if (val > father->val) //右儿子
                father->right = now->right;

            else
                father->left = now->right;
            delete now;
        }
    }
    else //左子树非空
    {
        if (father == nullptr) //要删除结点是根
        {
            root = max_left;
            max_left->left = now->left;
            max_left->right = now->right;
        }
        else //要删除结点不是根
        {
            //用val 判断要删除的结点是父节点的左儿子还是右儿子
            if (val > father->val) //右儿子
                father->right = max_left;

            else
                father->left = max_left;

            max_left->left = now->left;
            max_left->right = now->right;
        }

        delete now;
    }
}

//用来检查binary search tree 的结构
void check(ty *root)
{
    queue<ty *> q;
    root->row = 1;
    q.push(root);
    int last = 1;
    while (!q.empty())
    {
        ty *tmp = q.front();
        q.pop();
        if (tmp->row > last)
        {
            ++last;
            cout << endl;
        }

        cout << tmp->val << ' ';

        if (tmp->left)
        {
            tmp->left->row = last + 1;
            q.push(tmp->left);
        }

        if (tmp->right)
        {
            tmp->right->row = last + 1;
            q.push(tmp->right);
        }
    }
    cout << endl;
}

int main()
{
    int ch[10] = {7, 3, 10, 12, 5, 1, 9};
    for (int i = 0; i < 7; ++i)
    {

        insert(root, ch[i]); //插入结点
        check(root);         //检查结构

        cout << "---------------------" << endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值