C++/数据结构:二叉搜索树的实现与应用

目录

一、二叉搜索树简介

二、二叉搜索树的结构与实现

2.1二叉树的查找与插入

2.2二叉树的删除

2.3二叉搜索树的实现

2.3.1非递归实现

 2.3.2递归实现

三、二叉搜索树的k模型和kv模型


一、二叉搜索树简介

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:。
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
它的左右子树也分别为二叉搜索树。

二、二叉搜索树的结构与实现

2.1二叉树的查找与插入

int a [] = { 8 , 3 , 1 , 10 , 6 , 4 , 7 , 14 , 13 };
1. 二叉搜索树的查找
a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。
2. 二叉搜索树的插入
插入的具体过程如下:
a. 树为空,则直接新增节点,赋值给root指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

2.2二叉树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情
况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程
如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点
中,再来处理该结点的删除问题--替换法删除。

2.3二叉搜索树的实现

2.3.1非递归实现

//二叉树节点的构建
template<class K>struct BSTreeNode{typedef BSTreeNode<K> Node;Node* _left;Node* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};//class BinarySearchTreetemplate<class K>class BSTree{typedef BSTreeNode<K> Node;public:// 强制生成默认构造BSTree() = default;//拷贝构造BSTree(const BSTree<K>& t){_root = Copy(t._root);}//赋值拷贝BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}//析构函数~BSTree(){Destroy(_root);}/////增删查改//插入数据bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}//查找数据bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key < key){cur = cur->_right;}else if (cur->_key > key){cur = cur->_left;}else{return true;}}return false;}//删除数据bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (cur == parent->_right){parent->_right = cur->_right;}else{parent->_left = cur->_right;}}delete cur;return true;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (cur == parent->_right){parent->_right = cur->_left;}else{parent->_left = cur->_left;}}delete cur;return true;}else{// 替换法Node* rightMinParent = cur;Node* rightMin = cur->_right;while (rightMin->_left){rightMinParent = rightMin;rightMin = rightMin->_left;}cur->_key = rightMin->_key;if (rightMin == rightMinParent->_left)rightMinParent->_left = rightMin->_right;elserightMinParent->_right = rightMin->_right;delete rightMin;return true;}}}return false;}private:Node* _root;};

 2.3.2递归实现

//二叉树节点的构建
template<class K>struct BSTreeNode{typedef BSTreeNode<K> Node;Node* _left;Node* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};//class BinarySearchTreetemplate<class K>class BSTree{typedef BSTreeNode<K> Node;public:// 强制生成默认构造BSTree() = default;//拷贝构造BSTree(const BSTree<K>& t){_root = Copy(t._root);}//赋值拷贝BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}//析构函数~BSTree(){Destroy(_root);}/////增删查改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);}void InOrder(){_InOrder(_root);cout << endl;}private:void Destroy(Node* root){if (root == nullptr)return;Destroy(root->_left);Destroy(root->_right);delete 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;}//借助引用可以更好的删除和更改数据节点,不需要再额外创建父节点来更改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->_right == nullptr){root = root->_left;}else if (root->_left == nullptr){root = root->_right;}else{Node* rightMin = root->_right;while (rightMin->_left){rightMin = rightMin->_left;}swap(root->_key, rightMin->_key);return _EraseR(root->_right, key);}delete del;return true;}}bool _InsertR(Node*& root, const K& key){if (root == nullptr){root = new Node(key);return true;}if (root->_key < key){return _InsertR(root->_right, key);}else if (root->_key > key){return _InsertR(root->_left, key);}else{return false;}}bool _FindR(Node* root, const K& key){if (root == nullptr)return false;if (root->_key < key){return _FindR(root->_right, key);}else if (root->_key > key){return _FindR(root->_left, key);}else{return true;}}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}Node* _root;};

三、二叉搜索树的k模型和kv模型

1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到
的值
比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:
以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
例如:小区停车场,只要可以搜索到车牌号就可以自由进出。
2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方
式在现实生活中非常常见:
比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英
文单词与其对应的中文<word, chinese>就构成一种键值对;
再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出
现次数就是<word, count>就构成一种键值对
例如:商场停车场,进去时记录车牌号,出来时查询是否缴费,如果缴费才可以出去。
改造搜素二叉树为kv结构:
// 改造二叉搜索树为KV结构
template<class K, class V>
struct BSTNode{BSTNode(const K& key = K(), const V& value = V()): _pLeft(nullptr) , _pRight(nullptr), _key(key), _Value(value){}BSTNode<T>* _pLeft;BSTNode<T>* _pRight;K _key;V _value};
template<class K, class V>
class BSTree{typedef BSTNode<K, V> Node;typedef Node* PNode;
public:BSTree(): _pRoot(nullptr){}PNode Find(const K& key);bool Insert(const K& key, const V& value)bool Erase(const K& key)
private:PNode _pRoot;};void TestBSTree()
{// 输入单词,查找单词对应的中文翻译BSTree<string, string> dict;dict.Insert("string", "字符串");dict.Insert("tree", "树");dict.Insert("left", "左边、剩余");dict.Insert("right", "右边");dict.Insert("sort", "排序");// 插入词库中所有单词string str;while (cin>>str){BSTreeNode<string, string>* ret = dict.Find(str);if (ret == nullptr){cout << "单词拼写错误,词库中没有这个单词:" <<str <<endl;}else{cout << str << "中文翻译:" << ret->_value << endl;}}
}

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

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

