【C++从0到王者】第二十八站:二叉搜索树的应用

文章目录

  • 前言
  • 一、Key模型
  • 二、Key/Value模型
  • 总结

前言

二叉搜索树的在现实世界的应用很广泛,比如Key模型,Key-Value模型就是常见的两种的模型

一、Key模型

K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。即就是判断key在不在就可以了。

比如:门禁系统,小区车辆出入系统等等

给一个单词word,判断该单词是否拼写正确,具体方式如下:
以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。

我们前面文章中所完成的二叉搜索树就是key模型的二叉搜身树

二、Key/Value模型

Key/Value每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方式在现实生活中非常常见:比如商场的车辆出入系统(计时付费),高铁实名制车票系统等
比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文<word, chinese>就构成一种键值对;
再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是<word, count>就构成一种键值对

现在就让我们来实现一个key-value模型的二叉搜索树。

#pragma oncetemplate<class K, class V>
struct BSTreeNode
{BSTreeNode(const K& key = K(), const V& val = V()):_key(key),_val(val),_left(nullptr),_right(nullptr){}K _key;V _val;BSTreeNode<K,V>* _left;BSTreeNode<K,V>* _right;
};template<class K, class V>
class BSTree
{typedef BSTreeNode<K,V> Node;
public:BSTree():_root(nullptr){}BSTree(const BSTree<K,V>& t){_root = Copy(t._root);}~BSTree(){_Destory(_root);}BSTree<K,V>& operator=(BSTree<K,V> t){std::swap(_root, t._root);return *this;}bool Insert(const K& key,const V& val){if (_root == nullptr){_root = new Node(key,val);return true;}else{Node* parent = _root;Node* cur = _root;while (cur != nullptr){if (cur->_key == key){return false;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{parent = cur;cur = cur->_right;}}cur = new Node(key,val);if (parent->_key > key){parent->_left = cur;}else if (parent->_key < key){parent->_right = cur;}return true;}}void InOrder(){_InOrder(_root);}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_key == key){return cur;}else if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}}return nullptr;}bool Erase1(const K& key){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{if (parent == nullptr){if (cur->_left == nullptr){_root = cur->_right;delete cur;return true;}else if (cur->_right == nullptr){_root = cur->_left;delete cur;return true;}else{Node* leftMaxParent = cur;Node* leftMax = cur->_left;if (leftMax->_right == nullptr){leftMax->_right = cur->_right;delete cur;_root = leftMax;return true;}while (leftMax->_right){leftMaxParent = leftMax;leftMax = leftMax->_right;}std::swap(leftMax->_key, cur->_key);std::swap(leftMax->_val, cur->_val);leftMaxParent->_right = leftMax->_left;delete leftMax;leftMax = nullptr;return true;}}if (parent->_left == cur){if (cur->_left == nullptr){parent->_left = cur->_right;delete cur;return true;}else if (cur->_right == nullptr){parent->_left = cur->_left;delete cur;return true;}else {Node* leftMaxParent = cur;Node* leftMax = cur->_left;if (leftMax->_right == nullptr){leftMax->_right = cur->_right;delete cur;parent->_left = leftMax;return true;}while (leftMax->_right){leftMaxParent = leftMax;leftMax = leftMax->_right;}std::swap(leftMax->_key, cur->_key);std::swap(leftMax->_val, cur->_val);leftMaxParent->_right = leftMax->_left;delete leftMax;leftMax = nullptr;return true;}}else{if (cur->_left == nullptr){parent->_right = cur->_right;delete cur;return true;}else if (cur->_right == nullptr){parent->_right = cur->_left;delete cur;return true;}else{Node* leftMaxParent = cur;Node* leftMax = cur->_left;if (leftMax->_right == nullptr){leftMax->_right = cur->_right;delete cur;parent->_right = leftMax;return true;}while (leftMax->_right){leftMaxParent = leftMax;leftMax = leftMax->_right;}std::swap(leftMax->_key, cur->_key);std::swap(leftMax->_val, cur->_val);leftMaxParent->_right = leftMax->_left;delete leftMax;leftMax = nullptr;return true;}}}}return false;}bool Erase2(const K& key){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{if (cur->_left == nullptr){if (parent == nullptr){_root = cur->_right;}else if (parent->_left == cur){parent->_left = cur->_right;}else if (parent->_right == cur){parent->_right = cur->_right;}}else if (cur->_right == nullptr){if (parent == nullptr){_root = cur->_left;}else if (parent->_left == cur){parent->_left = cur->_left;}else if (parent->_right = cur){parent->_right = cur->_left;}}else{Node* leftMax = cur->_left;Node* leftMaxParent = cur;while (leftMax->_right){leftMaxParent = leftMax;leftMax = leftMax->_right;}std::swap(cur->_key, leftMax->_key);std::swap(cur->_val, leftMax->_val);if (leftMaxParent->_left == leftMax){leftMaxParent->_left = leftMax->_left;}else{leftMaxParent->_right = leftMax->_left;}cur = leftMax;}delete cur;return true;}}}Node* FindR(const K& key){return _FindR(_root, key);}bool InsertR(const K& key,const V& val){return _InsertR(_root, key, val);}bool EraseR(const K& key){return _EraseR(_root, key);}
private:Node* Copy(Node* root){if (root == nullptr){return nullptr;}Node* Copyroot = new Node(root->_key, root->val);Copyroot->_left = Copy(root->_left);Copyroot->_right = Copy(root->_right);return Copyroot;}void _Destory(Node*& root){if (root == nullptr){return;}_Destory(root->_left);_Destory(root->_right);delete root;root == nullptr;}bool _EraseR(Node*& root, const K& key){if (root == nullptr){return false;}if (root->_key < key){return _EraseR(root->_right, key);}else if (root->_key > key){return _EraseR(root->_left, key);}else{Node* del = root;if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{Node* leftMax = root->_left;while (leftMax->_right){leftMax = leftMax->_right;}std::swap(leftMax->_key, root->_key);std::swap(leftMax->_val, root->_val);return _EraseR(root->_left, key);}delete del;return true;}}bool _InsertR(Node*& root, const K& key, const V& val){if (root == nullptr){root = new Node(key, val);return true;}if (root->_key < key){return _InsertR(root->_right, key, val);}else if (root->_key > key){return _InsertR(root->_left, key, val);}else{return false;}}Node* _FindR(Node* root, const K& key){if (root == nullptr){return nullptr;}if (root->_key == key){return root;}else if (root->_key > key){return _FindR(root->_left, key);}else{return  _FindR(root->_right, key);}}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " :" << root->_val << endl;_InOrder(root->_right);}
private:Node* _root;
};

