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

一:二叉搜索树

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

它具有以下特点:

        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.rhkb.cn/news/127606.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Matlab图像处理-自适应阈值

自适应阈值 在许多的情况下&#xff0c;背景的灰度值并不是常数&#xff0c;物体和背景的对比度在图像中也有变化。这时&#xff0c;一个在图像中某一区域效果良好的阈值在其它区域却可能效果很差。在这种情况下&#xff0c;把灰度阈值取成一个随图像中位置缓慢变化的函数值是…

SNMP的监控

SNMP的监控 一、SNMP 介绍1.1 什么是SNMP1.2 SNMP的组件1.2.1 网络管理系统 NMS&#xff08;Network Management System&#xff09;1.2.2 代理进程&#xff08;Agent&#xff09;1.2.3 被管对象&#xff08;Managed Object&#xff09;1.2.4 管理信息库MIB&#xff08;Managem…

linux c++ 开发 - 05- 使用CMake创建一个动态库

外层CMakeList.txt中的内容&#xff1a; cmake_minimum_required(VERSION 3.16) PROJECT(HELLO) ADD_SUBDIRECTORY(lib bin)lib中CMakeLists.txt中的内容&#xff1a; SET(LIBHELLO_SRC hello.cpp) ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})hello.h: hello.cpp: ADD_LIBR…

多元共进|科技促进艺术发展,助力文化传承

科技发展助力文化和艺术的传播 融合传统与创新&#xff0c;碰撞独特魅力 一起来了解 2023 Google 开发者大会上 谷歌如何依托科技创新 推动艺术与文化连接 传承和弘扬传统文化 自 2011 年成立以来&#xff0c;谷歌艺术与文化致力于提供体验艺术和文化的新方式&#xff0c;从生成…

mysql基于AES_ENCRYPTAES_DECRYPT实现密码的加密与解密

1.直接使用AES_ENCRYPT&&AES_DECRYPT函数导致的问题。 执行语句 select AES_ENCRYPT(cd123,key) 结果 加密过后的字符串是一串很奇怪的字符。 尝试使用上面加密过后的字符解密。 select AES_DECRYPT(u5£d|#,key) 结果 并未成功的解密 2.解决办法 使用 hex(…

【漏洞复现】网互联路由器存在密码泄露

漏洞描述 蜂网互联-让链接无限可能&#xff0c;灵活的多线分流&#xff0c;强大的策略分流&#xff0c;灵活调度各种软件应用&#xff0c;深度识别系统&#xff0c;各种应用一网打尽&#xff0c;灵活调整优先级&#xff0c;最简单的路由器&#xff0c;简洁易学的配置&#xff…

MyBatisPlus 基础Mapperr接口:增删改查

MyBatisPlus 基础Mapper接口&#xff1a;增删改查 插入一条数据 代码 Testpublic void insert() {User user new User();user.setId(6L);user.setName("张三");user.setAge(25);user.setEmail("zhangsanexample.com");userMapper.insert(user);}日志 数…

单元测试与自测

单元测试在百度百科的定义&#xff1a; 自测在百度百科的定义&#xff1a; 单元测试是测一个类或一个函数&#xff0c;自立门第main函数&#xff0c;不依赖于项目&#xff0c;预期的是这个类或函数是没有问题的。程序编码完成之后至各种测试再到用户使用一二十年出现的任何bug都…

IDEA中的“Deployment“ 将项目直接部署到服务器上

ntelliJ IDEA中的"Deployment"工具栏是一个方便的工具&#xff0c;用于将你的项目直接部署到服务器上。这个工具栏提供了三种部署的方式&#xff1a; 1.Web Server在本地电脑上&#xff0c;并且服务器运行目录也在项目目录下。 2.Web Server在本地电脑上&#xff0c;…

nuxt3项目使用pdfjs-dist预览pdf

使用的包的源代码是 pdfjs - npm 但是我们实际上项目中使用的是pdfjs打包后的dist文件&#xff0c;也就是pdfjs-dist - npm 所以我们需要使用这个命令 npm i pdfjs-dist 我们可以克隆pdfjs这个包来看源代码&#xff0c;里面有使用的例子&#xff0c;也可以根据源代码自己打…

Vue中数据可视化关系图展示与关系图分析

Vue中数据可视化关系图展示与关系图分析 数据可视化是现代Web应用程序的重要组成部分之一&#xff0c;它可以帮助我们以图形的方式呈现和分析复杂的数据关系。Vue.js是一个流行的JavaScript框架&#xff0c;它提供了强大的工具来构建数据可视化应用。本文将介绍如何使用Vue.js…

JavaWeb知识梳理(后端部分)

JavaWeb 静态web资源&#xff08;如html 页面&#xff09;&#xff1a;指web页面中供人们浏览的数据始终是不变。 动态web资源&#xff1a;指web页面中供人们浏览的数据是由程序产生的&#xff0c;不同时间点访问web页面看到的内容各不相同。 静态web资源开发技术&#xff1…

Spring Data JPA:简化数据库交互的艺术

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

代码随想录第45天|70. 爬楼梯,322. 零钱兑换,279.完全平方数

70. 爬楼梯 开始按感觉做 class Solution {public int climbStairs(int n) {//第一版按感觉做//dp[i]爬到第i个台阶的方法数int[] dpnew int[n1];//初始化dp[0]1;dp[1]1;for(int i2;i<n;i){dp[i]dp[i-1]dp[i-2];}return dp[n];} } 改进-用完全背包做 这是背包里求排列问…

ubuntu server 更改时区:上海

1. 打开终端&#xff0c;在命令行中以超级用户或具有sudo权限的用户身份运行以下命令&#xff1a; sudo dpkg-reconfigure tzdata 这会打开一个对话框&#xff0c;用于选择系统的时区设置。 2. 在对话框中&#xff0c;使用上下箭头键在地区列表中选择"Asia"&#x…

vue表格不显示列号123456

我在网上找了半天&#xff0c;都是如何添加列号123456的&#xff0c;没有找到不显示列号的参考&#xff0c;现在把这个解决了&#xff0c;特此记录一下。 没有加右边的就会显示&#xff0c;加上右边的就隐藏了

npm/yarn link 测试包时报错 Warning: Invalid hook call. Hooks can only be called ...

使用 dumi 开发 React 组件库时&#xff0c;为避免每次修改都发布到 npm&#xff0c;需要在本地的测试项目中使用 npm link 为组件库建立软连接&#xff0c;方便本地调试。 结果在本地测试项目使用 $ npm link 组件库 后&#xff0c;使用内部组件确报错&#xff1a; react.dev…

Redis十大数据类型

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

腾讯音乐基于 Apache Doris + 大模型构建全新智能数据服务平台

当前&#xff0c;大语言模型的应用正在全球范围内引发新一轮的技术革命与商业浪潮。腾讯音乐作为中国领先在线音乐娱乐平台&#xff0c;利用庞大用户群与多元场景的优势&#xff0c;持续探索大模型赛道的多元应用。本文将详细介绍腾讯音乐如何基于 Apache Doris 构建查询高效、…

基于Python+DenseNet121算法模型实现一个图像分类识别系统案例

目录 介绍在TensorFlow中的应用实战案例最后 一、介绍 DenseNet&#xff08;Densely Connected Convolutional Networks&#xff09;是一种卷积神经网络&#xff08;CNN&#xff09;架构&#xff0c;2017年由Gao Huang等人提出。该网络的核心思想是密集连接&#xff0c;即每…