C++第十二讲:二叉搜索树

news/2024/11/18 11:09:45/

C++第十二讲:二叉搜索树

  • 1.什么是二叉搜索树
  • 2.二叉搜索树的性能分析
  • 3.二叉搜索树的实现
    • 3.1二叉搜索树的插入
    • 3.2二叉搜索树的查找
    • 3.3二叉树搜索树的打印
    • 3.4二叉树搜索树的删除
    • 3.5全部代码实现
  • 4.二叉搜索树的使用场景
    • 4.1key使用场景
    • 4.2 key/value搜索场景

1.什么是二叉搜索树

在这里插入图片描述

2.二叉搜索树的性能分析

在这里插入图片描述

3.二叉搜索树的实现

3.1二叉搜索树的插入

这里我们实现的二叉搜索树暂时不让重复的字符进行插入

在这里插入图片描述

//插入函数
bool Insert(const K& key)
{if (_root == nullptr){//当根节点为空时,需要初始化根节点_root = new Node(key);return true;}Node* pcur = _root;Node* parent = nullptr;while(pcur){if (pcur->_key > key){parent = pcur;pcur = pcur->_left;}else if (pcur->_key < key){parent = pcur;pcur = pcur->_right;}else return false;//不支持相同的值进行重复插入}if (parent->_left == pcur) parent->_left = new Node(key);else parent->_right = new Node(key);return true;
}

3.2二叉搜索树的查找

二叉搜索树中如果没有相同元素的话,那么查找起来是很简单的:

//二叉搜索树的查找
bool Find(const K& key)
{Node* pcur = _root;while (pcur){if (pcur->_key > key) pcur = pcur->_left;else if (pcur->_key < key) pcur = pcur->_right;else return true;}return false;
}

而如果有相等的值进行查找,其实是查找出现的第一个数据,这个之后会看:
在这里插入图片描述
这里出现的问题:
在这里插入图片描述

3.3二叉树搜索树的打印

直接一个中序遍历即可,还是十分简单的:

void _InOrder(Node* root)
{if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);
}

在这里插入图片描述
但是调用会出现错误,因为我们在外面拿不到_root,所以这里有两个方法:
1.实现一个Getroot方法
2.再实现一个类函数,在类中可以调用_InOrder函数
这里采用第二种方式:
在这里插入图片描述

3.4二叉树搜索树的删除

二叉搜索树的删除相对来说比较复杂,我们画图来看:

在这里插入图片描述

//二叉树的删除
bool Erase(const K& key)
{//对于删除,我们肯定要先找到这个结点Node* parent = nullptr;Node* pcur = _root;while (pcur){if (pcur->_key < key){parent = pcur;pcur = pcur->_right;}else if (pcur->_key > key){parent = pcur;pcur = pcur->_left;}else{//这里就找到了该结点,进行删除操作if (pcur->_left == nullptr){if (parent == nullptr) _root = pcur->_right;else{//左结点为空if (pcur == parent->_right) parent->_right = pcur->_right;else parent->_left = pcur->_right;}delete pcur;//pcur结点是需要被删除的}else if (pcur->_right == nullptr){if (parent == nullptr) _root = pcur->_left;else{//右结点为空if (pcur == parent->_right)parent->_right = pcur->_left;elseparent->_left = pcur->_left;}delete pcur;//pcur结点是需要被删除的}else{//左右结点都不为空时,我们这里采用寻找右子树的最小结点Node* minright = pcur->_right;Node* minparent = pcur;while (minright->_left) minparent = minright, minright = minright->_left;pcur->_key = minright->_key;if (minparent->_left == minright) minparent->_left = minright->_right;else minparent->_right = minright->_right;delete minright;}return true;}}return false;
}

3.5全部代码实现

