丹东网站建设公司/直通车关键词怎么优化
📝个人主页🌹:Eternity._
⏩收录专栏⏪:C++ “ 登神长阶 ”
🤡往期回顾🤡:C++多态
🌹🌹期待您的关注 🌹🌹
❀二叉搜索树
- 📒1. 二叉搜索树
- 🎩二叉搜索树概念
- 🎈二叉搜索树操作
- 📕2. 二叉搜索树模拟实现
- 🧩二叉搜索树结构
- 🧩二叉搜索树操作
- 🌈插入
- 🌞遍历
- 🌙查找
- ⭐删除
- 🧩二叉搜索树默认成员函数
- 📜3. 二叉搜索树模拟实现(递归)
- 🌞插入
- 🌙查找
- ⭐删除
- 📚4. 二叉搜索树的应用
- 🍁KV模型
- 🍂KV模型实现
- 💧英汉词典
- 🔥计数
- 🌄二叉树巩固知识
- 📖5. 总结
前言: 在数据结构和算法的广阔领域中,二叉搜索树(Binary Search Tree,简称BST)无疑是一颗璀璨的明星。它以其高效的数据检索能力和独特的树形结构,在计算机科学领域扮演着举足轻重的角色。对于任何对编程和数据结构感兴趣的人来说,掌握二叉搜索树都是至关重要的一步
二叉搜索树不仅仅是一个简单的数据结构,它更是一种解决问题的方式和思维的体现。通过维护二叉树中每个节点的左子树所有值均小于它的值,右子树所有值均大于它的值的特性,二叉搜索树在插入、查找和删除操作中展现出了卓越的性能。这种特性使得二叉搜索树在各种应用中成为了一种理想的数据结构选择,从基础的算法练习到复杂的系统优化,都能见到它的身影
学习二叉搜索树并非易事。它需要我们深入理解其性质、原理和算法实现。我们需要掌握如何构建一棵二叉搜索树,如何遍历它,以及如何在其中进行高效的查找、插入和删除操作。这些都需要我们付出大量的时间和精力去学习和实践。我们将从二叉搜索树的基本概念出发,逐步深入到其性质、构建、遍历以及操作的实现
让我们一起踏上学习二叉搜索树的旅程,探索它带来的无尽可能!
(本文重在二叉搜索树的模拟实现与理解)
📒1. 二叉搜索树
🎩二叉搜索树概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别为二叉搜索树
🎈二叉搜索树操作
首先,在二叉搜索树的操作中只支持插入,查找,删除,遍历,并不支持修改
操作,因为在修改后谁也不能保证它依然是一棵二叉搜索树,二叉搜索树的时间复杂度范围在(O(logN)~O(N)
)
在二叉搜索树的遍历中一般采用中序遍历: 先遍历左子树,然后访问根节点,最后遍历右子树。在BST中,中序遍历会按照升序访问所有节点
二叉搜索树示例
int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};
📕2. 二叉搜索树模拟实现
🧩二叉搜索树结构
二叉搜索树结构的和树形结构差不多,这意味着每个元素(通常称为节点)都有两个指针:一个指向前一个左子树,另一个指向右子树,因此我们需要单独再定义一个类来表示节点结构,每个节点再串联起来构成BST
(在模拟实现二叉搜索树时,不用定义命名空间,因为不会和库中发生冲突)
节点定义(示例):
template<class K>
struct BSTreeNode
{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key = K()):_key(key), _left(nullptr), _right(nullptr){}
};
BST定义(示例):
template<class K>
class BSTree
{typedef BSTreeNode<K> Node;
public:// 构造函数等可能的其他成员函数...
private:Node* _root = nullptr;
};
🧩二叉搜索树操作
🌈插入
插入的具体过程如下:
- 树为空,则直接新增节点,赋值给root指针
- 树不空,按二叉搜索树性质查找插入位置,插入新节点
插入代码实现(示例):
bool Insert(const K& key)
{// 当根为空时,直接插入if (_root == nullptr){_root = new Node(key);return true;}// 定义parent是因为,在最后找到插入位置时,需要parent将节点进行连接Node* parent = nullptr; Node* cur = _root;while (cur){parent = cur;// 插入的值比cur位置大时,cur往右移动if (key > cur->_key){cur = cur->_right;}// 插入的值比cur位置小时,cur往左移动else if (key < cur->_key){cur = cur->_left;}// 当插入的值和cur位置相等时,直接退出,因为二叉搜索树不允许有相同的元素else{return false;}}// 将插入位置的新节点与二叉搜索树连接cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;
}
🌞遍历
在二叉搜索树的遍历上,我们依旧采用当初二叉树时的中序遍历,但是我们想要递归遍历就必须调用节点,这里我们要调用两层
遍历代码实现(示例):
void InOrder()
{_InOrder(_root);cout << endl;
}void _InOrder(Node* root)
{// 递归出口if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " " ;_InOrder(root->_right);
}
遍历比较简单奥,我们接着往下讲
🌙查找
二叉搜索树的查找
- 从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找
- 最多查找高度次,走到到空,还没找到,这个值不存在
查找代码实现(示例):
bool Find(const K& key)
{Node* cur = _root;while (cur){// 查找的值比cur大,cur往右移动if (key > cur->_key){cur = cur->_right;}// 查找的值比cur小,cur往左移动else if (key < cur->_key){cur = cur->_left;}// 找到key,返回trueelse{return true;}}return false; // 找不到key,返回false
}
⭐删除
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面情况:
- 要删除的结点无孩子结点
- 要删除的结点只有左孩子结点
- 要删除的结点只有右孩子结点
- 要删除的结点有左、右孩子结点
而上面四种情况可以转化成下面的情况:
- 删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
- 删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
- 在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除
这三种情况就是我们模拟实现删除的方法!
删除代码实现(示例):
bool Erase(const K& key)
{Node* cur = _root;Node* parent = nullptr;while (cur){parent = cur;if (key > cur->_key){cur = cur->_right;}else if (key < cur->_key){cur = cur->_left;}else{// 准备删除// 左为空if (cur->_left == nullptr){// 当需要删除的是头节点时if (cur == _root){_root = cur->_right;}else{if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}}// 右为空else if (cur->_right == nullptr){// 当需要删除的是头节点时if (cur == _root){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}}// 两边都不为空else{// 这里与外层不是同一块作用域,所以可以再次定义parent,不把parent定义为nullptr是因为//,可能不进入下面循环导致对parent空指针的使用Node* subLeft = cur->_right; // 定义右数节点Node* parent = cur;while (subLeft->_left){parent = subLeft;subLeft = subLeft->_left;}swap(cur->_key, subLeft->_key); // 替换右子树的最左节点if (subLeft == parent->_left){// 最左节点肯定没有左孩子,所以让parent接管它的右子树parent->_left = subLeft->_right;}else{parent->_right = subLeft->_right;}delete subLeft;}return true;}}return false;
}
🧩二叉搜索树默认成员函数
构造
BSTree() = default; // 显式地定义默认构造函数
拷贝构造
BSTree(const BSTree<K>& t)
{_root = Copy(t._root);
}Node* Copy(Node* root)
{if (root == nullptr){return nullptr;}// 递归进行拷贝构造Node* newroot = new Node(root->_key);newroot->_left = Copy(root->_left);newroot->_right = Copy(root->_right);return newroot;
}
赋值重载
BSTree<K>& operator=(BSTree<K> t)
{// 现代写法-> 直接调用swapswap(_root, t._root);return *this;
}
析构
~BSTree()
{Destory(_root);
}void Destory(Node*& _root)
{if (_root == nullptr){return;}// 递归调用析构Destory(_root->_left);Destory(_root->_right);delete _root;_root == nullptr;
}
📜3. 二叉搜索树模拟实现(递归)
在进行递归操作的模拟实现时,一般都要传节点,进行多层的调用,因为我们都要定义两层
bool FindR(const K& key)
{return _FindR(_root, key);
}bool InsertR(const K& key)
{return _InsertR(_root, key);
}bool EraseR(const K& key)
{return _EraseR(_root, key);
}
🌞插入
代码实现(示例):
bool _InsertR(Node*& _root, const K& key)
{// 递归出口if (_root == nullptr){// 这里我们无需在进行对新节点的连接,因为我们是传引用传参,_root = new Node(key);return true;}if (key > _root->_key){return _InsertR(_root->_right, key);}else if (key < _root->_key){return _InsertR(_root->_left, key);}else{return false;}
}
🌙查找
代码实现(示例):
bool _FindR(Node* _root, const K& key){if (_root == nullptr){return false;}if (key > _root->_key){return _FindR(_root->_right, key);}else if (key < _root->_key){return _FindR(_root->_left, key);}else{return true;}}
⭐删除
代码实现(示例):
bool _EraseR(Node*& _root, const K& key)
{if (_root == nullptr){return false;}if (key > _root->_key){return _EraseR(_root->_right, key);}else if (key < _root->_key){return _EraseR(_root->_left, key);}else{// 删除if (_root->_left == nullptr){Node* del = _root;_root = _root->_right;delete del;return true;}else if (_root->_right == nullptr){Node* del = _root;_root = _root->_left;delete del;return true;}else{Node* subLeft = _root->_right;while (subLeft->_left){subLeft = subLeft->_left;}swap(_root->_key, subLeft->_key);// 让子树继续递归下去return _EraseR(_root->_right, key);}}
}
📚4. 二叉搜索树的应用
🍁KV模型
KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方式在现实生活中非常常见:
- 比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英
文单词与其对应的中文<word, chinese>就构成一种键值对- 再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出
现次数就是<word, count>就构成一种键值对
namespace kv // 避免与之前k模型冲突
{template<class K, class V>struct BSTreeNode{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;V _value;BSTreeNode(const K& key = K(), const V& value = V()): _left(nullptr), _right(nullptr), _key(key), _value(value){}};template<class K, class V>class BSTree{typedef BSTreeNode<K, V> Node;public:// 构造函数等可能的其他成员函数... // 在成员函数中,我们只需要在insert中加入value元素即可private:Node* _root = nullptr;};
}
在成员函数中,我们只需要在Insert中加入value元素即可
🍂KV模型实现
💧英汉词典
代码实现(示例):
int main()
{kv::BSTree<string, string> dict;dict.insert("left", "左边、剩余");dict.insert("string", "字符串");dict.insert("hahaha", "哈哈");dict.insert("Eternity", "永恒");dict.insert("sort", "排序");dict.InOrder();string str;while (cin >> str){kv::BSTreeNode<string, string>* ret = dict.Find(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词" << endl;}}
}
🔥计数
代码实现(示例):
int main()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉" };kv::BSTree<string, int> countTree;for (auto& e : arr){kv::BSTreeNode<string, int>* ret = countTree.Find(e);if (ret == nullptr){countTree.insert(e, 1);}else{ret->_value++;}}countTree.InOrder();return 0;
}
🌄二叉树巩固知识
最后在这给大家推荐几道巩固二叉树的编程题
二叉树创建字符串
二叉树的分层遍历
找到树中两个指定节点的最近公共祖先
二叉树搜索树转换成排序双向链表
根据一棵树的前序遍历与中序遍历构造二叉树
二叉树中序遍历 ,非递归迭代实现
📖5. 总结
经过我们一同对搜索二叉树的深入学习和探索,相信你已经对这种数据结构有了全面而深刻的理解。搜索二叉树以其独特的性质在数据检索领域展现了出色的性能,无论是插入、删除还是查找操作,都体现了其高效和灵活的特点
学习的道路永无止境。虽然我们已经走过了搜索二叉树的基本概念和操作的学习之旅,但这只是你编程旅程中的一个站点。前方还有更多数据结构等待你去探索,更多算法等待你去实践
不要忘记持续学习和自我提升。计算机科学是一个日新月异的领域,新的技术和算法不断涌现。只有保持对知识的渴望和追求,我们才能在这个领域中不断前行,让我们一起在学习的道路上不断前行!
希望本文能够为你提供有益的参考和启示,让我们一起在编程的道路上不断前行!
谢谢大家支持本篇到这里就结束了,祝大家天天开心!
相关文章:

【C++高阶】高效搜索的秘密:深入解析搜索二叉树
📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C “ 登神长阶 ” 🤡往期回顾🤡:C多态 🌹🌹期待您的关注 🌹🌹 ❀二叉搜索树 📒1. 二叉搜索树&…...

《软件定义安全》之七:SDN安全案例
第7章 SDN安全案例 1.DDoS缓解 1.1 Radware DefenseFlow/Defense4All Radware在开源的SDN控制器平台OpenDaylight(ODL)上集成了一套抗DDoS的模块和应用,称为Defense4ALL。其架构如下图,主要有两部分:控制器中的安全…...

java语言his系统医保接口 云HIS系统首页功能实现springboot框架+Saas模式 his系统项目源码
java语言his系统医保接口 云HIS系统首页功能实现springboot框架Saas模式 his系统项目源码 HIS系统的实施旨在整个医院建设企业级的计算机网络系统,并在其基础上构建企业级的应用系统,实现整个医院的人、财、物等各种信息的顺畅流通和高度共享,…...

使用vscode插件du-i18n处理前端项目国际化翻译多语言
前段时间我写了一篇关于项目国际化使用I18n组件的文章,Vue3 TS 使用国际化组件I18n,那个时候还没真正在项目中使用,需求排期还没有定,相当于是预研。 当时就看了一下大概怎么用,改了一个简单的页面,最近需…...

双系统下,如何隐藏另一个系统分区?
前言 最近有小伙伴在公众号下留言: 小伙伴说:“双系统时,非当前系统的系统盘能不能屏蔽?!比如Win7的系统盘在Win10系统时,盘符成了D盘,安装应用软件时,有些文件就到了D盘࿰…...

电脑意外出现user32.dll丢失的八种修复方法,有效解决user32.dll文件丢失
遇到与 user32.dll 相关的错误通常是因为该文件已损坏、丢失、或者与某些软件冲突。今天这篇文章寄给大家介绍八种修复user32.dll丢失的方法,下面是一步步的详细教程来解决这个问题。 1. 重新启动电脑 第一步总是最简单的:重新启动你的电脑。许多小问题…...

CUDA系列-Kernel Launch-8
这里写目录标题 kernel launch 本章主要追踪一下kernel launch的流程,会不断完善。 kernel launch 先抛出一个问题,如果在一个循环中不断的发送kernel(kernel 内部while死循环),会是什么结果。 // kernel 函数 __glo…...

# 消息中间件 RocketMQ 高级功能和源码分析(四)
消息中间件 RocketMQ 高级功能和源码分析(四) 一、 消息中间件 RocketMQ 源码分析:回顾 NameServer 架构设计。 1、RocketMQ 架构设计 消息中间件的设计思路一般是基于主题订阅发布的机制,消息生产者(Producer&…...

如何通过数据库与AI实现以图搜图?OceanBase向量功能详解
OceanBase支持向量数据库的基础能力 当前,数据库存储系统与人工智能技术的结合,可以体现在两个主要的应用方向上。 一、近似搜索。它利用大语言模型(LLM,简称大模型)的嵌入(embedding)技术&am…...

Kafka内外网分流配置listeners和advertised.listeners
问题背景: Kafka部署在内网,内网Java服务会使用Kafka收发消息,另外,Java服务会与其他第三方系统使用kafka实现数据同步,也就是外网也会发送消息到kafka,外网IP做了端口映射到了内网,advertised…...

Linux系统编程——网络编程
目录 一、对于Socket、TCP/UDP、端口号的认知: 1.1 什么是Socket: 1.2 TCP/UDP对比: 1.3 端口号的作用: 二、字节序 2.1 字节序相关概念: 2.2 为什么会有字节序: 2.3 主机字节序转换成网络字节序函数…...

信息安全技术基础知识-经典题目
【第1题】 1.在信息安全领域,基本的安全性原则包括机密性(Confidentiality)、完整性(Integrity)和 可用性(Availability)。机密性指保护信息在使用、传输和存储时 (1) 。信息加密是保证系统机密性的常用手段。使用哈希校验是保证数据完整性的常用方法。可用性指保证…...

nextjs(持续学习中)
return ( <p className{${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal}> Welcome to Acme. This is the example for the{’ } Next.js Learn Course , brought to you by Vercel. ); } 在顶级 /public 文件夹下提供静态资产 **默认 /…...

数据预处理与特征工程、过拟合与欠拟合
数据预处理与特征工程 常用的数据预处理步骤 向量化:将数据转换成pytorch张量值归一化:将特定特征的数据表示成均值为0,标准差为1的数据的过程;取较小的值:通常在0和1之间;相同值域处理缺失值特征工程&am…...

甲辰年五月十四风雨思
甲辰年五月十四风雨思 夜雨消暑气,远光归家心。 只待万窗明,朝夕千家勤。 苦乐言行得,酸甜日常品。 宫商角徵羽,仁义礼智信。...

java分别使用 iText 7 库和iText 5 库 将excel转成PDF导出,以及如何对excel转PDF合并单元格
第一种 package com.junfun.pms.report.util;import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.property.TextAlignment; import com.itextpdf.layout.prop…...

Java特性之设计模式【访问者模式】
一、访问者模式 概述 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式&…...

【教师资格证考试综合素质——法律专项】未成年人保护法笔记以及练习题
《中华人民共和国未成年人保护法》 目录 第一章 总 则 第二章 家庭保护 第三章 学校保护 第四章 社会保护 第五章 网络保护 第六章 政府保护 第七章 司法保护 第八章 法律责任 第九章 附 则 介一.首次颁布:第一部《中华人民共和国未成年人保护法…...

6.19作业
TCP服务器 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h>#define PORT 8888 #define IP "192.168.124.39&q…...

java 线程之间通信-volatile 和 synchronized
你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益: 了解大厂经验拥有和大厂相匹配的技术等 希望看什么,评论或者私信告诉我! 文章目录 一…...

资源宝库网站!人人必备的神器!
面对网络中海量的内容,一个高效、便捷的网络导航工具,可以帮助我们快速查找使用网络资源。无论是职场精英还是学生党,使用导航网站都可以帮助我们提升效率。下面小编就来和大家分享一款资源宝库网站-办公人导航-实用的办公生活导航网站&#…...

Redis实战—优惠卷秒杀(锁/事务/代理对象的应用)
本博客为个人学习笔记,学习网站与详细见:黑马程序员Redis入门到实战 P50 - P54 目录 优惠卷秒杀下单功能实现 超卖问题 悲观锁与乐观锁 实现CAS法乐观锁 一人一单功能实现 代码优化 代码细节分析 优惠卷秒杀下单功能实现 Controller层…...

HTML星空特效
目录 写在前面 完整代码 代码分析 运行效果 系列文章 写在后面 写在前面 100行代码实现HTML星空特效。 完整代码 全部代码如下。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&g…...

银行数仓项目实战(四)--了解银行业务(存款)
文章目录 项目准备存款活期定期整存整取零存整取存本取息教育储蓄定活两便通知存款 对公存款对公账户协议存款 利率 项目准备 (贴源层不必写到项目文档,因为没啥操作没啥技术,只是数据。) 可以看到,银行的贴源层并不紧…...

MySQL版本发布模型
MySQL 8.0 之后使用了新的版本控制和发布模型,分为两个主线:长期支持版(LTS)以及创新版。这两种版本都包含了缺陷修复和安全修复,都可以用于生产环境。 下图是 MySQL 的版本发布计划: 长期支持版 MySQL…...

java: 不兼容的类型: org.apache.xmlbeans.XmlObject无法转换为x2006.main.CTRow
我使用的xmlbeans版本是5.0,使用xmlbeans包做转换时,报错,正如标题显示得那样 解决办法 额外再引入下面的jar包 <dependency><groupId>org.apache.xmlbeans</groupId><artifactId>xmlbeans</artifactId><…...

内容时代:品牌如何利用社交平台精准触达用户
还记得学生时代老师教写作文的时候常说的一句话就是“开头质量决定了阅卷老师想不想花精力去读,而内容质量决定了她愿不愿意给你判高分”这个世界仿若一个巨大的圆,同样的逻辑放在任何地方好像都能适用。在品牌营销中,内容已成为品牌与消费者…...

推荐4款PC端黑科技工具,快来看看,建议收藏
Thunderbird Thunderbird 是由 Mozilla 基金会开发的一款免费且开源的电子邮件客户端,支持 Windows、macOS、Linux 等多种操作系统。它不仅可以用于发送和接收电子邮件,还可以作为新闻阅读器、聊天工具以及日历应用。 Thunderbird 提供了丰富的功能&…...

汉化版PSAI全面测评,探索国产AI绘画软件的创新力量
引言 随着AI技术的飞速发展,图像处理和绘画领域迎来了新的变革。作为一名AIGC测评博主,今天我们测评的是一款国产AI绘画软件——StartAI,一句话总结:它不仅在技术上毫不逊色于国际大牌,更在用户体验和本地化服务上做到…...

LeetCode | 709.转换成小写字母
这道题可以用api也可以自己实现,都不难,大小字母之前相差了32,检查到大写字母时加上32即可 class Solution(object):def toLowerCase(self, s):""":type s: str:rtype: str"""return s.lower()class Solution…...