数据结构 【搜索二叉树】

ops/2025/2/28 4:18:52/

        搜索二叉树是STL中map和set的重要铺垫,学好搜索二叉树有助于理解map和set的特性。搜索二叉树也是一种二叉树结构,只是多了一些特定的性质。

        一棵搜索二叉树可以为空树,如果不为空时,一定满足下面的性质。

  • 若它的左子树不为空,则所有左子树上的节点都小于根节点的键值。
  • 若它的右子树不为空,则所有的右子树上的节点都大于根节点的键值。
  • 它的左右子树也分别为搜索二叉树。

         基于先描述在组织的思想,我们可以尝试搭建一个搜索二叉树结构。

1、框架搭建

        先描述具体的节点,再进行节点间的组织链接。

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

        框架构造还是六个字:先描述,再组织。

2、节点插入

        数据进行插入时要分情况讨论:

  1. 搜索二叉树为空时,可以直接插入;
  2. 不为空时,如果插入的键值大于根节点就去根节点的右边继续寻找位置进行插入,如果插入的键值小于根节点就去根节点的左边寻找位置进行插入;如果搜索二叉树种存在要插入的键值就返回false;
	bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}else{//搜索二叉树不为空Node* parent = _root;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);cur->_key > parent->_key ? parent->_right = cur : parent->_left = cur;return true;}}

      在寻找空位置的过程中,也要同时记录当前节点的父节点位置。主要是方便进行后面的链接。

3、中序遍历

        由于中序遍历需要传入当前节点的地址进行递归,这里为了方便外部的对象调用。对中序遍历进行了一次封装。在封装之后的函数内部传入_root;

//省略类域	void InOrder(){_InOrder(_root);cout << endl;}
private:void _InOrder(Node* root)
{if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);
}

        对上述代码进行简单的测试:

#include<iostream>
using namespace std;
#include"BinarySearchTree.h"void TestBSTree()
{int arr[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };BSTree<int> bs;for (auto e : arr){bs.Insert(e);}bs.InOrder();}int main()
{TestBSTree();return 0;
}

        运行结果:

 4、节点删除

        节点的删除比较复杂。需要分下面的情况进行分析:

  • 要删除的节点没有子节点,可以直接进行删除,再删除之后要对它的父节点的位置进行置空操作。

  • 如果要删除的节点只有一个子节点,同样也可以直接删除,在删除之后需要在进行判断,如果删除节点的子节点小于删除节点的父节点,那么就链接在父节点的左边;反之,就连接在右边。

  • 如果要删除的节点左右子树都非空树,那么这时就需要进行替换删除。为了保证替换后的树形结构仍然满足搜索二叉树的性质,这时的替换要求为:只能和删除节点的左子树的最右节点或者右子树的最左节点进行替换。通常情况下使用左子树的最右节点进行替换。

上面的1和2可以归纳为一点,当删除的节点的左子树为空树时,就将删除节点的父节点链接上删除节点的右节点;反之,就将删除节点的父节点链接上删除节点的左节点。

	bool Erase(const K& key){Node* parent = _root;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{//找到了,进行删除操作//1.左子树为空if (cur->_left == nullptr){if (cur == _root){_root = _root->_right;}else{//判断删除节点的位置,进行原位置链接if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}}//2.右子树为空else if (cur->_right == nullptr){if (cur == _root){_root = _root->_left;}else{if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}}//3.左右子树都不为空else{Node* leftMaxParent = cur;Node* leftMax = cur->_left;//寻找左子树的最右节点 且找到它的父节点while (leftMax->_right){leftMaxParent = leftMax;leftMax = leftMax->_right;}std::swap(cur->_key, leftMax->_key);if (leftMaxParent->_left == leftMax){leftMaxParent->_left = leftMax->_left;}else{leftMaxParent->_right = leftMax->_left;}//下面统一删除cur;cur = leftMax;}delete cur;cur = nullptr;return true;}}return false;}


http://www.ppmy.cn/ops/161852.html

相关文章

算法-数据结构-图-邻接表构建

邻接表的基本概念 顶点&#xff08;Vertex&#xff09;&#xff1a; 图中的每个顶点用一个节点表示。 每个顶点存储一个链表或数组&#xff0c;用于记录与该顶点直接相连的其他顶点。 边&#xff08;Edge&#xff09;&#xff1a; 如果顶点 A 和顶点 B 之间有一条边&#xf…

可编辑PPT | DeepSeek如何赋能职场应用

这个PPT的核心内容是介绍DeepSeek如何赋能职场应用&#xff0c;从提示语技巧到多场景应用的详细解读。PPT首先介绍了DeepSeek的背景和团队&#xff0c;展示了其在AI领域的多项赛事奖项和研究成果&#xff0c;突出了其在人机协同和人机共生领域的专业能力。接着&#xff0c;PPT详…

【数字图像处理三】图像变换与频域处理

图像变换与频域处理&#xff1a;提升图像质量与特征提取 在数字图像处理中&#xff0c;图像变换和频域处理是两个非常重要的概念和技术。通过这些技术&#xff0c;我们不仅能够改善图像的视觉效果&#xff0c;还能进行更深入的图像分析&#xff0c;帮助我们从图像中提取有价值…

Mock测试:移动端分辨率适配

核心需求&#xff1a;通过 Charles 返回极端数据&#xff0c;测试 UI 对超长文本、大图、异常数值的兼容性 ​拦截接口​ 在移动端访问真实接口 https://api.example.com/productsCharles 左侧请求列表找到该接口&#xff0c;右键选择 ​Map Local ​绑定测试数据 选择该文件…

计算机网络之路由协议(OSPF路由协议)

一、定义与分类 OSPF是一种内部网关协议&#xff08;IGP&#xff09;&#xff0c;也属于链路状态路由协议。它使用链路状态路由算法&#xff0c;在单一自治系统&#xff08;AS&#xff09;内部工作。适用于IPv4的OSPFv2协议定义于RFC2328&#xff0c;而RFC5340则定义了适用于I…

Hot100 贪心算法

如果非要说这些题的共性&#xff0c;也许就是&#xff1a;在边界内不断寻找最优解 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09; 总结一下思路就是&#xff1a;如果第i天卖出股票&#xff0c;则最大利润为(该天的股价-前面天数中最小的股价)&#xff0c;然…

重学SpringBoot3-整合 Elasticsearch 8.x (一)客户端方式

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞??收藏评论 重学SpringBoot3-整合 Elasticsearch 8.x &#xff08;一&#xff09;客户端方式 1. 为什么选择 Elasticsearch&#xff1f;2. Spring Boot 3 和 Elasticsearch 8.x 的集成概述 2.1 准…

Linux MySQL 8.0.29 忽略表名大小写配置

Linux MySQL 8.0.29 忽略表名大小写配置 问题背景解决方案遇到的问题&#xff1a; 问题背景 突然发现有个大写的表报不存在。 在Windows上&#xff0c;MySQL是默认支持忽略大小写的。 这个时候你要查询一下是不是没有配置&#xff1a; SHOW VARIABLES LIKE lower_case_table…