> 文章列表 > 【C++】二叉搜索树的应用

【C++】二叉搜索树的应用

【C++】二叉搜索树的应用

前言

二叉搜索树本质也是二叉树,但因为其数据存储的特殊 — 子树的值都更小,右子树的值都更大,所以在大部分情况下,查找更为高效。本篇博客将讲述二叉搜索树两个应用搜索的场景
那么话不多说,马上开始今天的学习。

在这里插入图片描述

文章目录

  • 前言
  • 一. Key的模型
  • 二. Key_Value的模型
  • 结束语

一. Key的模型

Key的模型本质其实是在不在的问题

  1. 比如:门禁系统。当我们在进出学校时,可能需要刷校园卡,那其实校园卡里面有芯片,跟门禁交互后,可以读取到你的信息,然后拿着这个信息,去数据库中查找,找到了,那就允许通行,找不到,就不允许通行。
  2. 再比如:车库系统。如果你有这个车库的停车位,那么你进出车库,车库的杆子直接就抬起,放行。但是如果你没有车位,那么你进入停车场依然抬杆,但是你出来时候,需要支付停车费才能抬杆。这也涉及到了信息的查找和匹配。

最普通的二叉搜索树就是Key的模型每个节点只存储一个数据,且其实际意义就是那个数据的意义
比如下面这个二叉搜索树,其意义就是整型数字的存储。
【C++】二叉搜索树的应用
二叉搜索树Key模型的代码在【C++】二叉搜索树

二. Key_Value的模型

Key_Value的模型其实是映射关系Key不再单纯只有Key的意义,其还对应了一个Value
就像一把钥匙,他不仅是一把钥匙,他还有对应一个锁。我们的学号不仅是一串数字,他在学生信息管理系统中,还对应着我们的信息。

比如,我们要完成一个中英文互译的字典,就可以使用Key_Value模型,我们输入的Key是“sort”,对应的Value就是“排序”。

以下我们简单编写一下二叉搜索树的Key_Value模型的代码。其实基本框架和Key模型一样,只是类模板参数多了一个模板参数

//类模板,用于存储不同数据template<class K,class V>struct BinarySearchTree{BinarySearchTree<K,V>*_left;//左子树BinarySearchTree<K,V>*_right;//右子树K _key;//key值V _value;//value值//构造函数BinarySearchTree(const K&key,const V&value):_left(nullptr), _right(nullptr), _key(key),_value(value){}~BinarySearchTree(){_left = nullptr;_right = nullptr;}};template<class K,class V>class BSTree{typedef BinarySearchTree<K,V> Node;public://析构~BSTree(){Destroy(_root);_root = nullptr;}//插入bool Insert(const K&key,const V&value){//头为空时单独处理if (_root == nullptr){_root = new Node(key,value);return true;}//循环找插入的位置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//相等则返回假return false;}//找到了要插入的位置cur = new Node(key,value);//链接if (key > parent->_key)parent->_right = cur;elseparent->_left = cur;return true;}//中序遍历//因为二叉搜索树的特点,中序打印出来就是升序//实现封装void InOrder(){_InOrder(_root);cout << endl;}//查找Node* Find(const K&key){Node*cur = _root;//循环查找while (cur){//比当前值小,则往左走if (key < cur->_key)cur = cur->_left;else if (key > cur->_key)//大则往右走cur = cur->_right;else//不然就是相等,相等就是找到了return cur;}//循环没返回说明没查到return nullptr;}//删除bool Erase(const K&key){//分成两类//左或者右为空(包括叶子结点)//左右孩子都有//首先先找节点Node*cur = _root;//记录父亲节点Node*parent = nullptr;while (cur){//parent = cur;if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{//找到了//分两种情况//左为空if (cur->_left == nullptr){//还有可能删到根节点的一边为空(有点像歪脖子树)if (cur == _root)_root = cur->_right;else{//要判断父节点链接左还右if (parent->_left == cur)parent->_left = cur->_right;elseparent->_right = cur->_right;}delete cur;cur = nullptr;return true;}  // 右为空else if (cur->_right == nullptr){//还有可能删到根节点的一边为空(有点像歪脖子树)if (cur == _root)_root = cur->_left;else{//要判断父节点链接左还右if (parent->_left == cur)parent->_left = cur->_left;elseparent->_right = cur->_left;}delete cur;cur = nullptr;return true;}else{//左右子树都不为空//找保姆//左子树的最大节点 or 右子树的最小节点  二者都可以//  最右节点             最左节点Node*pMinRight = cur;//右子树的最小节点的父节点Node*MinRight = cur->_right;//右子树的最小节点while (MinRight->_left){pMinRight = MinRight;MinRight = MinRight->_left;}//直接赋值cur->_key = MinRight->_key;//判断父节点要链接左还是右if (pMinRight->_left == MinRight)pMinRight->_left = MinRight->_right;elsepMinRight->_right = MinRight->_right;//删除MinRight,因为完成交换了delete MinRight;MinRight = nullptr;return true;}}}return false;}protected://销毁二叉搜索树void Destroy(Node*root){if (root == NULL)return;//先删除左右节点,再删除当前节点Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}//因为要递归,所以要单独编写//注意此处不可以加缺省值_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;//根节点};

我们以英汉互译为例子,测试一下
【C++】二叉搜索树的应用
ctrl+z+回车可以正常结束这样的循环

结束语

感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述