数据结构与算法-二叉搜索树红黑树

news2025/1/15 17:47:52

一:二叉搜索树

大家来看以下几个结构:下图中的 二叉搜索树又叫二叉查找树,二叉排序树

它具有以下特点:

        1.如果它的左子树不为空,则左子树上结点的值都小于根结点。

        2.如果它的右子树不为空,则右子树上结点的值都大于根结点。

        3.子树同样也要遵循以上两点

为什么又叫做二叉排序树呢?

        二叉树的遍历方式:前 中 后 层次(Mysql)

        只要一颗树是二叉搜索树,那么它的中序遍历一定是有序的

        左根(输出)右 看右边的这颗二叉树,它的中序遍历为:左根右 左 根(输出) 右:0 3 4 5 6 8

         就是比较像二叉查找算法:猜数字,0~100出一个数,让你猜。每次会告诉你猜的结果是大了还是小了。 50 大了-> 51~100 小了 0~50每次一猜就可以排除一半的空间.归并排序,logn;有序的序列

        二:二叉搜索树的增删改查

        二叉搜索插入 5 3 6 0 4 8

        插入的时候每次都是和根结点比较。一直要找到它应该插入的位置。 肯定会插在叶子结点。

        那么其实大家可以看到 插入其实就是查找。

        增改查: 简单,主要是删除

        删除 是要分三种情况 

                1.要删除的结点是叶子结点 O(1)

                2.要删除的结点只有一个子树(左或者右)O(1)

                3.要删除的结点有两颗子树:找后继结点,而且后继结点的左子树一定为空。

        说明:这里的后继结点不是要删除的右边第一个结点,而是比它大的第一个结点,否则就不符合二叉搜索树的规则,无法排序,当这个后继结点只有一个子结点的时候就相当于删除的第二种情况。所以就引入了红黑树!

        性能:

                查找 logn

                插入:nlogn 有n个数要插入,每一个都要先查找到它的位置 就是logn 合起来就是nlogn,插入单个肯定是logn

       三:二叉树的应用

        二叉搜索树有哪些应用呢?

                O(n) for(int i = 0 ; i < n ; i++){} 像下图这个也是二叉树,只不过插入的是有序数列,所以为了防止这种现象,就出现了平衡二叉树,在中间隔开。弊端退化成链表了 既然是搜索树,那么肯定就是用在了查找上。 我们来分析它的查找时间复杂度: 看右边两颗二叉搜索树: 他们的性能: 查找时间复杂度其实就是树的深度 O(n)表示时间复杂度:查找N次。循环了N遍 为什么(退化了)?怎么解决呢? 不要变成一个链条一样

        AVL树(绝对平衡树): 红黑树和平衡二叉树:AVL属于实验室状态的,红黑树才是我们项目中用的。        

        3.1 二叉代码

package tree;

public class BinarySeachTree {
	
	private int color = 0;		//0表示黑,1表示红
	int data;
	BinarySeachTree left;
	BinarySeachTree right;
	
	BinarySeachTree parent;
	
	public BinarySeachTree(int data) {
		this.data = data;
		this.left = null;
		this.parent = null;
		this.color = 1;
		this.right = null;
		//parent.parent	;爷爷
		//parent.parent.left 左边的叔叔
		//parent.left 兄弟姐妹
	}
	//插入的时候每次都是和根结点比较。一直要找到它应该插入的位置。
	//肯定会插在叶子结点。那么其实大家可以看到 插入其实就是查找。 默认root不会为空

	public void insert(BinarySeachTree root,int data) {
		//if(root == null) {}
		if(root.data < data) {	//根节点小 我们要放到右边
			if(root.right == null) {
				root.right = new BinarySeachTree(data);
			}else {
				insert(root.right, data);
			}
		}else {
			if(root.left == null) {
				root.left = new BinarySeachTree(data);
			}else {
				insert(root.left, data);
			}
		}
	}
	
	public void find(BinarySeachTree root,int data) {
		if(root != null) {
			if(root.data < data) {
				find(root.right, data);
			}else if(root.data > data) {
				find(root.left, data);
			}else {
				System.out.println("找到了");
				System.out.println(root.data);
				return ;
			}
		}
	}
	public void pre() {	
		
	}
	public void post() {	
		
	}
	public void in(BinarySeachTree root) {		//中序遍历
		if(root != null) {
			in(root.left);
			System.out.print(root.data + " ");
			in(root.right);
		}
	}
	
