数据结构与算法分析实验12 实现二叉查找树

news2025/5/15 8:05:36

实现二叉查找树

  • 1、二叉查找树介绍
  • 2.上机要求
  • 3.上机环境
  • 4.程序清单(写明运行结果及结果分析)
    • 4.1 程序清单
      • 4.1.1 头文件 TreeMap.h 内容如下:
      • 4.1.2 实现文件 TreeMap.cpp 文件内容如下:
      • 4.1.3 源文件 main.cpp 文件内容如下:
    • 4.2 实现展效果示
    • 5.上机体会

1、二叉查找树介绍

二叉查找树(Binary Search Tree, BST)是一种特殊的二叉树,其中每个节点都包含一个键值,并且满足以下性质:

  • 左子树中的所有节点的键值小于当前节点的键值。
  • 右子树中的所有节点的键值大于当前节点的键值。
  • 左右子树也分别是二叉查找树。

二叉查找树的优缺点

  • 优点
    查找、插入和删除操作的平均时间复杂度为O(log n)。
    结构简单,易于实现。
  • 缺点
    在最坏情况下(如树退化为链表),时间复杂度会退化为O(n)。
    需要额外的平衡操作(如AVL树、红黑树)来保持树的平衡,避免性能退化。
  • 二叉查找树是计算机科学中一种基础且重要的数据结构,理解其原理和操作对于深入学习算法和数据结构具有重要意义。

2.上机要求

基于二叉排序树,实现插入键值对、按照关键字查询、删除记录等操作

3.上机环境

visual studio 2022
Windows11 家庭版 64位操作系统

4.程序清单(写明运行结果及结果分析)

4.1 程序清单

4.1.1 头文件 TreeMap.h 内容如下:

#pragma once
#include<iostream>
//基于二叉排序树,实现插入键值对、按照关键字查询、删除记录等操作
#define maxsize 100

using namespace std;
typedef  string Key;
typedef  string Val;

typedef struct TNode {					
	Key key;
	Val val;
	//struct TNode* parent;	
	struct TNode* lcd;		
	struct TNode* rcd;		
}Tnode, * pTnode;

void insert(pTnode& tree, Key key, Val val);	//函数插入
void TreeCreate(pTnode& tree);				//创建
void Min_Order_View(pTnode tree);			//由索引从小到大展示
void Max_Order_View(pTnode tree);		//由索引从大到小展示
void input(pTnode& tree);					//键盘插入
int gethigh(pTnode tree);					//得到这一层树的高度,可以通过它得到平衡因子
void deletee(pTnode& tree, Key key);		//删除
void search(pTnode tree, Key key);			//查找
int  getfactor(pTnode tree);				//得到平衡因子,尚且没有用到,方便拓展成平衡二叉树

4.1.2 实现文件 TreeMap.cpp 文件内容如下:

#include"TreeMap.h"

void insert(pTnode& tree,Key key,Val val){
	if (tree == nullptr) {
		tree = new Tnode;
		tree->val = val;
		tree->key = key;
		tree->lcd = nullptr;
		tree->rcd = nullptr;
		return;
	}

	if (key == tree->key) {
		cout << "键值已经存在"; return;
	}
	else if (key < tree->key) {
		insert(tree->lcd, key, val);
	}
	else {
		insert(tree->rcd, key, val);
	}
}
void TreeCreate(pTnode& tree) {
	cout << "开始输入键值对,键值对都为q时退出>>\n";
	while (1) {
		Key key;
		Val val;
		cout << "Key>>"; cin >> key;
		cout << "Val>>"; cin >> val;
		if ((key == "q" || key == "Q") && (val == "q" || val == "Q"))break;
		else {
			insert(tree, key, val);
		}
	}
	cout << "输入成功\n";
}
void Min_Order_View(pTnode tree){
	if (tree!=nullptr) {
		if (tree->lcd)Min_Order_View(tree->lcd);
		cout << tree->key << "\t" << tree->val << endl;
		if (tree->rcd)Min_Order_View(tree->rcd);
	}
	else return;
}
/**
 * 该函数用于按最大顺序遍历二叉树。
 * 遍历顺序为:右子树 -> 当前节点 -> 左子树。
 * @param tree 指向二叉树根节点的指针。
 */
void Max_Order_View(pTnode tree) {
	if (tree!=nullptr) {
		if (tree->rcd) Max_Order_View(tree->rcd);
		cout << tree->key << "\t" << tree->val << endl;
		if (tree->lcd) Max_Order_View(tree->lcd);
	}
	else return;
}
/**
 * 该函数用于向二叉树中插入一个新的节点。
 * 用户需要输入键值和对应的值,函数会将其插入到二叉树中。
 * @param tree 指向二叉树根节点的指针的引用。
 */