相关文章

从零开始教你手动搭建幻兽帕鲁私服( CentOS 版)

哈喽大家好&#xff0c;我是咸鱼。 想必上网冲浪的小伙伴最近都被《幻兽帕鲁》这款游戏刷屏了。 (文中图片均来自网络&#xff0c;侵删) 幻兽帕鲁是 Pocketpair 打造的一款开放世界的生存建造游戏。在游戏中&#xff0c;玩家捕捉各种各样的“帕鲁”。 “帕鲁” 在玩家支配下…

飞桨paddlespeech语音唤醒推理C INT8 定点实现

前面的文章&#xff08;飞桨paddlespeech语音唤醒推理C定点实现&#xff09;讲了INT16的定点实现。因为目前商用的语音唤醒方案推理几乎都是INT8的定点实现&#xff0c;于是我又做了INT8的定点实现。 实现前做了一番调研。量化主要包括权重值量化和激活值量化。权重值由于较小且…

[网络安全] IIS----WEB服务器

一、 WEB服务器 WEB服务器 也叫网页服务器和 HTTP服务器使用协议: HTTP(端口:80) 或 HTTPS(端口443)浏览器:HTTP客户端网站: 一个或多个网页组成的集合 二、HTTP和HTTPS协议: HTTP : 是 HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09;的简写&#xff0c;…

MySQL-DQL(Data Query Language)数据查询语言

文章目录 1. DQL定义2. 基础查询3. 条件查询&#xff08;WHERE&#xff09;4. 分组查询&#xff08;GROUP BY&#xff09;5. 过滤分组&#xff08;HAVING&#xff09;6. 排序&#xff08;ORDER BY&#xff09;7. 限制查询结果的条数&#xff08;LIMIT&#xff09;8. 多表查询8.…

6、应急响应-日志自动提取自动分析ELKLogkitLogonTracerAnolog等

用途&#xff1a;个人学习笔记&#xff0c;欢迎指正 目录 背景: 一、日志自动提取-七牛Logki&观星应急工具 1、七牛Logkit: (支持Windows&Linux&Mac等) 2、观星应急工具(只支持Windows) 二、日志自动分析-Web-360星图&Goaccess&ALB&Anolog 1、W…

敏捷认证大热:PMI-ACP

你是否在寻找一个能让你在不断变化的职场环境中脱颖而出的认证&#xff1f;PMI-ACP正是你需要的&#xff01;这个由美国项目管理协会PMI颁发的认证&#xff0c;是全球敏捷项目管理领域的权威代表。无论你是希望转型到项目管理领域&#xff0c;还是想提升现有项目管理技能&#…

内存取证 | Volatility使用手册

本文由掌控安全学院 - 君叹 投稿 volatility常用命令 查看volatility已安装的profile和插件 volatility --info 当我们拿到一个内存文件镜像的时候&#xff0c;一般来说我们应该先用 imageinfo&#xff0c;查看镜像的信息 imageinfo 查看系统摘要信息 -f 指定一个镜像文件…

C++文件操作(2)

文件操作&#xff08;2&#xff09; 1.二进制模式读取文本文件2.使用二进制读写其他类型内容3.fstream类4.文件的随机存取文件指针的获取文件指针的移动 1.二进制模式读取文本文件 用二进制方式打开文本存储的文件时&#xff0c;也可以读取其中的内容&#xff0c;因为文本文件…

20240127在ubuntu20.04.6下配置whisper

20240131在ubuntu20.04.6下配置whisper 2024/1/31 15:48 首先你要有一张NVIDIA的显卡&#xff0c;比如我用的PDD拼多多的二手GTX1080显卡。【并且极其可能是矿卡&#xff01;】800&#xffe5; 2、请正确安装好NVIDIA最新的驱动程序和CUDA。可选安装&#xff01; 3、配置whispe…

Redis核心技术与实战【学习笔记】 - 10.浅谈CPU架构对Redis性能的影响

概述 可能很多人都认为 Redis 和 CPU 的关系简单&#xff0c;Redis 的线程在 CPU 上运行&#xff0c;CPU 快 Reids 处理请求的速度也很快。 其实&#xff0c;这种认知是片面的&#xff0c;CPU 的多核架构及多 CPU 结构&#xff0c;也会影响到 Redis 的性能。如果不了解 CPU 对…

操作系统基础:进程同步【下】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;OS从基础到进阶 1 进程同步⛵1.1 吸烟者问题✈️1.1.1 问题描述✈️1.1.2 问题分析1.1.2.1 关系分析&#xff08;确定同步、互斥关系&#xff09;1.1.2.2 整理思路&#xff08;确定PV操作的…

Kafka运维相关知识

目录 一、基本概念 二、技术特性 三、设计思想 四、运维建议 一、基本概念 Apache kafka 是一个分布式的基于push-subscribe的消息系统&#xff0c;它具备快速、可扩展、可持久化的特点。它的最大的特性就是可以实时的处理大量数据以满足各种需求场景&#xff1a;比如基于h…