【查找】二叉排序树(BST)

news2024/9/22 3:16:31

有序序列查找可以用二分查找,但其插入删除需要移动数据,较为复杂;若不想多的移动,可以弄成无序序列,但这样就不能用二分查找。

为了不影响数据顺序,可以使用二叉排序树,

概念:

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

每个结点都有一个作为搜索依据的关键码key,所有结点的关键码 互不相同
左子树上所有结点的关键码都小于根结点的关键码;
右子树上所有结点的关键码都大于根结点的关键码、
左右子树也是二叉搜索树;
中序遍历这棵树,是从小到大排好序的;
最左边的孩子一定是最小的结点,最右边的孩子一定是最大的结点。

互不相同的原因:这是搜索树,不是为了创建而创建的,所以有重复的值可以不用插。

实际上二叉搜索树是个三叉链表,有指向左右孩子和双亲的三个指针,用于查找。

建立

结点结构

classBSTNode
{
public:
	BSTNode():m_left(nullptr), m_right(nullptr) {}
	BSTNode(int v):m_val(v),m_left(nullptr),m_right(nullptr) {}
	int m_val;
	BSTNode* m_left;
	BSTNode* m_right;
};

树建立

class BSTree
{
public:
	BSTree():m_root(nullptr){}
	void InsertValueST(int v)//插入
	{
		InsertValueBST(m_root, v);
	}
	void InsertValueBST(BSTNode*& root, int v);
	void Print()//打印
	{
		InOrder(m_root);
		cout << endl;
	}
	void InOrder(BSTNode* root);//中序遍历
	BSTNode* SearchValue(int v)//查找
	{
		return SearchValue(m_root, v);
	}
	BSTNode* SearchValue(BSTNode* root, int v);
	BSTNode* GetMax();//找最大
	BSTNode* GetMin();//找最小
	void DeleteValue(int v)//删除
	{
		DeleteValue(m_root, v);
	}
	void DeleteValue(BSTNode* &root, int v);
private:
	BSTNode* m_root;
};

输出

        输出用中序遍历,按顺序输出

void Print()
 {
  InOrder(m_root);
  cout << endl;
 }
 void InOrder(BSTNode* root);


void BSTree::InOrder(BSTNode* root)
{
	if (root != nullptr)
	{
		InOrder(root->m_left);
		cout << root->m_val << " ";
		InOrder(root->m_right);
	}
}

查询

将当前根与key比较,如果等于则输出;如果小于则找左子树,否则找右子树;

非递归的查找

BstNode* FindValue(BSTree* tree,int v)
{
    BstNode* p = tree;
    while (p != nullptr && p->val != v)
    {
        p = v < p->val ? p->m_left : p->m_right;
    }
    return p;
}

递归的查找

BSTNode* BSTree::SearchValue(BSTNode* root, int v)
{
	if (root==nullptr)
		return root;
	if (v < root->m_val)
		SearchValue(root->m_left, v);
	else if(v>root->m_val)
		SearchValue(root->m_right, v);
	else if(v==root->m_val)
		return root;
}

        注意:  每个结点的前驱是第一个左孩子的最右边的孩子,后继是第一个右孩子的最左侧的孩子(删除要用这个思想!!)

找最大、最小值

最大值:一直找右孩子,直到右为空是的结点为最大值;

最小值:一直找左孩子,直到左为空。

BSTNode* BSTree::GetMax()
{
	BSTNode* p = m_root;
	if (p != nullptr)
	{
		while (p->m_right != nullptr)
			p = p->m_right;
	}
	return p;
}
BSTNode* BSTree::GetMin()
{
	BSTNode* p = m_root;
	if (p != nullptr)
	{
		while (p->m_left != nullptr)
			p = p->m_left;
	}
	return p;
}

删除!!!

创建一个t指向结点的指针temp

当根不为空:

        若值比根小,递归在左边删

        若值比根大,递归在右边删

        若key等于当前结点值

                若根有左右孩子

                           使temp指向根第一个左子树的最右边,或第一个右子树的最左边,将root的值换成temp指向的,删temp;

                若只有一个孩子或没有孩子

                        让temp=root,root指向其唯一的孩子(或空),删除temp       

void BSTree::DeleteValue(BSTNode* &root, int v)
{
	BSTNode* temp = nullptr;
	if (root != nullptr)
	{
		if (v < root->m_val)
			DeleteValue(root->m_left, v);
		else if (v > root->m_val)
			DeleteValue(root->m_right, v);
		else if (root->m_left != nullptr && root->m_right != nullptr)
		{
			temp = root->m_left;
			while (temp->m_right != nullptr)
				temp = temp->m_right;
			root->m_val = temp->m_val;
			DeleteValue(root->m_left, root->m_val);
		}
		else
		{
			temp = root;
			if (root->m_right != nullptr)
				root = root->m_right;
			else
				root = root->m_left;
				delete(temp);
				temp = nullptr;
		}
		
	}
}

