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

C++二叉搜索树搜索二叉树二叉排序树

C++二叉搜索树

1. 二叉搜索树的概念

二叉搜索树BST,Binary Search Tree),也称为二叉排序树或二叉查找树。它与一般二叉树的区别在于:每个结点必须满足“左孩子大于自己,右孩子小于自己”的规则。在这种规则的约束下,二叉搜索树使用中序遍历出来的数据是一个由小到大排列的结果。

在这里插入图片描述

优点:

  1. 查找某个值最多只需要遍历高度次即可,效率高。
  2. 使用中序遍历出来的数据是有序的。

缺点:

  1. 结点的值不允许修改,否则破坏树的结构。

2. 二叉搜索树的插入

二叉搜索树的插入很简单,首先用插入的值从根结点开始比较。插入值小于结点值向左,插入值大于结点值向右,直到结点的左孩子或右孩子为空时结束,为空的位置就是插入的位置。

在这里插入图片描述

4作为插入结点的值,先找到6是插入结点的父结点,再判断4和6的大小关系,4<6,所以插入在6的左边。

在这里插入图片描述

7作为插入结点的值,先找到6是插入结点的父结点,再判断7和6的大小关系,7>6,所以插入在6的右边。

3. 二叉搜索树的删除

二叉搜索的删除需要分两种情况:

3.1 删除的结点是叶子结点

如果删除的结点是叶子结点,将该结点的父结点指针制空,再释放该结点即可。

在这里插入图片描述

3.2 删除的结点不是叶子结点

如果删除的结点不是叶子结点,可以分为三种情况讨论:

3.2.1 左子树为空

如果删除的结点的左子树为空,此时需要判断删除结点与其父子树的关系:我是父结点的左孩子,就让父结点的左指向我的右子树;我是父结点的右孩子,就让父结点的右指向我的右子树

在这里插入图片描述

在这里插入图片描述

3.2.2 右子树为空

右子树为空,原理与上相同,只是父结点改变的是左的指向。

在这里插入图片描述

在这里插入图片描述

3.2.3 左右子树不为空

如果删除结点的左右子树都不为空,那么此时就需要使用替换法的思想。替换法可以使用左子树的最大结点或右子树的最小结点作为替换结点来替换当前结点,再将替换结点删除。所谓“替换”在实际操作中不是把两个结点的值互换,而是将替换结点的值赋给原删除结点,因为替换节点最终要删除,所以不必要对其进行真正的替换操作。

使用最左结点替换:

在这里插入图片描述

使用最右结点替换:

在这里插入图片描述

4.二叉搜索树的退化问题

二叉搜索树的最优情况下,查找效率为logN。但当插入的顺序有序或部分有序时,二叉搜索树的查找效率会下降,极端情况下会退化至N

在这里插入图片描述

按{10,9,8,7,6,5,4}的顺序插入,导致二叉搜索树完全退化。

5. 参考代码

template<class K, class V>
struct BSTreeNode
{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _right;K _key;V _value;BSTreeNode(const K& key,const V& value):_left(nullptr),_right(nullptr),_key(key),_value(value){}
};template<class K, class V>
class BSTree
{typedef BSTreeNode<K, V> Node;
public:bool Insert(const K& key, const V& value){if (_root == nullptr){_root = new Node(key, value);return true;}Node* parent = nullptr;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;}}cur = new Node(key, value);{if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return cur;}}return nullptr;}bool Erase(const K& key){//先找到该结点Node* cur = _root;Node* parent = cur;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{//如果删除的是叶子结点,直接删除if (cur->_left == nullptr && cur->_right == nullptr){if (cur == parent->_left)parent->_left = nullptr;else if (cur == parent->_right)parent->_right = nullptr;delete cur;}//如果左为空else if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (cur == parent->_left){parent->_left = cur->_right;}else if (cur == parent->_right){parent->_right = cur->_right;}}delete cur;}//如果右为空else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else if (cur == parent->_right){parent->_right = cur->_left;}}delete cur;}// 如果左右都不为空else{//查找右子树的最左结点替换Node* RightMinParent = cur;Node* RightMin = cur->_right;while (RightMin->_left){RightMinParent = RightMin;RightMin = RightMin->_left;}cur->_key = RightMin->_key;cur->_value = RightMin->_key;cur->_value = RightMin->_value;if (RightMinParent->_left == RightMin){RightMinParent->_left = nullptr;}else{RightMinParent->_right = nullptr;}delete RightMin;}return true;}}return false;}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}void InOrder(){_InOrder(_root);cout << endl;}
private:Node* _root = nullptr;
};
http://www.lryc.cn/news/350177.html

相关文章:

  • Java 自然排序和比较器排序区别?Comparable接口和Comparator比较器区别?
  • 【CV】opencv调用DIS/LK等计算光流,前一帧和当前帧写反了有什么影响?
  • C语言学习细节|C语言面向对象编程!函数指针如何正确使用
  • C语言简要(一)
  • 那些年我与c++的叫板(一)--string类自实现
  • 二刷算法训练营Day08 | 字符串(1/2)
  • 使用高防IP是应对网络安全的重要措施
  • 代码随想录-算法训练营day40【动态规划03:整数拆分、不同的二叉搜索树】
  • MySQL数据库中基本数据管理操作
  • 记录一下Hql遇到的零碎问题
  • Flutter 中的 TextField 小部件:全面指南
  • GPT-4o:全面深入了解 OpenAI 的 GPT-4o
  • 2024中国应急(消防)品牌巡展西安站成功召开!惊喜不断
  • 信创电脑|暴雨新增兆芯KX-7000处理器版本
  • 面向对象 07:抽象类相关知识,抽象类的基本概念,使用方式,以及一些注意事项
  • Rust中的链式调用方法
  • xCode升级后: Library ‘iconv2.4.0’ not found
  • SQL语言:完整性约束
  • UBUNTU下CMAKE指定执行文件运行时查找库的路径
  • WHAT - CSS Animationtion 动画系列(四)- 移动端全屏动画
  • springboot004网页时装购物系统
  • 海外住宅IP介绍
  • Qt | QTimer 类(计时器)
  • SQL 面试系列(一)【留存率问题】
  • 2024OD机试卷-游戏分组 (java\python\c++)
  • 重装前端整体流程
  • Oracle Database 23ai Free版本体验
  • 84.网络游戏逆向分析与漏洞攻防-游戏技能系统分析-筛选与技能有关的数据包
  • 维护表空间中的数据文件
  • 2024五月母亲节嘉年华活动方案