void input(pTnode& tree){
	Key key; cout << "input key>>"; cin >> key;
	Val val; cout << "input val>>"; cin >> val;
	insert(tree, key, val);
	cout << "finish!" << endl;
}
/**
 * 该函数用于计算二叉树的高度。
 * 通过递归计算左子树和右子树的高度,返回较大的高度加1。
 * @param tree 指向二叉树根节点的指针。
 * @return 返回二叉树的高度。
 */
int gethigh(pTnode tree) {
	int hl, hr;
	if (tree) {
		hl = gethigh(tree->lcd);
		hr = gethigh(tree->rcd);
		return hl > hr ? hl + 1 : hr + 1;
	}
	else return 1;
}
/*
deletee 函数用于从二叉搜索树中删除具有指定键值的节点。
该函数通过递归的方式查找并删除目标节点,同时处理了多种情况,
包括删除叶子节点、只有左子树或右子树的节点,以及同时拥有左右子树的节点。
*/
void deletee(pTnode& tree, Key key){
	if (tree == nullptr) {
		cout << "无对应键值" << endl;
		return;
	}
	if (key == tree->key) {
		if (tree->lcd == nullptr&&tree->rcd == nullptr) {//叶子
			delete tree;
			tree = nullptr;		//呜呜请加上这句,bug所在
			cout << "OK1" << endl;
			return;
		}
		else if (tree->lcd == nullptr && tree->rcd != nullptr) {//没有左子树
			pTnode del = tree;
			tree = tree->rcd;
			delete del;
			cout << "OK2" << endl;
			return;
		}
		else if (tree->lcd != nullptr && tree->rcd == nullptr) {//没有右子树
			pTnode del = tree;
			tree = tree->lcd;
			delete del;
			cout << "OK3" << endl;
			return;
		}
		else {//左右子树都有
			pTnode move = tree->rcd;
			while (move->lcd != nullptr)//拿到替死鬼
			{
				move = move->lcd;
			}
			tree->key = move->key;
			tree->val = move->val;
			delete move;
			cout << "OK4" << endl;
			return;
		}
	}
	else if (key < tree->key) {
		if (tree->lcd)deletee(tree->lcd, key);
	}
	else {
		if (tree->rcd)deletee(tree->rcd, key);
	}
}
/**
 * @brief 在二叉搜索树中查找指定键值的节点
 * 该函数递归地在二叉搜索树中查找与给定键值匹配的节点。如果找到匹配的节点,则输出该节点的键值和对应的值;如果未找到,则输出提示信息。
 */
void search(pTnode tree, Key key) {
	if (tree == nullptr) {
		cout << key << ":" << "不存在此键值" << endl;
		return;
	}
	if (tree->key == key) {
		cout << key << ":" << tree->val << endl;
		return;
	}
	else if (key < tree->key) {
		search(tree->lcd, key);
	}
	else {
		search(tree->rcd, key);
	}
}
int getfactor(pTnode tree){
	if (tree) return(gethigh(tree->lcd) - gethigh(tree->rcd));
	else return 0;
}

4.1.3 源文件 main.cpp 文件内容如下:

#include"TreeMap.h"
int main() {
	pTnode tree = nullptr;
	TreeCreate(tree);				//创建
	cout << "从小到大索引" << endl;	//从小到大输出
	Min_Order_View(tree);
	input(tree);					//增加操作
	insert(tree, "my", "我的");
	cout << "从大到小索引" << endl;	//从大到小输出
	Max_Order_View(tree);
	cout << "删除操作" << endl;		//删除操作
	deletee(tree, "my");
	Max_Order_View(tree);
	cout << "查询操作" << endl;		//查找操作
	search(tree, "hello");
	search(tree, "my");
	cout<<"\nget factor:"<<getfactor(tree);
	return 0;
}

4.2 实现展效果示

如左下图,输入部分:当全部是q时完成输入,可以看到,输入的索引是无序的。

在这里插入图片描述
如右上图,输出部分,按照关键字大小顺序从小到大,输出了键值对,提示我们插入一条信息。
如左下图我们输入hellow 你好w,由于代码中插入 my 我的 这个记录,再次展示的记录多了两条,同时这次采用从大到小的打印方法。
在这里插入图片描述
如右上图,代码中我们选择删除 my 关键字,提示OK1,表明我们删除了叶子节点,再次展示从大到小,不存在 my 节点,同时 search 操作对 hello 有效,对 my 无效。

5.上机体会

