二叉搜索树的增删查

2023-05-16

     今天把搜索二叉树的思路又理了一遍,把代码又从头到尾敲了一遍,各位看客就不要在意代码粗糙和内存溢出了,主要把插入和删除的过程理了一遍,其中比较复杂的地方就是搜索二叉树的删除,涉及了很多次的指针重新指向,比较容易晕。另外,对于二叉树,在上溯的时候要特别注意根节点这个特殊的临界状态(大部分情况把根节点的父结点指向空,也可以设一个head结点,使root和head的父结点相互指向)。最后注意null结点不能取左右孩子和父结点,这也是一个容易使程序崩的情况。代码如下:

//二叉搜索树的插入和删除
struct SerachTree
{
	int data;
	SerachTree *left_child;
	SerachTree *right_child;
	SerachTree *parent_node;
};

class Serach_Tree
{
public:
	Serach_Tree()
	{
		root=NULL;
	}
	//插入
	SerachTree* insert(int number)
	{
		if(root==NULL)
		{
			root=new SerachTree;
			root->data=number;
			root->left_child=NULL;
			root->right_child=NULL;
			root->parent_node=NULL;
		}
		else
		{
			SerachTree *tem_root=root;
			SerachTree *tem=NULL;
			while(tem_root!=NULL)
			{
				tem=tem_root;
				if(number<tem_root->data)
					tem_root=tem_root->left_child;
				else
					tem_root=tem_root->right_child;
			}
			SerachTree *child=new SerachTree;
			child->data=number;
			child->left_child=NULL;
			child->right_child=NULL;
			if(number<tem->data)
			{
				tem->left_child=child;
				child->parent_node=tem;
			}
			else
			{
				tem->right_child=child;
				child->parent_node=tem;
			}
		}
		return root;
	}
	//最小值
	int minimum(SerachTree *root)
	{
		if(root==NULL)
			return NULL;
		while(root->left_child!=NULL)
			root=root->left_child;
		return root->data;
	}
	//最大值
	int maximum(SerachTree *root)
	{
		if(root==NULL)
			return NULL;
		while(root->right_child!=NULL)
			root=root->right_child;
		return root->data;
	}
	//查找指定的值,找到返回该值,找不到就返回空
	int search(SerachTree *root,int num)
	{
		if(root==NULL)
			return NULL;
		if(root->data==num)
		{
			return num;
		}
		else
		{
			if(num<root->data)
				search(root->left_child,num);
			else
				search(root->right_child,num);
		}
		return num;
	}
	//找一个结点的前驱结点
	int front_node(int num)
	{
		if(search(root,num)==NULL)
		{
			cout<<"no that node!"<<endl;
			return NULL;
		}
		else
		{
			SerachTree *tem=root;
			//肯定能找到
			while(true)
			{
				if(tem->data>num)
					tem=tem->left_child;
				else if(tem->data<num)
					tem=tem->right_child;
				else
					break;
			}
			//找前驱结点
			if(tem->left_child!=NULL)
				return maximum(tem->left_child);
			SerachTree *tem_parent=tem->parent_node;
			while(tem_parent!=NULL&&tem==tem_parent->left_child)
			{
				tem=tem_parent;
				tem_parent=tem_parent->parent_node;
			}
			if(tem_parent==NULL)
				return NULL;
			else
				return tem_parent->data;
		}
	}
	//找后继结点
	int back_node(int num)
	{
		if(search(root,num)==NULL)
		{
			cout<<"no node"<<endl;
			return NULL;
		}
		else
		{
			SerachTree *tem=root;
			//肯定能找到
			while(true)
			{
				if(tem->data>num)
					tem=tem->left_child;
				else if(tem->data<num)
					tem=tem->right_child;
				else
					break;
			}
			if(tem->right_child!=NULL)
				return minimum(tem->right_child);
			SerachTree *tem_root=tem->parent_node;
			while(tem_root!=NULL&&tem==tem_root->right_child)
			{
				tem=tem_root;
				tem_root=tem_root->parent_node;
			}
			if(tem_root==NULL)
				return NULL;
			else
				return tem_root->data;
		}
	}
	//删除结点
	void delete_node(int num)
	{
		if(search(root,num)==NULL)
		{
			cout<<"delete error!"<<endl;
			return;
		}
		else
		{
			SerachTree *tem_root=root;
			while(true)
			{
				if(tem_root->data<num)
				{
					tem_root=tem_root->right_child;
				}
				else if(tem_root->data>num)
				{
					tem_root=tem_root->left_child;
				}
				else
					break;
			}
			//tem是待删除的结点
			if(tem_root->left_child==NULL) //没有左孩子,直接右孩子顶上
				_delete_node(tem_root,tem_root->right_child);

			else if(tem_root->right_child==NULL) //没有右孩子,直接左孩子顶上
				_delete_node(tem_root,tem_root->left_child);
			else  //左右孩子不为空
			{
				//先找到右子数最小的结点
				SerachTree *tem=tem_root->right_child;
				while(tem->left_child!=NULL)
				{
					tem=tem->left_child;
				}
				if(tem->parent_node!=tem_root)  //找到的点不是与待删除的点直接相连
				{
					_delete_node(tem,tem->right_child);
					tem->right_child=tem_root->right_child;
					tem->right_child->parent_node=tem;
				}
				_delete_node(tem_root,tem);
				tem->left_child=tem_root->left_child;
				tem->left_child->parent_node=tem;
			}
			cout<<"delete success"<<endl;
		}
	}
private:
	void _delete_node(SerachTree *root1,SerachTree *root2)
	{
		if(root1->parent_node==NULL)  //当前结点是根节点
		{
			root=root2;
		}
		else if(root1==root1->parent_node->left_child) //当前结点是父结点的左孩子
		{
			root1->parent_node->left_child=root2;
		}
		else if(root1=root1->parent_node->right_child)
		{
			root1->parent_node->right_child=root2;
		}
		if(root2!=NULL)
			root2->parent_node=root1->parent_node;
	}
public:
	SerachTree *root;
};

