当前位置: 首页 > news >正文

二叉查找树的应用 —— K模型和KV模型

文章目录

  • 前言
  • 1. K模型
  • 2. KV模型
    • 🍑 构建KV模型的树
    • 🍑 英汉词典
    • 🍑 统计水果出现的次数
  • 3. 总结


前言

在上一篇文章中,我们进行了二叉查找树的实现(文章链接),那么今天主要探讨一下二叉查找树的应用

1. K模型

K 模型即只有 key 作为关键码,结构中只需要存储 Key 即可,关键码即为需要搜索到的值。

比如:给一个单词 word,判断该单词是否拼写正确,具体方式如下:

  • 以单词集合中的每个单词作为 key,构建一棵二叉查找树
  • 在二叉查找树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。

其实这个 K 模型就是上一篇文章中,我们实现的二叉查找树。

2. KV模型

所谓 KV 模型就是每一个关键码 key,都有与之对应的值 Value,即 <Key, Value> 的键值对。

这种方式在现实生活中非常常见:比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英文单词与其对应的中文 <word, chinese>就构成一种键值对;

再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出现次数就是 <word, count> 就构成一种键值对。

下面我们就构造一个 KV 模型的二叉查找树,然后用这棵树来做一些应用。

🍑 构建KV模型的树

我这里直接用递归的方式实现整颗树,需要添加一个模板参数 Value,另外对于查找函数 Find 的返回值就不能写成 bool 类型了,而是需要写成 Node* 类型,因为 Key 不能被修改,但是我们可以通过返回的节点类型来修改 Key 对应的 Value

代码实现

// KV模型
namespace key_value
{	// 节点类template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left; // 左指针BSTreeNode<K, V>* _right; // 右指针K _key; // 关键码V _value; // 对应的值// 构造函数BSTreeNode(const K& key, const V& value):_left(nullptr), _right(nullptr), _key(key), _value(value){}};// 二叉查找树类template<class K, class V>class BSTree{typedef BSTreeNode<K, V> Node;public:// 中序遍历void InOrder(){_InOrder(_root);cout << endl;}// 查找函数Node* FindR(const K& key){return _FindR(_root, key);}// 插入函数// 注意:这里除了要插入key,还要插入对应的valuebool InsertR(const K& key, const V& value){return _InsertR(_root, key, value);}// 删除函数(只需要删除key即可)bool EraseR(const K& key){return _EraseR(_root, key);}private:// 删除函数(递归删除子函数)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* minRight = root->_right;while (minRight->_left){minRight = minRight->_left;}swap(root->_key, minRight->_key);return _EraseR(root->_right, key);}delete del;return true;}}// 插入函数(递归插入子函数)bool _InsertR(Node*& root, const K& key, const V& value){if (root == nullptr){root = new Node(key, value);return true;}if (root->_key < key)return _InsertR(root->_right, key, value);else if (root->_key > key)return _InsertR(root->_left, key, value);elsereturn false;}// 查找函数(递归查找子函数)Node* _FindR(Node* root, const K& key){if (root == nullptr)return nullptr;if (root->_key < key){return _FindR(root->_right, key);}else if (root->_key > key){return _FindR(root->_left, key);}else{return root;}}// 中序遍历(递归遍历子函数)void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root = nullptr;};
}

🍑 英汉词典

用这棵树实现一个简单的英汉词典 dict,可以通过英文找到与其对应的中文。

<单词, 中文含义> 为键值对构造二叉查找树时,二叉查找树需要进行键值对的比较,并且只需要比较 Key,查询英文单词时,只需给出英文单词,就可快速找到与其对应的 key。

代码实现