测试:

int main()
{
	int num[] = { 62,88,58,47,35,73,51,99,37,93 };
	int n = sizeof(num) / sizeof(num[0]);
	BSTree bt;
	for(int i=0;i<n;i++)
		bt.InsertValueST(num[i]);
	bt.Print();
	BSTNode* p = nullptr;
	p = bt.SearchValue(47);
	if (p == nullptr)cout << "没找到" << endl;
	else cout << "找到" << endl;
	p = bt.SearchValue(1999999);
	if (p == nullptr)cout << "没找到" << endl;
	else cout << "找到" << endl;
	cout << bt.GetMax()->m_val << " " << bt.GetMin()->m_val << endl;
	bt.DeleteValue(62);
	bt.Print();
}

 

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

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

相关文章

11、STM32H7 MPU Cache

篇前小问题 在使用stm32H750的FMC时&#xff0c;出现一些奇怪的问题&#xff0c;写A时序时时&#xff0c;总是写1次的代码了出现了写四次的时序&#xff0c;所以找了很久&#xff0c;才找到问题出在了MPU上&#xff0c;使用FMC时&#xff0c;必须开启MPU&#xff0c;不然会出现…

QML图形动画基础之

图形动画基础 颜色&#xff08;color&#xff09;渐变&#xff08;Gradient&#xff09;系统调色面板(SystemPalette) 图片边界动画&#xff08;BorderImage&#xff09;动态图片&#xff08;AnimatedImage&#xff09;缩放&#xff0c;旋转和平移变换Transform实现高级变换 颜…

CLion开发工具 | 01 - 认识外观界面

专栏介绍 一、创建/打开项目 二、外观和界面 1. 文件编辑区 CLion的自动提示功能如下&#xff1a; CLion的参数提示功能如下&#xff1a; CLion的形参名称显示功能&#xff1a; 2. 项目文件浏览区 3. 工具栏 3.1. 一键编译运行 CLion内置了MinGW&#xff0c;点击运行可以…

卷积神经网络推理特征图可视化查看,附录imagenet类别和编号对应查询表。通过观察法进行深度学习可解释研究

CNN模型虽然在图像处理上表现出非常良好的性能和准确性&#xff0c;但一直以来都被认为是一个黑盒模型&#xff0c;人们无法了解里面的工作机制。 针对这个问题&#xff0c;研究人员除了从理论层面去寻找解释外&#xff0c;也提出了一些可视化的方法直观地理解CNN的内部机理&am…

atl创建avtive

activex无窗口问题 控件在编码过程中要检查m_hWnd是否存在&#xff0c;不然vs可能会出现绘制错乱和崩溃 atl窗体通过CComControlBase的内部变量控制&#xff0c;窗体属性&#xff0c;包括onsize事件对应的m_bRecomposeOnResize变量控制窗体变化事件响应。 可插入的控件 授权…

Hbase基本操作

目录 HBASE 基本操作 hbase shell&#xff1a;进入hbase shell环境 status命令&#xff1a;查看集群状态 version&#xff1a;查看版本信息 create&#xff1a;创建表 drop 删除表 list&#xff1a;查看所有表 desc &#xff1a;查看表结构 exists &#xff1a;查看表…

分布式数据一致性解决方案推理过程

redis是一个极轻量级的进程&#xff0c;单机单线程单进程。 使用redis很容易实现分布式锁&#xff1a;setnx&#xff0c;同一个key&#xff0c;谁设置成功了&#xff0c;谁就抢到了锁&#xff0c;所以就产生了多锁问题。 假设客户端1抢到了锁&#xff0c;redis挂了&#xff0c…

Docker下载、安装

安装docker前&#xff0c;需要安装WSL Linux 内核、Hyper-V Hyper-V 首先确认系统是否安装&#xff1a;Hyper-V 如果没有则安装&#xff1a; pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findstr /i . h…

java中的泛型

1.2 泛型的引入 在Java中&#xff0c;我们在声明方法时&#xff0c;当在完成方法功能时如果有未知的数据需要参与&#xff0c;这些未知的数据需要在调用方法时才能确定&#xff0c;那么我们把这样的数据通过形参表示。在方法体中&#xff0c;用这个形参名来代表那个未知的数据…