int main()
{
	Serach_Tree s;
	int choose;
	while(true)
	{
		cout<<"1:插入  2:max  3:min  4:serach  5:delete  0:exit"<<endl;
		cin>>choose;
		if(choose==1)
		{
			int num;
			cout<<"insert num:";
			cin>>num;
			s.insert(num);
		}
		if(choose==2)
		{
			if(s.maximum(s.root)!=NULL)
				cout<<s.maximum(s.root)<<endl;
			else
				cout<<"no node"<<endl;
		}
		if(choose==3)
		{
			if(s.minimum(s.root)!=NULL)
				cout<<s.minimum(s.root)<<endl;
			else
				cout<<"no node"<<endl;
		}
		if(choose==4)
		{
			int num=0;
			cout<<"search num:";
			cin>>num;
			if(s.search(s.root,num)!=NULL)
				cout<<s.search(s.root,num)<<endl;
			else
				cout<<"no node"<<endl;
		}
		if(choose==5)
		{
			int num=0;
			cout<<"delete num:";
			cin>>num;
			s.delete_node(num);
		}
		if(choose==0)
			break;
	}
	return 0;
}
 
    测试基本没有问题,但不排除特殊案例没考虑到的情况。欢迎指正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉搜索树的增删查 的相关文章

  • JAVA操作Kafka

    一 环境说明 1 电脑或你的服务器需要安装zookeeper和kafka 可以参考我的这篇博客 xff1a 请点击这里 xff01 2 项目中需要下面的依赖 xff1a span class token tag span class tok
  • Gradle使用本地maven仓库

    一 基本配置 在repositories下添加mavenLocal 方法 plugins span class token punctuation span id span class token string 39 java 39 spa
  • Docker容器编排

    一 简介和下载安装 1 简介 docker compose是Docker官方的开源项目 xff0c 可以管理多个docker容器组成的一个应用 你需要定义一个YAML格式的配置文件docker compose yaml xff0c 写好多容
  • 若依微服务(ruoyi-cloud)保姆版容器编排运行

    一 简介 项目gitee地址 xff1a https gitee com y project RuoYi Cloud 由于该项目运行有很多坑 xff0c 大家可以在git克隆拷贝到本地后 xff0c 执行下面的命令使master版本回退到本
  • 深入学习Tomcat----自己动手写服务器(附服务器源码)

    相信大多 Web 开发者对 Tomcat 是非常熟悉的 xff0c 众所周知 Tomcat 是一款非常好用的开源 Servlet 容器 xff0c 您一定对这个最流行的 Servlet 容器充满好奇 xff0c 虽然它并不像一个黑盒子那样让
  • Docker图形界面

    一 Portainer Portainer是一款轻量级的应用 xff0c 它提供了图形化界面 xff0c 用于方便地管理Docker环境 xff0c 包括单机环境和集群环境 官网 xff1a https www portainer io 运
  • Docker网络

    一 简介 从其架构和运行流程来看 xff0c Docker是一个C S模式的架构 xff0c 后端是一个松耦合架构 xff0c 众多模块各司其职 docker运行的基本流程为 xff1a 1 用户是使用Docker Client和Docke
  • NOKOV Seeker2.2动作捕捉软件与ROS的通信

    一 动捕软件安装与数据准备 1 在操作系统为Windows系统 xff0c 且位数为64位的电脑上 xff0c 以鼠标右键点击 以管理员身份运行 的方式 xff0c 运行 Seeker2 2 Tracker setup exe 文件 xff
  • NOKOV度量动捕软件教程(1):软件安装与设置

    一 软件安装 1 在操作系统为 64 位的 Windows 系统上 xff0c 关闭防火墙退出杀毒软件 xff08 360 电脑管家等 xff09 xff0c 以鼠标右键点击 以管理员身份运行 的方式 xff0c 运行 XINGYING 1
  • Pixhawk+PX4+NOKOV+C++SDK动捕飞控方案

    一 PX4配置 1 参数设置 xff0c 保存重启后生效 EKF2 AID MASK 61 24 EKF2 HGT MODE 61 2 二 动捕软件设置 1 配置参考 xff08 1 xff09 mocap nokov ROS Wiki 三
  • Pixhawk+PX4+NOKOV+VRPN动捕飞控方案

    一 PX4 配置 1 参数设置 xff0c 保存重启后生效 EKF2 AID MASK 61 24 EKF2 HGT MODE 61 2 二 VRPN配置 1 Nokov 动捕软件正确配置参数并启动 VRPN 2 使用 vrpn clien
  • JS-DOM— —节点操作

    五 节点操作 5 1 节点操作的作用 获取元素通常使用两种方式 1 利用DOM提供的方法获取元素 document getElementByld document getElementsByTagName0 document querySe
  • 立创EDA专业版入门经验分享(1)——对标AD的快捷操作

    作者团队在近期从Alitum Designer转战到立创EDA专业版 在习惯AD的工作方式后 xff0c 转到立创EDA专业版后磨合了很长一段时间 现将原来AD中的功能对应到立创EDA中的高级功能像大家分享 欢迎大家一起交流学习 本帖将作为
  • c语言中字符数组的理解

    数组的理解参考该文 对于字符数组 xff0c 当最后一个元素是 0 xff0c 则这个字符数组是一个字符串 xff1b 字符串可以通过首地址来打印输出 1 对于一维数组 int pack 3 61 1 2 3 printf 34 d 34
  • 如何减小与“大牛”的差距

    为什么同样的时间有的人可以漂亮的完成工作 xff0c 而有些人废了很大的力气也没有完成 xff1f 前者我们常常称之为 大牛 xff0c 后者我们常常叫他们 菜鸟 当然 大牛 都是相对而言的 xff0c 大牛 也不可能方方面面都非常厉害 x
  • 利用字符串的最后一个字符为‘\0‘的特性操作字符串

    利用末尾为 0 特性 xff0c 求字符串长度 xff0c 实现strlen int len 61 0 char str 61 34 hello 34 char p 61 str while p len 43 43 计算字符串的长度 p 4
  • 信号量sem_init,sem_wait,sem_post

    本篇文章是信号量的简单入门 xff0c 主要学习关于信号量四个函数的使用 文章综合整理了两篇文章 xff1a http blog csdn net qyz og article details 47189219 http blog csdn
  • readdir函数

    readdir会不断读取目中的文件及目录 xff0c 但不会读子目录中的文件 include lt sys types h gt include lt dirent h gt include lt stdio h gt include lt
  • fwrite写文件是乱码

    fwrite写的二进制文件 xff0c 所以我们打开所写的文件是乱码 xff0c 但数据是正确的 xff0c 我们通过fread函数按照原来的数据格式读取即可 可以参考该文 include lt sys types h gt include