void TestBSTree1()
{BSTree<string, string> ECDict;ECDict.InsertR("root", "根");ECDict.InsertR("string", "字符串");ECDict.InsertR("left", "左边");ECDict.InsertR("insert", "插入");ECDict.InsertR("erase", "删除");ECDict.InsertR("right", "右边");cout << "请输入要查找的单词: ";string str; // 输入要查找的单词while (cin >> str){auto ret = ECDict.FindR(str);if (ret != nullptr){cout << "对应的中文:" << ret->_value << endl; // 如果单词存在,输出对应的中文}else{cout << "无此单词,请重新输入" << endl; // 如果单词不存在}}
}

可以看到,当我们输入树中存在的单词时,就会显示对应的中文,如果单词不存在,就不会显示。

在这里插入图片描述

如果我们要修改某个单词的中文也是可以的,只需要修改节点指向的 Value 即可。

🍑 统计水果出现的次数

KV 模型的二叉树还可以用来统计某个元素出现的次数。

比如下面有一组水果,现在我需要统计水果出现的次数,并输出。

代码实现

void TestBSTree2()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };// 水果出现的次数BSTree<string, int> countTree; // key是字符串; value是次数for (const auto& str : arr){auto ret = countTree.FindR(str); // 查找该水果是否存在if (ret == nullptr) // 如果该水果不存在{countTree.InsertR(str, 1); // 就插入到树中,并把次数置为1(出现了一次)}else // 如果该水果存在{ret->_value++;  // 就修改value}}// 打印结果countTree.InOrder();
}

可以看到水果的次数已经被统计出来了

在这里插入图片描述

3. 总结

对于 K 模型的二叉查找树上节课我们已经说过了,它有很多缺点,后面的 AVL树 就是在它的基础上进行优化的,那么与之对应的就是 STL 当中的 set 容器,它的底层就是一颗 K 模型的二叉查找树。

对于 KV 模型的二叉查找树,它与之对应的是 STL 当中的 map 容器,它的底层是一颗 KV 模型的二叉查找树。

相关文章:

二叉查找树的应用 —— K模型和KV模型

文章目录前言1. K模型2. KV模型&#x1f351; 构建KV模型的树&#x1f351; 英汉词典&#x1f351; 统计水果出现的次数3. 总结前言 在上一篇文章中&#xff0c;我们进行了二叉查找树的实现&#xff08;文章链接&#xff09;&#xff0c;那么今天主要探讨一下二叉查找树的应用…...

深度学习实战(11):使用多层感知器分类器对手写数字进行分类

使用多层感知器分类器对手写数字进行分类 1.简介 1.1 什么是多层感知器&#xff08;MLP&#xff09;&#xff1f; MLP 是一种监督机器学习 (ML) 算法&#xff0c;属于前馈人工神经网络 [1] 类。该算法本质上是在数据上进行训练以学习函数。给定一组特征和一个目标变量&#x…...

ThingsBoard-警报

1、使用 IoT 设备警报 ThingsBoard 提供了创建和管理与您的实体相关的警报的能力:设备、资产、客户等。例如,您可以将 ThingsBoard 配置为在温度传感器读数高于某个阈值时自动创建警报。当然,这是一个非常简化的案例,实际场景可能要复杂得多。 2、主要概念 下面让我们回…...

如何去阅读源码,我总结了18条心法

在聊如何去阅读源码之前&#xff0c;先来简单说一下为什么要去阅读源码&#xff0c;大致可分为以下几点原因&#xff1a;最直接的原因&#xff0c;就是面试需要&#xff0c;面试喜欢问源码&#xff0c;读完源码才可以跟面试官battle提升自己的编程水平&#xff0c;学习编程思想…...

排序:归并排序