如上就是我们的KV模型的二叉搜索树。我们可以使用如下的两个模型,就是我们的这棵树的应用

void test1()
{BSTree<string, string> dic;dic.Insert("review", "复习");dic.Insert("product", "产品,产物");dic.Insert("education", "教育");dic.Insert("interfere", "干涉");cout << "请输入单词" << endl;string str;while (cin >> str){BSTreeNode<string, string>* ret = dic.Find(str);if (ret){cout << ret->_val << endl;}else{cout << "无此单词" << endl;cout << "请你添加单词的意思:" << endl;string str_val;cin >> str_val;dic.Insert(str, str_val);}cout << "请输入单词" << endl;}
}

如上就是一个查找单词的模型,可以帮我们快速找出单词的意思,如果没有,可以自行添加意思

image-20230908132917937

如下所示是一个水果计数的应用

void test2()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉" };BSTree<string, int> FruitCount;for (auto& e : arr){BSTreeNode<string, int>* ret = FruitCount.Find(e);if (ret == nullptr){FruitCount.Insert(e, 1);}else{ret->_val++;}}FruitCount.InOrder();}

image-20230908133012844


总结

本节主要讨论了二叉搜索树的两种应用。希望能对大家带来帮助

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/103382.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习入门教学——人工智能、机器学习、深度学习

1、人工智能 人工智能相当于人类的代理人&#xff0c;我们现在所接触到的人工智能基本上都是弱AI&#xff0c;主要作用是正确解释从外部获得的数据&#xff0c;并对这些数据加以学习和利用&#xff0c;以便灵活的实现特定目标和任务。例如&#xff1a; 阿尔法狗、智能汽车简单…

