C++模拟实现二叉搜索树

目录

1.二叉搜索树概念

2.二叉搜索树的实现

2.1二叉搜索树的查找

2.2二叉树的插入

2.3二叉树的删除

 3.所有代码

4.二叉搜索树的应用

5.二叉搜索树的性能分析


1.二叉搜索树概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

        若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;

        若它的右子树不为空,则右子树上所有节点的值都大于根节点的值;

        它的左右子树也分别为二叉搜索树。

二叉搜索树,也称为二叉排序树或二叉查找树。

示例:

2.二叉搜索树的实现

2.1二叉搜索树的查找

a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。

b、最多查找高度次,走到到空,还没找到,这个值不存在。

代码:

	Node* Find(const K& key) {
		Node* cur = root;
		Node* parent = nullptr;
		while (cur) {
			if (cur->val == key) 
				return cur;
			else if(key > cur->val){
				parent = cur;
				cur = cur->right;
			}
			else {
				parent = cur;
				cur = cur->left;
			}
		}
		return nullptr;
	}

2.2二叉树的插入

插入的具体过程如下:

a. 树为空,则直接新增节点,赋值给root指针

b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

bool Insert(const K& key, const V& value) {
		Node* newnode = new Node(key);
		Node* cur = root;
		Node* parent = nullptr;
		if (cur == nullptr) {
			root = newnode;
			return true;
		}
		while (cur) {
			if (cur->val == key)
				return false;
			else if (key > cur->val) {
				parent = cur;
				cur = cur->right;
			}
			else {
				parent = cur;
				cur = cur->left;
			}
		}
		if (key > parent->val)
			parent->right = newnode;
		else
			parent->left = newnode;
		return true;
	}

2.3二叉树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情

况:

        a. 要删除的结点无孩子结点;

        b. 要删除的结点只有左孩子结点;

        c. 要删除的结点只有右孩子结点;

        d. 要删除的结点有左、右孩子结点。

看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程

如下:

        情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除;

        情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除;

        情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点

中,再来处理该结点的删除问题--替换法删除。

bool Erase(const K& key) {
		Node* cur = root;
		Node* parent = nullptr;
		while (cur) {
			if (cur->val == key)
				break;
			else if (key > cur->val) {
				parent = cur;
				cur = cur->right;
			}
			else {
				parent = cur;
				cur = cur->left;
			}
		}
		if (!cur)
			return false;
		//ҵ
		if (parent == nullptr) {
			delete root;
			root = nullptr;
			return true;
		}
		if (cur->left == nullptr) {
			if (parent->left == cur)
				parent->left = cur->right;
			else
				parent->right = cur->right;
		}
		else if (cur->right == nullptr) {
			if (parent->left == cur)
				parent->left = cur->left;
			else
				parent->right = cur->left;
		}
		else {
			Node* leftMax = cur->left;
			Node* parent = leftMax;
			while (leftMax->right) {
				parent = leftMax;
				leftMax = leftMax->right;
			}
			swap(leftMax->val, cur->val);
			if (parent->left == leftMax)
				parent->left = nullptr;
			else if (parent->right == leftMax)
				parent->right = nullptr;
			cur = leftMax;
		}
		delete cur;
		cur = parent = nullptr;
		return true;
	}

 3.所有代码



template<class K, class V>
struct BSTreeNode
{
	BSTreeNode* left;
	BSTreeNode* right;
	K val;

	BSTreeNode(const K& x) 
		:left(nullptr),
		 right(nullptr),
		 val(x)
	{}
}; 

template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	BSTree()
		:root(nullptr)
	{}
	bool Insert(const K& key, const V& value) {
		Node* newnode = new Node(key);
		Node* cur = root;
		Node* parent = nullptr;
		if (cur == nullptr) {
			root = newnode;
			return true;
		}
		while (cur) {
			if (cur->val == key)
				return false;
			else if (key > cur->val) {
				parent = cur;
				cur = cur->right;
			}
			else {
				parent = cur;
				cur = cur->left;
			}
		}
		if (key > parent->val)
			parent->right = newnode;
		else
			parent->left = newnode;
		return true;
	}
	Node* Find(const K& key) {
		Node* cur = root;
		Node* parent = nullptr;
		while (cur) {
			if (cur->val == key) 
				return cur;
			else if(key > cur->val){
				parent = cur;
				cur = cur->right;
			}
			else {
				parent = cur;
				cur = cur->left;
			}
		}
		return nullptr;
	}
	bool Erase(const K& key) {
		Node* cur = root;
		Node* parent = nullptr;
		while (cur) {
			if (cur->val == key)
				break;
			else if (key > cur->val) {
				parent = cur;
				cur = cur->right;
			}
			else {
				parent = cur;
				cur = cur->left;
			}
		}
		if (!cur)
			return false;
		//ҵ
		if (parent == nullptr) {
			delete root;
			root = nullptr;
			return true;
		}
		if (cur->left == nullptr) {
			if (parent->left == cur)
				parent->left = cur->right;
			else
				parent->right = cur->right;
		}
		else if (cur->right == nullptr) {
			if (parent->left == cur)
				parent->left = cur->left;
			else
				parent->right = cur->left;
		}
		else {
			Node* leftMax = cur->left;
			Node* parent = leftMax;
			while (leftMax->right) {
				parent = leftMax;
				leftMax = leftMax->right;
			}
			swap(leftMax->val, cur->val);
			if (parent->left == leftMax)
				parent->left = nullptr;
			else if (parent->right == leftMax)
				parent->right = nullptr;
			cur = leftMax;
		}
		delete cur;
		cur = parent = nullptr;
		return true;
	}
	void _InOrder(Node* root) {
		if (root == nullptr)
			return;
		_InOrder(root->left);
		cout << root->val << " ";
		_InOrder(root->right);
	}
	void InOrder() {
		_InOrder(root);
		cout << endl;
	}
