C++之搜索二叉树(上)

embedded/2024/9/24 3:22:30/

目录

搜索二叉树的概念 

搜索二叉树的操作

递归版本

二叉树的插入

二叉树的查找 

二叉树的删除 

非递归版本

二叉树的递归插入

二叉树的递归查找 

二叉树的递归删除


在之前我们已经学习过了二叉树这一数据结构,本期我们将学习一种新的数据结构------搜索二叉树。

搜索二叉树的概念 

我们把具有以下性质的树成为搜索二叉树:

  1. 若左子树不为空,则左子树所有节点的值都小于根节点的值。
  2. 若右子树不为空,则右子树所有节点的值都大于根节点的值。
  3. 所有子树均满足1和2两个性质。

搜索二叉树图示如下。

我们对搜索二叉树进行中序遍历,结果为0,1,2,3,4,5,6,7,8,9,同时我们规定搜索二叉树不能有相同的元素,所以搜索二叉树的功能就是排序去重。 

搜索二叉树的操作

递归版本

二叉树的插入

代码如下。

	//2.插入bool insert(K key){//当树为空时if (_root == nullptr){_root = new Node(key);return true;}//当树不为空时else{Node* cur = _root;Node* parent = nullptr;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(key);if (cur->_key < parent->_key){parent->_left = cur;}else{parent->_right = cur;}}return true;}void InOrder(){_InOrder(_root);}void _InOrder(Node* root){//如果为空树if (root == nullptr)return;//不为空树_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}

 运行结果如下。

运行结果符合预期。

二叉树的查找 

代码如下。

//3.查找bool find(K key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return true;}}return false;}

运行结果如下。

运行结果符合预期。

二叉树的删除 

二叉树的各种操作中,最复杂的就是二叉树的删除,二叉树的删除总共分为两种情况。

 第一种节点的删除只需要更改指针的指向即可。第二种较为复杂,我们需找到左子树的最大值或者右子树的最小值让其作为删除之后的搜索二叉树的根节点。

