当前位置: 首页 > news >正文

【算法】BST的非递归插入,删除,查询

BST

        所谓二叉搜索树(Binary Search Tree,简称 BST)大家应该都不陌生,它是一种特殊的二叉树。对于二叉树上的每一个节点,如果满足左孩子的值 < 父节点的值 < 右孩子的值,把满足上面性质的二叉树就称作BST树,Binary Search/Sort Tree。

        有了BST的这种特性,就可以在二叉树中做类似二分搜索的操作,搜索一个元素的效率很高。

特点:

  1. 有序性:对于BST中的每个节点,其左子树中的所有节点的值都小于该节点的值,而右子树中的所有节点的值都大于该节点的值。
  2. 递归性:BST的每个子树也是BST,即子树中的节点仍然满足有序性和递归性。
  3. 无重复值:BST中不允许存在相同值的节点。

        由于BST的有序性,它具有快速的查找、插入和删除操作的特点,因此被广泛应用于数据结构和算法中。

BSTree的数据定义:

// BSTREE代码实现
template <typename T, typename Compare = less<T>>
class BSTree
{
private:
    /* data */
    // 节点定义
    struct Node
    {
        Node(T data = T())
            : data_(data), left_(nullptr), right_(nullptr)
        {
        }
        T data_;
        Node *left_;
        Node *right_;
    };

    Node *root_;

public:
    BSTree()
        : root_(nullptr)
    {
    }
    ~BSTree()
    {
    }
};

        使用类模板,使它可以存入各种不同数据类型,而且c++中提供Compare函数对象,可以根据用户需要,来比较不同类型的数据。

BST树的非递归插入

root => 根节点 nullptr

BST如果为空,root => 新生成的节点来存放插入的数据

BST如果不为空,从根节点开始比较,找到合适的位置,生成新的节点,并把节点的地址写入父节点相应的地址域当中。

BSTree非递归插入操作:

	void n_insert(const T &val)
    {
        // 树为空,生成根节点
        if (root_ == nullptr)
        {
            root_ = new Node(val);
            return;
        }

        // 搜索合适位置,记录父节点位置
        Node *parent = nullptr;
        Node *cur = root_;
        while (cur != nullptr)
        {
            if (cur->data_ > val)
            {
                parent = cur;
                cur = cur->left_;
            }
            else if (cur->data_ < val)
            {
                parent = cur;
                cur = cur->right_;
            }
            else
            {
                // 不插入元素相同的值
                return;
            }
        }
        // 把新节点插入到parent节点的孩子上
        if(val < parent->data_)
        {
            parent->left_ = new Node(val);
        }
        else
        {
            parent->right_ = new Node(val);
        }
    }

BST树的非递归删除

1.没有孩子的节点,父节点地址域nullptr

2.有一个孩子,把孩子写入父节点地址域

3.删除的节点有两个孩子,找待删除节点的前驱节点(或者后继节点),用前驱或者后继节点的值把待删除节点的值覆盖掉,然后直接删除前驱或者后继节点就可以了。

前驱节点:当前节点左子树中值最大的节点。

后继节点:当前节点右子树中值最小的节点。

// 非递归的删除操作
    void n_remove(const T &val)
    {
        if(root_ == nullptr)
        {
            return ;
        }
        Node *parent = nullptr;
        Node *cur = root_;
        while(cur != nullptr)
        {
            if(cur->data_ == val)
            {
                break;
            }
            else if(!Compare(cur->data_, val))
            {
                parent = cur;
                cur = cur->left_;
            }
            else
            {
                parent = cur;
                cur = cur->right_;
            }
        }
        if(cur == nullptr)
        {
            return; // 没找到待删除节点
        }
        if(cur->left_ != nullptr && cur->right_ != nullptr)
        {
            parent = cur;
            Node *pre = cur->left_;
            while(pre->right_ != nullptr)
            {
                parent = pre;
                pre = pre->right_;
            }
            cur->data_ = pre->data_;
            cur = pre; // 让cur指向前驱节点,转化成情况1,2
        }
        // cur指向删除节点,parent指向其父节点,统一处理情况1,2
        Node *child = cur->left_;
        if(child == nullptr)
        {
            child = cur->right_;
        }
        if(parent == nullptr)
        {
            root_ = child;
        }
        else
        {
            if (parent->left_ == cur)
            {
                parent->left_ = child;
            }
            else
            {
                parent->right_ = child;
            }
        }
        delete cur;
    }

BST树的非递归查询

// 非递归查询操作
    bool n_query(const T& val)
    {
        Node *cur = root_;
        while(cur != nullptr)
        {
            if(cur->data_ == val)
            {
                return ture;
            }
            else if(Compare(cur->data_, val))
            {
                cur = cur->right_;
            }
            else
            {
                cur = cur->left_;
            }
        }
        return false;
    }

相关文章:

  • 蓝桥杯[每日两题] 练习题:盛最多水的容器 三数之和(java版)
  • flutter的HTTP headers用法介绍
  • 【组件安装】Rocky 8.10 安装Local License Server 25.03.0 for Linux
  • Python基本语法——变量
  • Conda环境搭建实战指南:打造高效开发环境
  • DeepSeek开源Day2:DeepEP技术详解
  • Ae 效果详解:VR 降噪
  • tkinter上canvas展示图片报错(mac系统)
  • 【人工智能】随机森林的智慧:集成学习的理论与实践
  • Linux练级宝典->Linux进程概念介绍
  • ROS2学习笔记2
  • 使用Vue CLI从零搭建企业级项目实战(Vue3+全家桶)
  • 【Axure原型分享】数字滚动——同时滚动效果
  • UIToolkit(一)
  • 【redis】pipeline管道
  • 第八章:C++ 实践
  • 调试正常 ≠ 运行正常:Keil5中MicroLIB的“量子态BUG”破解实录
  • 【Java面试题汇总】Java面试100道最新合集!
  • 笔记六:单链表链表介绍与模拟实现
  • cocos creator使用mesh修改图片为圆形,减少使用mask,j减少drawcall,优化性能
  • 从《缶翁的世界》看吴昌硕等湖州籍书画家对海派的影响
  • 广药集团原董事长李楚源被“双开”:去年8月被查,曾多次发表争议言论
  • 俄媒:俄乌代表团抵达谈判会场
  • 2025年“新时代网络文明公益广告”征集展示活动在沪启动
  • 自强!助残!全国200个集体和260名个人受到表彰
  • 外企聊营商|武田制药:知识产权保护助创新药研发