一、归并 li[2,4,5,7,//1,3,6,8]#归并的前提是必须两部分排好序 def merge(li,low,mid,high):ilowjmid1ltmp[]while i<mid and j<high: #只要左右两边都有数if li[i]<li[j]:ltmp.append(li[i])i1else:ltmp.append(li[j])j1#while执行完&#xff0c;肯定有一部分没数…...

Allegro172版本线到铜皮不按照设定值避让的原因和解决办法

Allegro172版本线到铜皮不按照设定值避让的原因和解决办法 用Allegro做PCB设计的时候,有时会单独给某块铜皮附上线到铜皮额外再增加一个数值,如下图 在规则的基础上,额外再避让10mil 规则避让line到铜皮10.02mil 额外设置多避让10mil,避让的结果却是30.02mil,正确的是20.…...

小白该从哪方面入手学习大数据

大数据本质上是海量数据。 以往的数据开发&#xff0c;需要一定的Java基础和工作经验&#xff0c;门槛高&#xff0c;入门难。 如果零基础入门数据开发行业的小伙伴&#xff0c;可以从Python语言入手。 Python语言简单易懂&#xff0c;适合零基础入门&#xff0c;在编程语言…...

尚医通(十)数据字典加Redis缓存 | MongoDB

目录一、Redis介绍二、数据字典模块添加Redis缓存1、service_cmn模块&#xff0c;添加redis依赖2、service_cmn模块&#xff0c;添加Redis配置类3、在service_cmn模块&#xff0c;配置文件添加redis配置4、通过注解添加redis缓存5、查询数据字典列表添加Redis缓存6、bug&#x…...

为什么我们不再发明编程语言了?

上个世纪&#xff0c;数百种编程语言被发明出来&#xff0c;但是进入21世纪&#xff0c;当我们都进入互联网时代时&#xff0c;只剩那么寥寥几个了。 如果你翻一下TIOBE得编程语言排行榜&#xff0c;就会发现20年来&#xff0c;上蹿下跳的就是那几张老面孔&#xff1a;C , Java…...

预处理指令详解

预处理指令详解**1.预定义符号****2.#define****2.1 #define 定义标识符****2.2 #define 定义宏****2.3 #define 替换规则****2.4 #和##****#的作用****##的作用****2.5 带副作用的宏参数****2.6 宏和函数的对比****宏和函数对比图****2.7 命名约定****3.#undef**4.条件编译4.1…...

Redis

一.认识NoSQL 1.SQL 关系型数据库 结构化: 定义主键&#xff0c;无符号型数据等关联的&#xff1a;结构化表和表之间的关系通过外键进行关联&#xff0c;节省存储空间SQL查询&#xff1a;语法固定 SELECT id,name,age FROM tb_user WHERE id1 ACID 2.NoSQL 非关系型数据库 Re…...

Elasticsearch5.5.1 自定义评分插件开发

文本相似度插件开发&#xff0c;本文基于Elasticsearch5.5.1&#xff0c;Kibana5.5.1 下载地址为&#xff1a; Past Releases of Elastic Stack Software | Elastic 本地启动两个服务后&#xff0c;localhost:5601打开Kibana界面&#xff0c;点击devTools&#xff0c;效果图…...

4.4 序列化与反序列化

文章目录1.概述2.特点/应用场景3.涉及到的流对象4.代码实现序列化与反序列化4.1 步骤1&#xff1a;创建学生类Student24.2 步骤2&#xff1a;创建序列化测试类5.测试案例中常见的几种编译错误类型6.为什么反序列化版本号需要与序列化版本号一致&#xff1f;7.自动提示 生成UID …...

647. 回文子串 516. 最长回文子序列

647. 回文子串 方法一&#xff1a;动态规划 dp[i][j]:[i,j]范围的下标字符串s是否为回文子串 遍历字符串&#xff0c;每次判断s[i]与s[j]是否相等 ①若相等&#xff0c;j-i0 即单个字符串s[i]&#xff0c;那么一定为回文子串&#xff0c;赋值为1 ②若相等&#xff0c;j-i1…...

实用小妙招

记录一些实用小妙招&#xff0c;都是收藏夹里收藏的各种文章&#xff0c;总结在一起&#xff0c;持续更新 实用小妙招LinuxUbuntu修改终端语言安装 Node.js (nvm)git 记住账号密码WSL迁移默认用户修改Linux Ubuntu 修改终端语言 apt update apt install -y language-pack-zh…...

别让猴子跳回背上

1.管理者的贡献来自于他们的判断力与影响力&#xff0c;而非他们所投入的个人时间与埋头苦干 2.管理者的绩效表现则是许多人群策群力的结果 3.管理者的时间管理: 老板占用的时间;组织占用的时间;自己占用的时间;外界占用的时间; 4.管理者的策略在于增加自己的时间&#xff0c…...

数据结构 | 线性表

&#x1f525;Go for it!&#x1f525; &#x1f4dd;个人主页&#xff1a;按键难防 &#x1f4eb; 如果文章知识点有错误的地方&#xff0c;请指正&#xff01;和大家一起学习&#xff0c;一起进步&#x1f440; &#x1f4d6;系列专栏&#xff1a;数据结构与算法 &#x1f52…...

Deepwalk深度游走算法

主要思想 Deepwalk是一种将随机游走和word2vec两种算法相结合的图结构数据的挖掘算法。该算法可以学习网络的隐藏信息&#xff0c;能够将图中的节点表示为一个包含潜在信息的向量&#xff0c; Deepwalk算法 该算法主要分为随机游走和生成表示向量两个部分&#xff0c;首先…...

微服务项目【服务调用分布式session共享】

nginx动静分离 第1步&#xff1a;通过SwitchHosts新增二级域名&#xff1a;images.zmall.com 第2步&#xff1a;将本次项目的所有静态资源js/css/images复制到nginx中的html目录下 第3步&#xff1a;在nginx的核心配置文件nginx.conf中新增二级域名images.zmall.com访问映射…...

神经网络的万能逼近定理

这是我见过的讨论神经网络万有逼近问题的最好的文章。在文章中&#xff0c;给出了最清晰&#xff0c;简洁的构造性证明。揭示了它的本质。 三十年前&#xff0c;我们接触到神经网络的万有逼近问题。发表了几篇文章。这些文章把神经网络能力的来历、优点、缺点&#xff0c;都已…...

【信息系统项目管理师】项目管理过程的三万字大论文

【信息系统项目管理师】项目管理过程的三万字大论文 【信息系统项目管理师】项目管理过程的三万字大论文 【信息系统项目管理师】项目管理过程的三万字大论文1.制定项目章程2.识别干系人3.制定范围管理计划4.制定进度管理计划5.制定成本管理计划6.制定质量管理计划7.编制人力资…...

【C++】C++11 ~ 包装器解析

&#x1f308;欢迎来到C专栏~~包装器解析 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&a…...

SpringBoot整合(三)SpringBoot发送邮件

使用SpringBoot发送邮件 邮件发送其实是一个非常常见的需求&#xff0c;用户注册&#xff0c;找回密码等地方&#xff0c;都会用到&#xff0c;Spring Boot 中对于邮件发送&#xff0c;提供了相关的自动化配置类&#xff0c;使得邮件发送变得非常容易。 1、前置工作 目前国内…...

【docker知识】联合文件系统(unionFS)原理

一、说明 Docker CLI 操作起来比较简单——您只需掌握Create、Run、InspPull和Push容器和图像&#xff0c;但是谁想过Docker 背后的内部机制是如何工作的&#xff1f;在这个简单的表象背后隐藏着许多很酷的技术&#xff0c; UnionFS&#xff08;统一文件系统&#xff09;就是其…...

使用Lame库实现wav、pcm转mp3

文章目录 前言 一、Lame库是什么&#xff1f; 二、使用步骤 0.创建native项目 1.下载Lame库 2.pcm转MP3 3.wav转MP3 4、native方法如下 三、注意 总结 前言 因为使用android录音后生成的文件是wav或者pcm格式&#xff0c;项目要求最后的文件需要是mp3格式&#xff0c;于…...

c++11 标准模板(STL)(std::multimap)(三)

定义于头文件 <map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class multimap;(1)namespace pmr { template <class Key, class T…...

【报复性赚钱】2023年5大风口行业

今天就来和大家分享一下&#xff0c;在时代的洪流下&#xff0c;普通人如何顺应大势抓住机遇&#xff01; 实现人在风口上&#xff0c;猪都会飞起来。 根据对市场的观察及各平台数据分析结果&#xff0c;结合国家政策和经济专家的分析&#xff0c;小编预测了2023年将会迎来大…...

单目相机、双目相机和RGB-D相机学习笔记(一些视频和博文网址)

目录1. 单目相机1.1 摄像头原理1.2 单目相机的标定2 双目相机2.1 双目相机定位原理2.2 双目相机的缺陷3 RGB-D相机3.1 深度相机结构光原理3.2 RGB-D相机的应用1. 单目相机 1.1 摄像头原理 视频网址&#xff1a;【全网最详细】摄像头原理分析&#xff08;约25分钟课程&#xf…...

word和wps添加mathtype选项卡

word或wps添加mathtype选项卡 前提 安装好word或wps安装好mathtype 步骤 确认word或wps具体安装位置确认word或wps位数为32位还是64位复制mathtype中的MathPage.wll文件和MathType Commands 2016.dotm文件到STARTUP位置添加受信任位置添加加载项 安装位置 通过开始页面&a…...

获取成员userID

文章目录一、简介二、获取token1、获取秘钥2、获取Token三、获取部门数据1、获取部门列表2、获取子部门ID列表3、获取单个部门详情四、获取成员信息1、读取成员2、获取部门成员3、获取部门成员详情一、简介 同步数据到企微&#xff1a; 企业如果需要从自有的系统同步通讯录到…...

商洛网站开发/线上广告推广平台

回调对象是一个多用途的回调列表对象&#xff0c;提供了强大的的方式来管理回调函数列表。 最简单的缓存对象 function Callbacks(){var list [],self {add: function(fn){list.push(fn);},remove: function(fn){var index;if((index list.indexOf(fn)) > -1){list.spli…...

wordpress应用微信支付宝/兰州网络推广公司哪家好

超限邻域滤波 1、前言 超限邻域滤波是在均值滤波的基础增加阈值处理,可以在有效地去除椒盐噪声的同时尽可能保留原图像信息。 2、超限邻域滤波描述 设 G ( x , y ) G(x,y) G(x,y)为输入图像,...

桂林市建设工程造价管理站网站/新手怎么学电商运营

据央视报道&#xff0c;中国人民银行副行长范一飞今日在第六届中国支付清算论坛上表示&#xff0c;我国将大幅放宽金融业市场准入&#xff0c;欢迎和鼓励外资进入支付清算市场。同时对现有的经营主体加强监管、规范&#xff0c;对违规零容忍。范一飞表示&#xff0c;我国将全面…...

注册网站帐号注销/淘宝推广怎么做

我的简单jQuery的加载语句需要花费太多时间(50秒).没有服务器端问题,服务器的页面逻辑很简单.我也试过$.ajax,$.get甚至尝试使用ManualAJAX调用(XMLHttpRequest).以下是jQuery加载的示例.$(function() {$(#frmPrd).live(submit, function(event) {event.preventDefault();mUrl …...

网站后台如何添加代码/国外网站如何搭建网页

网站视频存放服务器 内容精选换一换简要介绍Web Bench是Linux中被广泛使用的网站压力测试工具&#xff0c;同时支持HTTPS静态网站和动态网站。编写语言&#xff1a;C/C一句话概述&#xff1a;网站压力测试工具建议的版本建议使用版本为1.5。云服务器要求本文以云服务器KC1实例测…...

wordpress插件要求/爱站网站排名查询工具

为什么80%的码农都做不了架构师&#xff1f;>>> 编写一个程序&#xff0c;定义一个名为 button 的类&#xff0c;表示GUI中的一个可点击按钮。 为该类加入两个方法 add_handler() 和 remove_handler()&#xff0c;它们均要求一个函数名作为参数。 如果 click() 方法…...