如何在四维轻云地理空间数据管理云平台中搭建场景?

《四维轻云》是一款轻量化的地理空间数据管理云平台&#xff0c;支持地理空间数据的在线管理、编辑以及分享。平台有项目管理、数据上传、场景搭建、发布分享、素材库等功能模块&#xff0c;支持多用户在线协作管理&#xff0c;实现了轻量化、便捷化的空间数据应用。 目前&…

< 前端性能优化: 资源加载优化 >

文章目录 &#x1f449; 前言&#x1f449; 一、路由懒加载> 实现代码> 处理前后各文件大小情况 &#x1f449; 二、组件懒加载> 实现代码> 适用场景 &#x1f449; 三、骨架屏优化白屏时长&#x1f449; 四、JavaScript 的6种加载方式1. 正常模式2. async 模式3. …

云端上的结题报告——凌恩智能交付系统

做组学分析的小伙伴不难发现&#xff0c;在拿到测序分析结果后&#xff0c;经常会需要进行调整&#xff0c;比如&#xff1a;配色不符合自己审美、分组需要重新设置、重复性差需要剔除样本等&#xff0c;面对重新分析或改图的情况&#xff0c;自学生信费时费力&#xff0c;找公…

ClickHouse数据一致性

目录 1 准备测试表和数据2 手动OPTIMIZE(不推荐)3 通过 Group by 去重4 通过 FINAL 查询4.1 老版本测试4.2 新版本测试 1 准备测试表和数据 查询 CK 手册发现&#xff0c;即便对数据一致性支持最好的 Mergetree&#xff0c;也只是保证最终一致性&#xff1a; 我们在使用 Repl…

条码控件Aspose.BarCode入门教程(7):如何在Java 中的 GS1-128 条码生成器

Aspose.BarCode for .NET 是一个功能强大的API&#xff0c;可以从任意角度生成和识别多种图像类型的一维和二维条形码。开发人员可以轻松添加条形码生成和识别功能&#xff0c;以及在.NET应用程序中将生成的条形码导出为高质量的图像格式。 Aspose API支持流行文件格式处理&am…

C语言—深度剖析数据在内存中的存储

深度剖析数据在内存中的存储 数据类型介绍类型的基本归类整形在内存中的存储大小端介绍整形在内存中的存储的相关练习浮点型在内存中的存储浮点型在内存中的存储相关介绍 数据类型介绍 内置类型&#xff08;C语言本身就具有的类型&#xff09;&#xff1a; char //字符…

linux_时序竞态-pause函数-sigsuspend函数-异步I/O-可重入函数-不可重入函数

接上一篇&#xff1a;linux_信号捕捉-signal函数-sigaction函数-sigaction结构体 今天来分享时序竞态的知识&#xff0c;关于时序竞态的问题&#xff0c;肯定会和cpu有关&#xff0c;也会学习两个函数&#xff0c;pause函数&#xff0c;sigsuspend函数&#xff0c; 也会分享什么…

教你轻松申请Azure OpenAI

Azure OpenAI 和 OpenAI 官方提供的服务基本是一致的&#xff0c;但是目前前者还是处于预览版的状态&#xff0c;一些功能还没有完全开放。 优点&#xff1a; 不受地域限制&#xff0c;国内可以直接调用。可以自己上传训练数据进行训练&#xff08;据说很贵&#xff09;。Azu…

【原理图专题】Cadence如何导出智能PDF

原理图导出PDF只会使用打印?打印后没有书签还需要手动建立多页面的书签? 其实Cadence支持导出智能pdf,不仅能够在pdf上直接看到料件的各种参数,还可以直接点击连页符跳转到对应的页面和网络上,并且还能根据页面自动建立完整的书签,方便查找。 最终能生成如下所示的页面…

建筑负荷需求响应的介绍

可再生能源发展及电网用电平衡现状 近些年,我国城市建筑的电网供给和需求存在严重的不平衡问题,特别是当受建筑空调季节性负荷的影响时。一方面夏季及冬季电力负荷短缺,而另外一方面全年仍然存在着发电设备过剩、运行小时数不足等问题。以加州为例,夏季高峰用电中 50%左右…

一个对付小孩便秘的指南,让麻麻不再当催屎员

便秘在儿童中很常见。多达30%的儿童患有便秘。据估计&#xff0c;它占所有儿科医生的3%-5%。便秘通常包括排便困难或排便频率降低。正常排便的频率和特征在不同的儿童时期是不同的&#xff0c;因此没有单一的正常定义。●在足月新生儿中&#xff0c;第一次排便通常发生在出生后…