随机推荐

  • 经典面试题 动态链接库与静态链接库的区别

    经典面试题 动态链接库与静态链接库的区别 面试轻松学习 xff0c offer快点拿 文章目录 经典面试题 动态链接库与静态链接库的区别一 动态链接库是什么 xff1f 二 静态链接库是什么 xff1f 三 区别1 静态链接库速度快 xff
  • Docker占用的磁盘空间清理

    Docker占用的磁盘空间清理 1 docker system命令 在谁用光了磁盘 xff1f Docker System命令详解中 xff0c 我们详细介绍了docker system命令 它可以用于管理磁盘空间 docker syste
  • 卡尔曼滤波算法详细推导(全网最详细的推导过程)

    本文是来源于B站Dr CAN的视频的学习笔记 xff0c 有需要详细了解的 xff0c 可以到B站看相关视频DR CAN的个人空间 1 递归算法 例 xff1a 假设测一段距离 xff0c 第一次测 z 1 z 1 z 1 61 50 1m
  • ADC采样滤波算法利用卡尔曼滤波算法详解

    1 ADC采样模型 xff08 本文为笔者早期所写 xff0c 当时对卡尔曼滤波器理解尚未透彻 xff0c 如今回顾 xff0c 该模型还有所缺陷 xff0c 推荐读者看卡尔曼的推导过程或者B站大佬Dr CAN的空间 xff09 假设ADC
  • 微信支付趟过的坑

    这段时间在做微信支付开发 xff0c 在公司的公众号审批下来后 xff0c 我这边的测试用例也已经开发完毕 xff0c 于是拿着具体的数据来调试了 xff0c 大段大段的代码就不贴了 xff0c demo里有 xff0c 这里就说说调试过程
  • java底层原理

    Java运行三部曲 xff1a 编写 xff0c 编译 xff0c 运行 编写 xff1a 硬件编写代码 xff0c 就是我们写代码 编译 xff1a javac将文件编译成一个或多个 class文件 编译中间的过程主要是类型和格式的检查
  • 信息化时代下的我们----弄潮儿

    读完 信息化与信息管理实践之道 的部分章节想起了 第三次浪潮 中的一段话 xff0c 摘录如下 人类到现在已经经历了两次巨大的变革浪潮 这两次浪潮都淹没了早先的文明和文化 xff0c 都是以前人所不能想象的生活方式 xff0c 替代了原来的
  • ORB-SLAM稠密点云地图构建(黑白+彩色)+ pcd文件以八叉树形式表示

    pcl1 8 1 VTK 7 1 1 版本一定要对好 xff0c 如果安装了不符的版本如我之前安的pcl1 1 3和VTK8 2 一定要卸载干净不然会一直报错 xff0c 不同版本的pcl和vtk是无法共存的 xff0c 并且光把包删除是不
  • 一步步学习多线程(一) 重要概念

    几个重要的概念 1 同步 xff08 synchronous xff09 和 异步 xff08 asynchronous xff09 2 并发 xff08 Concurrency xff09 和 并行 xff08 Parallelism x
  • MAVLink功能开发,移植教程。

    MAVLink功能开发 本文由 智御电子 提供 xff0c 同时提供视频移植教程 xff0c 以便电子爱好者交流学习 1 MAVLink简介 MAVLink是一种针对微型飞行器 xff0c 推出的轻量化 xff0c 仅由头文件信息编码而成的
  • workerman问题总结大全及解决方案

    workerman无法正常访问 问题描述 xff1a 在阿里云ECS上部署了workerman的应用 xff08 ECS是专有网络 xff09 xff0c 在ECS安全组里已经允许workerman需要的全部端口 xff0c 但是外网一直不
  • Eclipse Android开发遇到:"The type org.apache.http.HttpResponse cannot be resolved."问题的解决办法

    今天在做手机卫士的项目中 xff0c 在联网下载的功能模块中遇到The type org apache http HttpResponse cannot be resolved It is indirectly referenced fro
  • UG创建图纸明细表失败的情况

    今天进行UG二次开发的时候 xff0c 由于要在图纸中自动加入零件明细表 xff0c 但是当我在图纸中插入明细表的时候UG会弹出错误对话框 xff1a 当打开UGII UPDATE ALL ID SYMBOLS WITH PLIST变量时
  • 字符串末尾自动加上'\0'的情况

    之前一直都有一个问题困扰着我 xff0c 就是我们知道C风格的字符串在用strlen求长度时只会遇到 39 0 39 结束 xff0c 如果一个字符数组全部填满了 xff0c 而在末尾没有加上 39 0 39 就会出现结果不定的现象 xff
  • c++类成员变量的初始化顺序以及特殊成员的初始化方法规则

    说到类的成员变量的初始化顺序 xff0c 对于初学者很多容易混淆其顺序 xff0c 以为简单的按初始表来初始化 xff0c 其实不然 xff0c 现在我来详细讲解下类的初始化顺序 xff1a 首先由简单开始 xff1a class peop
  • deque 迭代器失效的问题详解

    今天在看STL源码的时候 xff0c 无意写了如下的代码 xff0c 发现程序崩溃了 xff1a lt span style 61 34 font size 14px 34 gt deque lt int gt iterator iter
  • Python中__init__.py文件的作用

    在创建python包的过程中 xff0c IDE都会在包根目录下创建一个 init py文件 xff0c 该Python文件默认是空的 目录结构如下 xff1a Pycharm下的package树结构 xff1a 在Finder中的目录结构
  • 使用Ajax以及CSS+DIV高仿谷歌搜索(附源码下载)

    在使用 Google 搜索或者是 Baidu 搜索的时候 xff0c 在输入搜索关键字的同时 xff0c 会自动弹出匹配的其他关键字的提示 xff0c 全心全意为人民服务的精神在这里崭露无遗 这种利用 Ajax 技术实现输入提示和自动完成的
  • 导致索引失效的可能情况

    如下是可能导致索引失效的情况 xff1a 1 xff0e 隐式转换导致索引失效 这一点应当引起重视 也是开发中经常会犯的错误 由于表的字段tu mdn定义为varchar2 20 但在查询时把该字段作为number类型以where条件传给O
  • 二叉搜索树的增删查

    今天把搜索二叉树的思路又理了一遍 xff0c 把代码又从头到尾敲了一遍 xff0c 各位看客就不要在意代码粗糙和内存溢出了 xff0c 主要把插入和删除的过程理了一遍 xff0c 其中比较复杂的地方就是搜索二叉树的删除 xff0c 涉及了很