	public static void main(String[] args) {
		//快速排序,归并排序,二叉树排序
		int data[] = {0,5,9,1,2,3,10};
		BinarySeachTree root = new BinarySeachTree(data[0]);	//第一个点作为跟结点
		for(int i = 1 ; i < data.length ; i ++) {
			root.insert(root, data[i]);
		}
		System.out.println("中序遍历:");
		root.in(root);
	}
}

        四:引入红黑树(性质,左旋,右旋

        通过上面两个图我们发现,二叉树的结构就决定了其搜索的性能,那么我们应该怎么优化呢?

        因此就有了AVL树和红黑树

        AVL树:平衡二叉树,它的左右子树高度之差不超过1 这样确实可以避免一条直线型的结构,但还不是我们最理想的

        可以认为是理想状态,实验室。红黑树

        为什么呢? 通过性能综合考虑选用:

        红黑树的性质(重点):

                1.每个结点不是红色就是黑色

                2.不可能有连在一起的红色结点(黑色的就可以),每个叶子节点都是黑色的空节点(NIL),也就是说,叶子节点不存储数据

                3.根结点都是黑色 root 4.每个节点,从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点;

        4.2 红黑树的三种变换

                1.改变颜色:最简单  红变黑 黑变红

                2.左旋:针对于点旋,但是点上面的子树也要跟着转。指针

                3.右旋:

        那么我们又该如何选择以上三种方式呢?

        4.3 插入规则

插入的时候旋转和颜色变换规则:

        1.变颜色的情况:当前结点的父亲是红色,且它的祖父结点的另一个子结点 也是红色。(叔叔结点): (1)把父节点设为黑色 (2)把叔叔也设为黑色 (3)把祖父也就是父亲的父亲设为红色(爷爷) (4)把指针定义到祖父结点(爷爷)设为当前要操作的.

        2.左旋:当前父结点是红色,叔叔是黑色的时候,且当前的结点是右子树。左旋 以父结点作为左旋。指针变换到父亲结点

        3.右旋:当前父结点是红色,叔叔是黑色的时候,且当前的结点是左子树。右旋 (1)把父结点变为黑色 (2)把祖父结点变为红色 (爷爷) (3)以祖父结点旋转(爷爷)

红黑树的删除: 红黑树的删除讲实话是最难的,这里我不作必须掌握的要求,但是你必须要掌握二叉搜索的删除原理。因为,即便你将左右旋背得滚瓜烂熟,我保证你过不几天就忘光了。学习红黑树的代码实现,对于你平时做项目开发没有太大帮助。 对于大部分人来说,这辈子你可能都不会亲手写红黑树。而且,它对于算法面试也几乎没什么用,一般情况下,正常的人也不会要你手写红黑树,最多只会问你一下原理,但是二叉搜索树就是必须要掌握的了,这个我在面试中就可能会要你写伪代码。

红黑树的性能分析 插入 近似:nlogn 查找 logn 删除:近似logn

红黑树的应用: 1.HashMap 2.TreeMap 3.Windows底层:查找 4.Linux进程调度,nginx等

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

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

相关文章

动手学深度学习——Windows下的环境安装流程(一步一步安装,图文并配)

目录 环境安装官网步骤图文版安装Miniconda下载包含本书全部代码的压缩包使用conda创建虚拟&#xff08;运行&#xff09;环境使用conda创建虚拟环境并安装本书需要的软件激活之前创建的环境打开Jupyter记事本 环境安装 文章参考来源&#xff1a;http://t.csdn.cn/tu8V8 官网…

编程初学者指南(2023版):零基础小白如何学习编程-两万字详述

文章目录 1.写在前面1.1 为什么有这份指南1.2 指南里有什么1.3 关于软件协会1.4 面对人生&#x1f340; 对工作&#xff1a;越努力越幸运&#x1f340; 对感情&#xff1a;爱得厚重开阔&#x1f340; 对他人&#xff1a;保持尊重、友好、真诚和谦逊&#x1f340; 对生活&#x…

【论文解读】元学习:MAML

一、简介 元学习的目标是在各种学习任务上训练模型&#xff0c;这样它就可以只使用少量的训练样本来解决新任务。 论文所提出的算法训练获取较优模型的参数&#xff0c;使其易于微调&#xff0c;从而实现快速自适应。该算法与任何用梯度下降训练的模型兼容&#xff0c;适用于…

群辉 Synology NAS Docker 安装 RustDesk-server 自建服务器只要一个容器

from https://blog.zhjh.top/archives/M8nBI5tjcxQe31DhiXqxy 简介 之前按照网上的教程&#xff0c;rustdesk-server 需要安装两个容器&#xff0c;最近想升级下版本&#xff0c;发现有一个新镜像 rustdesk-server-s6 可以只安装一个容器。 The S6-overlay acts as a supervi…

【Proteus仿真】【STM32单片机】便携式血糖仪

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 系统运行后&#xff0c;LCD1602显示开机界面信息&#xff0c;当按下K1键开始测量&#xff0c;步进电机运行启动针头采血&#xff0c;然后检测血糖值显示在屏幕上&#xff1b;如果血糖高于上限&#xff0c…

Upload-labs十六和十七关

目录 第十六关第十七关 第十六关 直接上传php文件判断限制方式&#xff1a; 同第十五关白名单限制 第十六关源码&#xff1a; 代码逻辑判断了后缀名、content-type&#xff0c;以及利用imagecreatefromgif判断是否为gif图片&#xff0c;最后再做了一次二次渲染 第71行检测…

计算机网络第四章——网络层(中)

提示&#xff1a;待到山花烂漫时&#xff0c;她在丛中笑。 文章目录 需要加头加尾&#xff0c;其中头部最重要的就是加了IP地址和MAC地址&#xff08;也就是逻辑地址和物理地址&#xff09;集线器物理层设备&#xff0c;交换机是物理链路层的设备&#xff0c;如上图路由器左边就…

Vue使用ts的枚举类型

vue项目中要使用ts的枚举类型需要为script标签的lang属性添加ts属性值 <script lang"ts" setup></script > 首先要声明一下&#xff08;我这里是声明了一个名称一个颜色&#xff09;&#xff1a; 接下来是页面中的标签使用&#xff08;用的是element表格…

Linux系统编程--IO系统调用

文章目录 一、I/O系统调用1.open() 打开文件1.1 所需基础知识1.2. open() 详解1.3 示例代码 2.read() 读取文件2.1.基础知识2.2.read() 详解2.3. 读入所有字节 3.write() 写文件3.1. 基础背景知识3.2.write() 详解3.3.示例代码3.4.注意点3.4.1.同步IO1. fsync() 和fdatasync()2…

MySQL高可用搭建方案之(MMM)

有的时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步,认准https://blog.zysicyj.top 注意&#xff1a;这篇转载文章&#xff0c;非原创 首发博客地址 原文地址 前言 MySQL的高可用有很多种&#xff0c;有我们经常说的MMM架构、MHA架构、…

内网隧道代理技术(二十三)之 DNS隧道反弹Shell

DNS隧道反弹Shell DNS隧道 DNS协议是一种请求、应答协议,也是一种可用于应用层的隧道技术。DNS隧道的工作原理很简单,在进行DNS查询时,如果查询的域名不在DNS服务器本机缓存中,就会访问互联网进行查询,然后返回结果。如果在互联网上有一台定制的服务器,那么依靠DNS协议…

标准C库IO函数和Linux系统IO函数

linux系统的io函数更加偏底层&#xff0c;更加建议使用C库的函数&#xff0c;效率较高&#xff08;有缓冲区&#xff09; 磁盘满了或者手动fflush或者关闭文件才会io一次&#xff0c;效率提高&#xff0c;但是linux没有缓冲区 主要通过file *fp指针操作文件&#xff0c;文件描…

COSCon'23 社区召集令

一年一度的开源盛会&#xff0c;COSCon23 第八届中国开源年会&#xff0c;将于10月28~29日&#xff0c;在四川成都市高新区菁蓉汇召开&#xff01;本次大会的主题是&#xff1a;“开源&#xff1a;川流不息、山海相映”&#xff01; 三年新冠疫情没有将我们击垮&#xff0c;开源…

记录socket的使用 | TCP/IP协议下服务器与客户端之间传送数据 | java学习笔记

谨以此篇&#xff0c;记录TCP编程&#xff0c;方便日后查阅笔记 注意&#xff1a;用BufferedWriter write完后&#xff0c;一定要flush&#xff1b;否则字符不会进入流中。去看源码可知&#xff1a;真正将字符写入的不是write()&#xff0c;而是flush()。 服务器端代码&#…

运维学习之部署Alertmanager-0.24.0

参考《监控系统部署prometheus基本功能》先完成prometheus部署。 参考《运维学习之采集器 node_exporter 1.3.1安装并使用》安装node_exporter。 下载 nohup wget https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.ta…

SecureCRT ssh链接服务器

SecureCRT通过密钥进行SSH登录 说明&#xff1a; 一般的密码方式登录容易被密码暴力破解。所以一般我们会将 SSH 的端口设置为默认22以外的端口&#xff0c;或者禁用root账户登录。其实可以通过密钥登录这种方式来更好地保证安全。 密钥形式登录的原理是&#xff1a;利用密钥…

day34 集合总结

集合总结 一、概述 作用&#xff1a;存储对象的容器&#xff0c;代替数组的&#xff0c;使用更加的便捷 所处的位置&#xff1a;java.util 体系结构 二、Collection 内部的每一个元素都得是引用数据类型 常用方法 add(Object o) 添加元素 addAll(Collection c) 将指定集…

【LeetCode周赛】LeetCode第362场周赛

LeetCode第362场周赛 与车相交的点判断能否在给定时间到达单元格将石头分散到网格图的最少移动次数 与车相交的点 给你一个下标从 0 开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i&#xff0c;nums[i] [starti, endi] &#xff0c;其中 starti 是第 i…

讯飞星火认知大模型,多种应用一键体验整合

分享几个可以&#xff0c;直接可以使用的AI应用&#xff0c;依托于讯飞星火大模型实现的&#xff1b; 现在讯飞星火认知大模型&#xff0c;使用已经完全开放&#xff0c;可以直接使用&#xff1b; AI抖音商品种草文案 功能&#xff1a; 通过将商品信息输入到讯飞星火AI大模…