二叉搜索树的实现与测试

目录

1.二叉搜索树的结构与特性

2.二叉搜索树的实现

(1)节点

(2)功能实现

插入:

删除:

查找:

打印:

3.测试

插入删除:

查找:

4.变种测试,即带value值

单词查找:

个数统计:


1.二叉搜索树的结构与特性

BSTree(二叉搜索树)是一个神奇的数据结构,其的特点是,左子树的所有值比根小,而右子树的所有值比根大

根据这种特性,我们可以从该结构中快速的搜索一个数的存在,速度则为树的高度次。

类似于这样的数。

2.二叉搜索树的实现

(1)节点

因为是树的结构,所以肯定少不了节点

    template<class K>struct BSTreeNode{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};

利用初始化列表将其进行初始化。

(2)功能实现

该结构应该有插入、删除功能,因为叫搜索树,所有肯定有查找功能

插入:
    bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left; }else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(key);if (parent->_key > key)parent->_left = cur;elseparent->_right = cur;return true;}

插入功能的实现逻辑很简单,只需要遵循根比左子树大,比右子树小即可。

删除:
bool Erase(const K& key){Node* cur = _root;Node* parent = cur;while (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 (parent == cur)_root = cur->_right;else{if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}}else if(cur->_right == nullptr){if (parent == cur)_root = cur->_left;else{if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}}else{Node* MinRight = cur->_left; parent = cur;while (MinRight->_right){parent = MinRight;MinRight = MinRight->_right;}cur->_key = MinRight->_key;if(parent->_right == MinRight)parent->_right = MinRight->_left;elseparent->_left = MinRight->_left;}return true;}}return false;}

删除功能的逻辑就比较复杂了,分三种情况讨论,一种是cur有两个子节点,二是cur有一个子节点,三是cur无子节点。

最后可以将二、三中情况合并处理,因为都存在nullptr。

查找:
    bool 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 true;}}return false;}

查找逻辑简单,无须多说,只需根据二叉搜索树的特性画图即可。

同时加入一个打印功能方便观察:

打印:
        void Inorder(){_Inorder(_root);cout << endl;}void _Inorder(Node* _root){if (_root == nullptr){return;}_Inorder(_root->_left);cout << _root->_key << ' ';_Inorder(_root->_right);}

创建一个_Inorder的原因是方便读取底层的_root元素,然后中序遍历即可

3.测试

插入删除:

查找:

1表示存在,0表示不存在

4.变种测试,即带value值

namespace YC_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:bool Insert(const K& key, const V& value){if (_root == nullptr){_root = new Node(key, value);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(key, value);if (parent->_key > key)parent->_left = cur;elseparent->_right = cur;return true;}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 cur;}void Inorder(){_Inorder(_root);cout << endl;}bool Erase(const K& key){Node* cur = _root;Node* parent = cur;while (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 (parent == cur)_root = cur->_right;else{if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}}else if (cur->_right == nullptr){if (parent == cur)_root = cur->_left;else{if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}}else{Node* MinRight = cur->_left;parent = cur;while (MinRight->_right){parent = MinRight;MinRight = MinRight->_right;}cur->_key = MinRight->_key;if (parent->_right == MinRight)parent->_right = MinRight->_left;elseparent->_left = MinRight->_left;}return true;}}return false;}private:void _Inorder(Node* root){if (root == nullptr){return;}_Inorder(root->_left);cout << root->_key << ":" << root->_value << endl;_Inorder(root->_right);}private:Node* _root = nullptr;};void TestBSTree2(){BSTree<string, string> dict;dict.Insert("string", "字符串");dict.Insert("left", "左边");dict.Insert("insert", "插入");//...string str;while (cin >> str){BSTreeNode<string, string>* ret = dict.find(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词,请重新输入" << endl;}}}void TestBSTree3(){// 统计次数string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };BSTree<string, int> countTree;for (const auto& str : arr){auto ret = countTree.find(str);if (ret == nullptr){countTree.Insert(str, 1);}else{ret->_value++;}}countTree.Inorder();}
};
单词查找:

个数统计:

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

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

相关文章

vue3 【提效】自动注册组件 unplugin-vue-components 实用教程

还在为每次都要导入组件而烦恼吗 &#xff1f; // 每次都需手动导入组件 import webName from /components/webName.vue用 unplugin-vue-components 来帮你吧&#xff0c;以后组件直接拿来用即可&#xff0c;无需再导入啦 &#xff01; <webName />使用流程 1. 安装 un…

逻辑这回事(七)---- 器件基础

Xilinx FPGA创建了先进的硅模块(ASMBL)架构,以实现FPGA具有针对不同应用程序领域优化的各种功能组合的平台。通过这一创新,Xilinx提供了更多的设备选择,使客户能够为其特定设计选择具有正确的功能和功能组合的FPGA。ASMBL体系结构通过以下方式突破了传统的设计障碍:消除几…

LINUX系统编程:多线程互斥

目录 1.铺垫 2.线程锁接口的认识 静态锁分配 动态锁的分配 互斥量的销毁 互斥量加锁和解锁 3.加锁版抢票 4.互斥的底层实现 1.铺垫 先提一个小场景&#xff0c;有1000张票&#xff0c;现在有4个进程&#xff0c;这四个进程疯狂的去抢这1000张票&#xff0c;看看会发生什…