Arm 架构 Ubuntu 使用 Docker 安装 Gitlab 并使用

官方 gitlab 文档 我的系统是 arm 架构的 ubuntu 官网没有提供 arm 架构的 docker 的 gitlab 的安装方式&#xff0c;直接安装的也是后来加的&#xff0c;文档也是随笔带过&#xff0c;&#xff0c;&#xff0c;我用到了&#xff0c;记录一下 默认已经安装了 docker 在 docker …

​Vue + Element UI前端篇(二):Vue + Element 案例 ​

Vue Element UI 实现权限管理系统 前端篇&#xff08;二&#xff09;&#xff1a;Vue Element 案例 导入项目 打开 Visual Studio Code&#xff0c;File --> add Folder to Workspace&#xff0c;导入我们的项目。 安装 Element 安装依赖 Element 是国内饿了么公司提…

WordPress 网站 “Error Establishing a Database Connection” 建立数据库连接时出错的解决方法

WordPress 网站 “Error Establishing a Database Connection” 建立数据库连接时出错的解决方法 有事半年没管网站&#xff0c;今天突然访问网站居然出现了这个&#xff1a; 以下是解决方案&#xff1a; 检查数据库是否运行&#xff0c;重启数据库 1.检查数据库是否正常运…

Redis之布隆过滤器(Bloom Filter)解读

目录 引进前言 隆过滤器定义 隆过滤器原理 布隆过滤器优缺点 布隆过滤器的使用场景 布谷鸟过滤器(了解) 引进前言 在实际开发中&#xff0c;会遇到很多要判断一个元素是否在某个集合中的业务场景&#xff0c;类似于垃圾邮件的识别&#xff0c;恶意ip地址的访问&#x…

软件测试/测试开发丨跨平台 api 对接 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 跨平台 api 对接 测试平台需求 稳定 功能 调用脚本报告获取分布式支持 API 调用 开源 Jenkins 环境准备 Jenkins 满足所有调度平台的需求 需…

Alins - 化繁为简、极致优雅的WebUI框架

最近造了个js框架 Alins&#xff0c;分享一下&#xff1a; &#x1f680; Alins: 最纯粹优雅的WebUI框架 English | 文档 | 演练场 | 更新日志 | 反馈错误/缺漏 | Gitee | 留言板 0 简介 0.1 前言 Alins是一款极致纯粹、简洁、优雅的Web UI框架。秉持0-API、Less is More 的…

Java“牵手”京东商品详情数据,京东商品详情API接口,京东API接口申请指南

京东平台商品详情接口是开放平台提供的一种API接口&#xff0c;通过调用API接口&#xff0c;开发者可以获取京东商品的标题、价格、库存、月销量、总销量、库存、详情描述、图片等详细信息 。 获取商品详情接口API是一种用于获取电商平台上商品详情数据的接口&#xff0c;通过…

C# OpenVino Yolov8 Seg 分割

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp;namespace OpenVino_Yolov8_Demo {public…

React16、18 使用 Redux

Redux 核心 Redux 介绍 Redux 是javaScript 状态容器&#xff0c;提供可预测化的状态管理 Redux 工作流程 Actions&#xff1a;对象&#xff0c;描述对状态进行怎样的操作 Reducer&#xff1a;函数&#xff0c;操作状态并返回新的状态 Store&#xff1a;存储状态的容器&am…

NPM 常用命令(六)

1、npm explain 1.1 命令使用 npm explain <package-spec>别名: why 1.2 描述 此命令将打印导致在当前项目被其他引用包的依赖链。 如果提供了一个或多个包规范&#xff0c;则只有与其中一个说明符匹配的包才会解释它们的关系。 包规范还可以引用 ./node_modules 中…

关于测试的思考-质量保障体系

一、质量保障体系 1、质量保障体系说明 2、如何构建质量保障体系 3、质量保障案例 二、敏捷开发下的软件测试 1、互联网公司敏捷流程的实践 2、提升测试上线质量&#xff08;质量右移&#xff09;&#xff1a; 灰度方式&#xff1a;根据机器&#xff0c;根据用户画像&#xff…