二叉查找树(Binary Search Tree,BST)是一种特殊类型的二叉树,它所有的根节点大于左子树的节点,小于右子树的节点。具有以下性质:
1、 如果左子树不为空,则左子树上的所有节点都小于根节点。
2、 如果右子树不为空,则右子树上的所有节点都大于根节点。
3、 左右子树也为搜索二叉树。
二叉查找树的常用操作有:插入、查找、删除、最大值、最小值等。
在二叉树的创建过程中,可以使用递归的方式。首先,将根节点的值设置为给定的值,然后递归地构建左子树和右子树。插入查找删除的理想时间复杂度为 O(log n),其中 n 是树的节点数。中序遍历输出二叉树则是很好的排序方法。通过实验,我们可以更加深入地理解二叉查找树的概念和性质,掌握二叉查找树的常见操作的实现方法。同时,我们也可以通过实验发现一些二叉查找树的应用场景,例如在数据库中的索引结构、文件系统中的目录结构等。需要注意的是,二叉查找树的性能高度依赖于树的平衡性。如果树的平衡性较差,可能会导致搜索效率降低。因此,在实际应用中,需要对二叉查找树进行适当的平衡调整,例如使用红黑树等自平衡二叉查找树。

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

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

相关文章

使用 Semantic Kernel 调用 Qwen-VL 多模态模型

使用 Semantic Kernel 调用 Qwen-VL 多模态模型 一、引言 随着人工智能技术的不断发展&#xff0c;多模态模型逐渐成为研究的热点。Qwen-VL 是阿里云推出的大规模视觉语言模型&#xff0c;支持图像、文本等多种输入形式&#xff0c;并能够进行图像描述、视觉问答等多种任务。…

(4)python开发经验

文章目录 1 使用ctypes库调用2 使用pybind11 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发 &#x1f448;&#x1f449;python开发 &#x1f448; 1 使用ctypes库调用 说明&#xff1a;ctypes是一个Python内置的库&#xff0c;可以提供C兼容的数据类型…

深度剖析 GpuGeek 实例:GpuGeek/Qwen3-32B 模型 API 调用实践与性能测试洞察

深度剖析 GpuGeek 实例&#xff1a;GpuGeek/Qwen3-32B 模型 API 调用实践与性能测试洞察 前言 GpuGeek专注于人工智能与高性能计算领域的云计算平台&#xff0c;致力于为开发者、科研机构及企业提供灵活、高效、低成本的GPU算力资源。平台通过整合全球分布式数据中心资源&#…

MindSpore框架学习项目-ResNet药物分类-数据增强

目录 1.数据增强 1.1设置运行环境 1.1.1数据预处理 数据预处理代码解析 1.1.2数据集划分 数据集划分代码说明 1.2数据增强 1.2.1创建带标签的可迭代对象 1.2.2数据预处理与格式化&#xff08;ms的data格式&#xff09; 从原始图像数据到 MindSpore 可训练 / 评估的数…

【MySQL】别名设置与使用

个人主页&#xff1a;Guiat 归属专栏&#xff1a;MySQL 文章目录 1. 别名基础概念2. 列别名设置2.1 基础语法2.2 特殊字符处理2.3 计算字段示例 3. 表别名应用3.1 基础表别名3.2 自连接场景 4. 高级别名技术4.1 子查询别名4.2 CTE别名 5. 别名执行规则5.1 作用域限制5.2 错误用…

【内网渗透】——S4u2扩展协议提权以及KDC欺骗提权

【内网渗透】——S4u2扩展协议提权以及KDC欺骗提权 文章目录 【内网渗透】——S4u2扩展协议提权以及KDC欺骗提权[toc]一&#xff1a;Kerberos 委派攻击原理之 S4U2利用1.1原理1.2两种扩展协议**S4U2Self (Service for User to Self)****S4U2Proxy (Service for User to Proxy)*…

Linux——CMake的快速入门上手和保姆级使用介绍、一键执行shell脚本

目录 一、前言 二、CMake简介 三、CMake与其他常见的构建、编译工具的联系 四、CMake入门 1、CMake的使用注意事项 2、基本的概念和术语 3、CMake常用的预定义变量 4、CMakeLists.txt文件的基本结构 五、上手实操 1、示例 ​编辑 2、一个正式的工程构建 2.1基本构…

如何高效集成MySQL数据到金蝶云星空

MySQL数据集成到金蝶云星空&#xff1a;SC采购入库-深圳天一-OK案例分享 在企业信息化建设中&#xff0c;数据的高效流转和准确对接是实现业务流程自动化的关键。本文将聚焦于一个具体的系统对接集成案例——“SC采购入库-深圳天一-OK”&#xff0c;详细探讨如何通过轻易云数据…

通过POI实现对word基于书签的内容替换、删除、插入

一、基本概念 POI&#xff1a;即Apache POI&#xff0c; 它是一个开源的 Java 库&#xff0c;主要用于读取 Microsoft Office 文档&#xff08;Word、Excel、PowerPoint 等&#xff09;&#xff0c;修改 或 生成 Office 文档内容&#xff0c;保存 为对应的二进制或 XML 格式&a…