新书速览|Adobe Firefly:萤火虫:AI绘画快速创意设计

《Adobe Firefly&#xff1a;萤火虫&#xff1a;AI绘画快速创意设计》 本书内容 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;浪潮的席卷已经变成不可阻挡的趋势&#xff0c;伴随着这种变化&#xff0c;在图形设计、图像制作、绘画领域也相应发生了…

什么是接口测试,我们如何实现接口测试?

1. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…

NewspaceGPT带你玩系列之SQL专家(强烈推荐)

目录 注册一个账号&#xff0c;用qq邮箱&#xff0c;然后登录选一个可用的Plus&#xff0c;不要选3.5探索GPT今天的主角是SQL Expert&#xff08;SQL 专家&#xff09;问题1&#xff1a;答1. 索引原因&#xff1a;优化措施&#xff1a;示例&#xff1a; 2. 查询设计原因&#x…

ros中teleop_twist_keyboard安装使用

目录 1.安装 2.使用 3.说明 1.安装 sudo apt-get install ros-noetic-teleop-twist-keyboard 其中noetic替换成你自己的ros版本 2.使用 roscore #启动roscore rosrun teleop_twist_keyboard teleop_twist_keyboard.py …

零基础STM32单片机编程入门(五)FreeRTOS实时操作系统详解及实战含源码视频

文章目录 一.概要二.什么是实时操作系统三.FreeRTOS的特性四.FreeRTOS的任务详解1.任务函数定义2.任务的创建3.任务的调度原理 五.CubeMX配置一个FreeRTOS例程1.硬件准备2.创建工程3.调试FreeRTOS任务调度 六.CubeMX工程源代码下载七.讲解视频链接地址八.小结 一.概要 FreeRTO…

[SwiftUI 开发] 嵌套的ObservedObject中的更改不会更新UI

1. 发生问题的demo 业务逻辑代码 class Address: ObservableObject {Published var street "123 Apple Street"Published var city "Cupertino" }class User: ObservableObject {Published var name "Tim Cook"Published var address Addr…

nacos漏洞小结

Alibaba Nacos是阿里巴巴推出来的一个新开源项目&#xff0c;是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nacos提供了一组简单易用的特性集&#xff0c;可以快速实现动态服务发现、服务配置、服务元数据及流量管理…

64、哥伦比亚大学:CU-Net-目前脑肿瘤分割的最先进模型

本文已被接受发表在2024年IEEE MLISE会议上&#xff08;c&#xff09;2024 IEEE。准确地将脑肿瘤从MRI扫描中分割出来对于制定有效的治疗方案和改善患者预后至关重要。本研究引入了一种新的哥伦比亚大学网络&#xff08;CU-Net&#xff09;架构实现&#xff0c;用于使用BraTS 2…

收银系统源码-千呼新零售2.0【移动管理端】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

如何循环遍历循环中的剩余元素

1、问题背景 给定一段文本&#xff0c;文本中包含多条错误信息&#xff0c;每条错误信息包含行号、错误路径和错误信息。需要从文本中提取出这些错误信息&#xff0c;并以特定的格式输出。 line, Error 12, This is the Error line, Error 34, Another Error line, Error …

【Linux】线程周边002之线程安全

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.Linux线程互斥 1…

每日一题——Python实现PAT乙级1050 螺旋矩阵(举一反三+思想解读+逐步优化)6千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度分析 空间复杂度分析 总结 我要更强 代码解释 时间复杂度 …

小区服务前台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;住户管理&#xff0c;管理员管理&#xff0c;员工管理&#xff0c;安保管理&#xff0c;安保分配管理&#xff0c;客服聊天管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;公告&#xff0c;…

Mongodb集群中的分布式读写

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第81篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

Java进阶学习|Day3.Java集合类(容器),Stream的使用,哈希初接触

java集合类&#xff08;容器&#xff09; Java中的集合类主要由Collection和Map这两个接口派生而出&#xff0c;其中Collection接口又派生出三个子接口&#xff0c;分别是Set、List、Queue。所有的Java集合类&#xff0c;都是Set、List、Queue、Map这四个接口的实现类&#xf…

Powershell 简易爬虫,提取种子网站的磁力链接

目录 一. 需求二. 分析2.1 思路分析2.2 技术点 三. 代码四. 效果 一. 需求 ⏹有网站如下所示&#xff0c;先要求从按照关键词搜索到的网页中&#xff0c;提取出所有的磁力链接。 二. 分析 2.1 思路分析 打开网页之后&#xff0c;从网页中先提取出所有的标题相关的url然后再打…

linux驱动部分内容整理

文章目录 Linux驱动概念应用程序调用驱动程序流程驱动模块的加载linux设备号加载和卸载注册新字符设备注册设备节点自动创建设备节点编译编译驱动程序编译应用程序 地址映射ioctrl命令码的解析 并发与竞争原子操作自旋锁信号量互斥体 linux中断DMA映射其它printkmemcpyvolatile…