代码如下。

	bool erase(K key){//查找对应的元素Node* parent = nullptr;Node* cur = _root;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){if (parent == nullptr){_root = cur->_right;}if (cur->_key < parent->_key){parent->_left = cur->_right;}parent->_right = cur->_right;delete cur;}//右孩子为空else if (cur->_right == nullptr){if (parent == nullptr){_root = cur->_left;}if (cur->_key < parent->_key){parent->_left = cur->_left;}parent->_right = cur->_left;delete cur;}//左右孩子均不为空,找左子树最右的节点或者右子树最左的节点else{Node* MinParent = cur;Node* min = cur->_right;while (min->_left){MinParent = min;min = min->_left;}//找到了最小的节点cur->_key = min->_key;if (MinParent->_left = min){MinParent->_left = min->_right;}MinParent->_right = min->_right;delete min;}return true;}}return false;}

运行结果如下。

 运行结果符合预期。

非递归版本

二叉树的递归插入

代码如下。

	 //递归插入void insertR(K key){_insertR(_root, key);}void  _insertR(Node*& root, K key){if (root == nullptr){root = new Node(key);return;}if (root->_key > key){_insertR(root->_left, key);}else if (root->_key < key){_insertR(root->_right, key);}else{return;}}

二叉树的递归查找 

    Node* findR(K key){return _findR(_root,key);}Node* _findR(Node* root, K key){if (root == nullptr){return nullptr;}if (root->_key < key){_findR(root->_right,key);}else if (root->_key > key){_findR(root->_left,key);}else{return root;}}

二叉树的递归删除

    bool eraseR(K key){return _eraseR(_root, key);}bool _eraseR(Node* &root,K key){if (root == nullptr){return false;}if (root->_key < key){_eraseR(root->_right, key);}else if (root->_key > key){_eraseR(root->_left, key);}else{Node* erase = root;if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{Node* min = root->_right;while (min->_left){min = min->_left;}swap(root->_key, min->_key);//递归到右子树删除_eraseR(root->_right, key);}delete erase;return true;}

递归中使用了引用,去接收根节点,这一点省去了插入和删除元素之后,节点之间的链接,大家可以画递归展开图进一步了解。 

搜索二叉树优化

观察图1和图2。

图1和图2都是搜索二叉树,如果我们都去查找9这个元素,不难发现两个搜索二叉树都要去查找4次,但是明显图1的节点比图2的节点多了一倍,这也是影响搜索二叉树效率的一个关键原因------树上的节点分布不均衡,同样是N个节点,如果在理想情况下即满二叉树,查找一个元素的复杂度为O(logN),但是如果分布不均匀,就像一个链表一样,查找一个节点的时间复杂度为O(N),所以在后续我们会学习平衡二叉树如AVL树红黑树来避免像图2的情景发生。 

以上便是搜索二叉树的所有内容。

本期内容到此结束^_^


http://www.ppmy.cn/embedded/104426.html

相关文章

【Faiss】构建高效搜索系统 - Faiss向量数据库的搭建

目录 ​编辑1. 引言 2. Faiss简介 3. 安装与配置 3.1 在不同操作系统上的安装方法 3.1.1 Windows 3.1.2 macOS 3.1.3 Linux 3.2 配置开发环境 3.2.1 使用virtualenv 3.2.2 使用Anaconda 1. 引言 在当今这个数据爆炸的时代&#xff0c;快速有效地处理海量数据已经成为…

高防服务器中的流量清洗是什么意思?

高防服务器能够为企业防御一定的网络攻击&#xff0c;是网络游戏行业经常会选择的一款服务器类型&#xff0c;其中高防服务器的流量清洗则是指对服务器所接收的流量进行实时监测、识别和过滤&#xff0c;将恶意流量与攻击流量进行清除&#xff0c;保证网络能够正常运行。 接下来…

前端知识HTMLCSS

目录 1. 前端开发介绍 1.1 认识前端开发 1.2 web标准 2. HTML & CSS 2.1 HTML快速入门 2.1.1 操作 2.1.2 总结 2.2 开发工具 2.3 基础标签 & 样式 2.3.1 标题实现 2.3.1.1 标题排版 2.3.1.1.1 分析 2.3.1.1.2 标签 2.3.1.1.2 实现 2.3.1.2 标题样式 2.…

Electron 项目实战 02:打包和自动更新

技术选型 electron-forgeelectron-builder electron-forge 是Electron 官方文档介绍的&#xff0c;打包和发布都包含了&#xff0c;但是包含的坑也非常多。electron-builder下载量和集成打包非常顺利&#xff0c;本教程也是采用electron-buid来介绍打包。大家在技术选型的时候…

【代码随想录|图论part03之后】

代码随想录|数组 704. 二分查找,27. 移除元素 一、part031、101. 孤岛的总面积1.1 dfs版本1.2 BFS版本2.102. 沉没孤岛3、103. 水流问题4、104.建造最大岛屿二、part041、110. 字符串接龙2、105.有向图的完全可达性3、106. 岛屿的周长三、part05-06 并查集理论1、107. 寻找存在…

Java 单元测试指南

本文不仅介绍了单元测试的规范&#xff0c;还结合实际开发案例&#xff0c;演示了如何编写单元测试。我们使用了 JUnit、H2、Surefire 等常用的单元测试工具。如果你希望深入了解这些工具&#xff0c;可以查阅相关资料。本文基于企业内部实际应用的工作流程&#xff0c;通过教程…

11 Java 方法引用、异常处理

文章目录 前言一、Java接口之函数式编程 --- 接口知识补充1 Function<T,R>泛型接口2 BiFunction<T, U, R>泛型接口3 自定义泛型函数式编程接口 二、方法引用1 方法引用初体验&#xff08;以Array.sort()方法为例&#xff09;2 引用静态方法3 引用其他类成员方法 前…

Day 31: 贪心算法基础 V

56. 合并区间 本题也是重叠区间问题&#xff0c;如果昨天三道都吸收的话&#xff0c;本题就容易理解了。 给出一个区间的集合&#xff0c;请合并所有重叠的区间。 示例 1: 输入: intervals [[1,3],[2,6],[8,10],[15,18]]输出: [[1,6],[8,10],[15,18]]解释: 区间 [1,3] 和 [2,…