//结点的结构体
template<class K>
struct BSTNode
{//结点中需要一个值,然后再存储左右结点的指针即可K _key;BSTNode<K>* _left;BSTNode<K>* _right;//构造BSTNode(const K& key):_key(key),_left(nullptr),_right(nullptr){}
};//class SearchBinaryTree
template <class K>
class BSTree
{typedef BSTNode<K> Node;
public://插入函数bool Insert(const K& key){if (_root == nullptr){//当根节点为空时,需要初始化根节点_root = new Node(key);return true;}Node* pcur = _root;Node* parent = nullptr;while(pcur){if (pcur->_key < key){parent = pcur;pcur = pcur->_right;}else if (pcur->_key > key){parent = pcur;pcur = pcur->_left;}else {return false;//不支持相同的值进行重复插入}}pcur = new Node(key);if (parent->_key < key) parent->_right = pcur;else parent->_left = pcur;这个比较不能是这样比较的,应该是key值的比较来确定左树还是右树//if (parent->_left == pcur) parent->_left = pcur;//else parent->_right = pcur;return true;}//二叉搜索树的查找bool Find(const K& key){Node* pcur = _root;while (pcur){if (pcur->_key > key) pcur = pcur->_left;else if (pcur->_key < key) pcur = pcur->_right;else return true;}return false;}//二叉树的删除bool Erase(const K& key){//对于删除,我们肯定要先找到这个结点Node* parent = nullptr;Node* pcur = _root;while (pcur){if (pcur->_key < key){parent = pcur;pcur = pcur->_right;}else if (pcur->_key > key){parent = pcur;pcur = pcur->_left;}else{//这里就找到了该结点,进行删除操作if (pcur->_left == nullptr){if (parent == nullptr) _root = pcur->_right;else{//左结点为空if (pcur == parent->_right) parent->_right = pcur->_right;else parent->_left = pcur->_right;}delete pcur;//pcur结点是需要被删除的}else if (pcur->_right == nullptr){if (parent == nullptr) _root = pcur->_left;else{//右结点为空if (pcur == parent->_right)parent->_right = pcur->_left;elseparent->_left = pcur->_left;}delete pcur;//pcur结点是需要被删除的}else{//左右结点都不为空时,我们这里采用寻找右子树的最小结点Node* minright = pcur->_right;Node* minparent = pcur;while (minright->_left) minparent = minright, minright = minright->_left;pcur->_key = minright->_key;if (minparent->_left == minright) minparent->_left = minright->_right;else minparent->_right = minright->_right;delete minright;}return true;}}return false;}void InOrder(){_InOrder(_root);cout << endl;}
private:void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}Node* _root = nullptr;
};int main()
{BSTree<int> b;int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };for (auto e : a){b.Insert(e);}b.InOrder();b.Erase(8);b.InOrder();for (auto e : a){b.Erase(e);b.InOrder();}return 0;
}

4.二叉搜索树的使用场景

4.1key使用场景

在这里插入图片描述

4.2 key/value搜索场景

在这里插入图片描述
我们可以简单看一下使用场景(比如我们要查汉字出现的次数):
在这里插入图片描述


http://www.ppmy.cn/news/1547967.html

相关文章

给阿里云OSS绑定域名并启用SSL

为什么要这么做&#xff1f; 问题描述&#xff1a; 当用户通过 OSS 域名访问文件时&#xff0c;OSS 会在响应头中增加 Content-Disposition: attachment 和 x-oss-force-download: true&#xff0c;导致文件被强制下载而不是预览。这个问题特别影响在 2022/10/09 之后新开通 OS…

跨平台WPF框架Avalonia教程 十

如何绘制图形 内容正在准备中。 图形​ Avalonia引入了一个广泛、可伸缩、灵活的图形功能集&#xff0c;具有以下优势&#xff1a; 分辨率无关和设备无关的图形。Avalonia图形系统的基本测量单位是设备无关像素&#xff0c;即1/96英寸&#xff0c;与实际屏幕分辨率无关&…

蓝桥杯每日真题 - 第12天

题目&#xff1a;&#xff08;数三角&#xff09; 题目描述&#xff08;14届 C&C B组E题&#xff09; 解题思路&#xff1a; 给定 n 个点的坐标&#xff0c;计算其中可以组成 等腰三角形 的三点组合数量。 核心条件&#xff1a;等腰三角形的定义是三角形的三条边中至少有…

03.01、三合一

03.01、[简单] 三合一 1、题目描述 三合一。描述如何只用一个数组来实现三个栈。 你应该实现push(stackNum, value)、pop(stackNum)、isEmpty(stackNum)、peek(stackNum)方法。stackNum表示栈下标&#xff0c;value表示压入的值。 构造函数会传入一个stackSize参数&#xf…

边缘提取函数 [OPENCV--2]

OPENCV中最常用的边界检测是CANNY函数 下面展示它的用法 通常输入一个灰度图像&#xff08;边界一般和颜色无关&#xff09;这样也可以简化运算cv::Canny(inmat , outmat , therhold1, therhold2 ) 第一个参数是输入的灰度图像&#xff0c;第二个是输出的图像这两个参数都是引用…

【软件测试】设计测试用例的万能公式

文章目录 概念设计测试用例的万能公式常规思考逆向思维发散性思维万能公式水杯测试弱网测试如何进行弱网测试 安装卸载测试 概念 什么是测试用例&#xff1f; 测试⽤例&#xff08;Test Case&#xff09;是为了实施测试⽽向被测试的系统提供的⼀组集合&#xff0c;这组集合包…

[SWPUCTF 2021 新生赛]whitegive_pwn

ret2libc 获取puts函数的PLT&#xff08;过程链接表&#xff09;地址、GOT&#xff08;全局偏移表&#xff09;地址和_start符号的地址。 pop_rdi 0x400763&#xff1a;这是pop rdi; ret指令的地址&#xff0c;用于控制rdi寄存器的值&#xff0c;以便调用puts函数。 payload1 …

LabVIEW弧焊参数测控系统

在现代制造业中&#xff0c;焊接技术作为关键的生产工艺之一&#xff0c;其质量直接影响到最终产品的性能与稳定性。焊接过程中&#xff0c;电流、电压等焊接参数的精确控制是保证焊接质量的核心。基于LabVIEW开发的弧焊参数测控系统&#xff0c;通过实时监控和控制焊接过程中关…