private:
	Node* root = nullptr;
};

4.二叉搜索树的应用

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

的值

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

        以词库中所有单词集合中的每个单词作为key,构建一棵二叉搜索树

        在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。

2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key, Value>的键值对。该种方

式在现实生活中非常常见:

        比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英

文单词与其对应的中文<word, chinese>就构成一种键值对;

        再比如统计单词次数,统计成功后,给定单词就可快速找到其出现的次数,单词与其出

现次数就是<word, count>就构成一种键值对

5.二叉搜索树的性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二

叉搜索树的深度的函数,即结点越深,则比较次数越多。

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

 

最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:log N;

最差情况下,二叉搜索树退化为单支树(或者类似单支),其平均比较次数为:N。

问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插

入关键码,二叉搜索树的性能都能达到最优?那么我们后续章节学习的AVL树和红黑树就可以上

场了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3D渐变柱状图

代码说明 数据准备&#xff1a; 数据可以是任意形式的矩阵&#xff0c;例如 5x7 的矩阵。 行标签 (rowLabels) 和列标签 (colLabels) 是可选的&#xff0c;如果不需要可以删除相关部分。 颜色定义&#xff1a; 使用自定义的蓝黄渐变色 (map)。 如果需要其他颜色&#xff0c;…

完美解决 error:0308010C:digital envelope routines::unsupported

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 windows电脑完美解决办法&#xff1a;设置说明…

Xilinx kintex-7系列 FPGA支持PCIe 3.0 吗?

Xilinx kintex-7系列资源如下图 Xilinx各系列的GT资源类型和性能 PCIe Gen1/2/3的传输速率对比 K7上面使用的高速收发器GTX最高速率为12.5GT/s&#xff0c; PCIe Gen2 每个通道的传输速率为 5 GT/s。 PCIe Gen3 每个通道的传输速率为 8 GT/s。 所以理论上硬件支持PCIe3.0&#…

支持列表拖拽嵌套,AI流式输出的多模态文档编辑器flowmix/docx: 全面升级

hi, 大家好, 我是徐小夕. 马上又到周五了, 最近也收到很多用户对 flowmix/docx 多模态文档编辑器的反馈&#xff0c;我们也做了一波新功能的升级&#xff0c;今天就和大家分享一下 flowmix/docx 多模态文档编辑器的最新更新. 演示地址: https://flowmix.turntip.cn/docx 以下是…

Mysql中使用sql语句生成雪花算法Id

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

聊聊 IP 地址和端口号的区别

在计算机网络中&#xff0c;两个基本概念对于理解设备如何通过网络进行通信至关重要。IP 地址和端口号是 TCP/IP 的典型特征&#xff0c;其定义如下&#xff1a;IP 地址是分配给连接到网络的每台机器的唯一地址&#xff0c;用于定位机器并与其通信。相反&#xff0c;端口号用于…

【线性代数】1行列式

1. 行列式的概念 行列式的符号表示: 行列式的计算结果:一个数 计算模型1:二阶行列式 二阶行列式: 三阶行列式: n阶行列式: 🍎计算行列式 计算模型2:上三角形行列式 上三角形行列式特征:主对角线下皆为0。 上三角形行列式: 化上三角形通用方法:主对角线下,…

问界M8细节曝光,L3自动驾驶有了!

文 | AUTO芯球 作者 | 雷慢 太惊喜了&#xff0c; 问界M8近距离实拍曝光了&#xff0c; 我看了一圈&#xff0c; 给大家扒出几个炸裂的信息&#xff0c; 注意看侧身这一堆传感器&#xff0c; 这可不是什么普通摄像头&#xff0c; 这一片传感器和和尊界S800那套一模一样&a…