FlashInfer - 测试的GPU H100 SXM、A100 PCIe、RTX 6000 Ada、RTX 4090

FlashInfer - 测试的GPU H100 SXM、A100 PCIe、RTX 6000 Ada、RTX 4090 flyfish GPU 技术参数术语 1. Memory bandwidth (GB/s) 中文&#xff1a;显存带宽&#xff08;单位&#xff1a;GB/秒&#xff09; 定义&#xff1a;显存&#xff08;GPU 内存&#xff09;与 GPU 核心…

MongoDB从入门到实战之Windows快速安装MongoDB

前言 本章节的主要内容是在 Windows 系统下快速安装 MongoDB 并使用 Navicat 工具快速连接。 MongoDB从入门到实战之MongoDB简介 MongoDB从入门到实战之MongoDB快速入门 MongoDB从入门到实战之Docker快速安装MongoDB 下载 MongoDB 安装包 打开 MongoDB 官网下载页面&…

Excelize 开源基础库发布 2.9.1 版本更新

Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库&#xff0c;基于 ECMA-376&#xff0c;ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Excel、WPS、OpenOffice 等办公软件创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式&#xf…

Profibus DP主站转Modbus RTU/TCP网关接艾默生流量计与上位机通讯

Profibus DP主站转Modbus RTU/TCP网关接艾默生流量计与上位机通讯 艾默生流量计与Profibus DP主站转Modbus RTU/TCP网关的通讯&#xff0c;是现代工业自动化中的一个关键环节。为了实现这一过程&#xff0c;我们需要了解一些基础概念和具体操作方法。 在工业自动化系统中&…

Linux proc文件系统 内存影射

文章目录 常见的内存分配函数/proc/pid/ 目录解析 用户进程的内存空间分配算法mmap 分配大内存可能不在堆中换为 malloc 现象相同 常见的内存分配函数 malloc / calloc / realloc&#xff08;来自 C 标准库&#xff09; void *malloc(size_t size)&#xff1a;分配 size 字节…

五、Hadoop集群部署:从零搭建三节点Hadoop环境(保姆级教程)

作者&#xff1a;IvanCodes 日期&#xff1a;2025年5月7日 专栏&#xff1a;Hadoop教程 前言&#xff1a; 想玩转大数据&#xff0c;Hadoop集群是绕不开的一道坎。很多小伙伴一看到集群部署就头大&#xff0c;各种配置、各种坑。别慌&#xff01;这篇教程就是你的“救生圈”。 …

电流检测放大器的优质选择XBLW-INA180/INA181

前言&#xff1a; 在当前复杂的国际贸易环境下&#xff0c;关税的增加使得电子元器件的采购成本不断攀升&#xff0c;电子制造企业面临着巨大的成本压力。为了有效应对这一挑战&#xff0c;实现国产化替代已成为众多企业降低生产成本、保障供应链稳定的关键战略。对此芯伯乐推出…

# 深度剖析LLM的“大脑”:单层Transformer的思考模式探索

简单说一下哈 —— 咱们打算训练一个单层 Transformer 加上稀疏自编码器的小型百万参数大型语言模型&#xff08;LLM&#xff09;&#xff0c;然后去调试它的思考过程&#xff0c;看看这个 LLM 的思考和人类思考到底有多像。 LLMs 是怎么思考的呢&#xff1f; 开源 LLM 出现之后…

【C++】类与对象【下】

文章目录 再谈构造函数构造函数的赋值构造函数体赋值&#xff1a;初始化列表explicit关键字 static成员概念特性 C11中成员初始化的新玩法友元友元类 内部类概念 再谈构造函数 构造函数的赋值 构造函数体赋值&#xff1a; 在创建对象时&#xff0c;编译器会通过调用构造函数…

无人机避障——如何利用MinumSnap进行对速度、加速度进行优化的轨迹生成(附C++python代码)

&#x1f525;轨迹规划领域的 “YYDS”——minimum snap&#xff01;作为基于优化的二次规划经典&#xff0c;它是无人机、自动驾驶轨迹规划论文必引的 “开山之作”。从优化目标函数到变量曲线表达&#xff0c;各路大神疯狂 “魔改”&#xff0c;衍生出无数创新方案。 &#…

Llama:开源的急先锋

Llama:开源的急先锋 Llama1&#xff1a;开放、高效的基础语言模型 Llama1使用了完全开源的数据&#xff0c;性能媲美GPT-3&#xff0c;可以在社区研究开源使用&#xff0c;只是不能商用。 Llama1提出的Scaling Law 业内普遍认为如果要达到同一个性能指标&#xff0c;训练更…