支付宝 IoT 设备入门宝典(上)设备管理篇

相信不少朋友最近都被支付宝“碰一下”广告刷屏&#xff0c;“不用打开 APP 支付就碰一下”几个字一出简直自带BGM……其实“碰一下”就是支付宝 IoT 设备的一种&#xff0c;趁着热度还在&#xff0c;我会分为设备管理和设备经营上下两篇&#xff0c;简单介绍一下支付宝 IoT&am…

【Linux网络-网络基础】计算机网络背景+协议+OSI七层模型

一、计算机网络背景 网络相关概念 1.什么是网络&#xff1f; 网络是一种由多个节点&#xff08;如计算机、手机或其他电子设备&#xff09;通过通信线路或无线信号连接而成的系统。在网络中&#xff0c;信息可以通过这些节点进行传输和交换 2.独立模式 独立模式&#xff1…

VisionPro 划痕检测小练习

划痕检测,我这里用到的是Sobel算子和blob斑点匹配以及blob里面的形态学调整 Sobel 是一种在数字图像处理和计算机视觉领域广泛应用的算法&#xff0c;主要用于边缘检测 脚本展示 #region namespace imports using System; using System.Collections; using System.Drawing; …

盛铂科技 SMF106 低相位噪声贴片式频率综合器模块

在现代通信和电子设备领域&#xff0c;频率综合器作为关键组件&#xff0c;其性能优劣直接影响系统的整体表现。盛铂科技的 SMF106 低相位噪声贴片式频率综合器&#xff0c;以其卓越的性能和独特设计&#xff0c;成为众多高性能系统的选择。 一、频率覆盖范围广&#xff0c;步进…

DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”_deepseek ddos

当算力博弈升级为网络战争&#xff1a;拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下&#xff0c;网络已然成为人类社会运转的关键基础设施&#xff0c;深刻融入经济、生活、政务等各个领域。从金融交易的实时清算&#xf…

DeepSeek如何重塑我的编程学习:计算机新生的AI实践

目录 &#x1f680;前言&#x1f31f;邂逅DeepSeek&#xff1a;从困惑到惊喜&#x1f4af;初学编程的困境&#x1f4af;DeepSeek的优势 &#x1f58a;️DeepSeek在编程学习中的运用&#x1f4af;注释&#x1f4af;算法逐步分析&#x1f4af;调试帮助&#x1f4af;跨语言迁移学习…

内网穿透简单使用

简介 简单概括&#xff0c;通过【内网穿透软件】将内网与外网通过隧道打通&#xff0c;外网可以读取内网中的数据。 在这里推荐2个免费的内网穿透服务&#xff0c;分别是&#xff1a; cpolar:https://www.cpolar.com/natapp:https://natapp.cn/ 这里以cpolar为例&#xff0c;…

CentOS搭建PPPOE服务器

一、安装软件包 yum -y install rp-pppoe 二、配置服务器 1.修改配置文件 打开/etc/ppp/pppoe-server-options文件 nano /etc/ppp/pppoe-server-options 编辑为以下内容&#xff1a; # PPP options for the PPPoE server # LIC: GPL require-pap require-chap login …

C语言之easyX

目录 概要 easyX整体架构 图形绘制 画布宽高 圆形 图片的贴图 加载图像 游戏框架 概要 easyX是一个轻量级的图形库&#xff0c;用于在Windows平台上进行简单的2D图形绘制。它提供了一组简单易用的函数&#xff0c;可以方便地绘制基本的图形元素&#xff0c;如线条、矩形、圆形…

通过docker启用rabbitmq插件

创建文件&#xff0c;docker-compose.yml services:rabbitmq:image: rabbitmq:4.0-managementports:- "5672:5672"- "15672:15672"volumes:- ./data/rabbitmq/data:/var/lib/rabbitmq # 持久化数据- ./data/rabbitmq/plugins/rabbitmq_delayed_message_ex…

PMP--冲刺--流程图

文章目录 变更易混点&#xff1a;是否需要向CCB提交正式书面变更请求 质量规划风险应对 采购管理决策流程问题处理流程日志更新问题 敏捷 变更 易混点&#xff1a;是否需要向CCB提交正式书面变更请求 第一步&#xff1a;知道&#xff1a;项目预算成本基准应急储备&#xff1b;…

2025Java面试题超详细整理《微服务篇》

什么是微服务架构&#xff1f; 微服务框架是将某个应用程序开发划分为许多独立小型服务&#xff0c;实现敏捷开发和部署&#xff0c;这些服务一般围绕业务规则进行构建&#xff0c;可以用不同的语言开发&#xff0c;使用不同的数据存储&#xff0c;最终使得每个服务运行在自己…