当前位置: 首页 > news >正文

数据结构

一、栈

先进后出

二、队列

先进先出

三、数组

查询快,增加修改慢

四、链表

查询慢,增加修改慢

五、二叉树

节点:

查找二叉树

二叉查找树的特点

  • 二叉查找树,又称二叉排序树或者二叉搜索树

  • 每一个节点上最多有两个子节点

  • 左子树上所有节点的值都小于根节点的值

  • 右子树上所有节点的值都大于根节点的值

二叉查找树添加节点规则

  • 小的存左边

  • 大的存右边

  • 一样的不存

数据结构(二叉树)遍历方式

  1. 前序遍历:当前节点,左子节点,右子结点
  2. 中序遍历:左子节点,当前节点,右子结点
  3. 后序遍历:左子节点,右子结点,当前节点
  4. 层序遍历:一层一层的去遍历

平衡二叉树

特点

  • 二叉树左右两个子树的高度差不超过1

  • 任意节点的左右两个子树都是一颗平衡二叉树

平衡二叉树旋转

  • 旋转触发时机

    • 当添加一个节点之后,该树不再是一颗平衡二叉树

  • 左旋

    • 确定支点:从添加的节点开始,不断的往父节点找不平衡的节点

    以不平衡的点作为支点
    将根节点的右侧往左拉
    原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点

右旋

  • 确定支点:从添加的节点开始,不断的往父节点找不平衡的节点

以不平衡的点作为支点
就是将根节点的左侧往右拉
原先的左子节点变成新的父节点,并把多余的右子节点出让,给已经降级的根节点当左子节点

平衡二叉树旋转的四种情况

左左

  • 左左: 当根节点左子树的左子树有节点插入,导致二叉树不平衡

  • 如何旋转: 直接对整体进行右旋即可

左右

  • 左右: 当根节点左子树的右子树有节点插入,导致二叉树不平衡

  • 如何旋转: 先在左子树对应的节点位置进行左旋,再对整体进行右旋

右右

  • 右右: 当根节点右子树的右子树有节点插入,导致二叉树不平衡

  • 如何旋转: 直接对整体进行左旋即可

右左

  • 右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡

  • 如何旋转: 先在右子树对应的节点位置进行右旋,再对整体进行左旋

红黑树

红黑树的特点

红黑树的增删改查性能都很好

  • 平衡二叉B树

  • 每一个节点可以是红或者黑

  • 红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的

节点

红黑规则

  1. 每一个节点是红色的,或者是黑色的
  2. 根节点必须是黑色
  3. 叶节点是黑色的
  4. 两个红色节点不能相连
  5. 任意节点到所有后代叶节点的简单路径上,黑色节点数量相同;

红黑树结构图

红黑树添加节点的默认颜色

  • 添加节点时,默认为红色,效率高

红黑树添加节点后如何保持红黑规则

  • 根节点位置

    • 直接变为黑色

  • 非根节点位置

    • 父节点为黑色

      • 不需要任何操作,默认红色即可

    • 父节点为红色

      • 叔叔节点为红色

        1. 将"父节点"设为黑色,将"叔叔节点"设为黑色

        2. 将"祖父节点"设为红色

        3. 如果"祖父节点"为根节点,则将根节点再次变成黑色

      • 叔叔节点为黑色

        1. 将"父节点"设为黑色

        2. 将"祖父节点"设为红色

        3. 以"祖父节点"为支点进行旋转

实现代码

public class RBTree {class Node {int val, color;Node left, right;}
//    使用NIL节点来充当叶节点Node NIL;Node root;public RBTree() {NIL = new Node();NIL.val = -1;NIL.color = 1;NIL.left = NIL.right = NIL;root = NIL;}// 创建节点private Node getNewNode(int val) {Node p = new Node();p.val = val;p.color = 0;p.left = p.right = NIL;return p;}//判断有没有红色孩子private boolean has_red_child(Node tree) {return tree.left.color == 0 || tree.right.color == 0;}//左旋private Node left_rotate(Node tree) {Node temp = tree.right;tree.right = temp.left;temp.left = tree;return temp;}//右旋private Node right_rotate(Node tree) {Node temp = tree.left;tree.left = temp.right;temp.right = tree;return temp;}//寻找前驱private Node preNode(Node tree) {Node p = tree.left;while (p.right != null) {p = p.right;}return p;}//删除public void erase(int val) {root = erase(root, val);}private Node erase(Node tree, int val) {tree = __erase(tree, val);tree.color = 1;return tree;}private Node __erase(Node tree, int val) {if (tree == NIL) return tree;if (val < tree.val) {tree.left = __erase(tree.left, val);} else if (val > tree.val) {tree.right = __erase(tree.right, val);} else {if (tree.left == NIL || tree.right == NIL) {Node temp = tree.left == NIL ? tree.right : tree.left;temp.color += tree.color;tree = temp;return tree;} else {Node temp = preNode(tree);tree.val = temp.val;tree.left = __erase(tree.left, temp.val);}}return erase_maintion(tree);}//删除调整private Node erase_maintion(Node tree) {if (tree.left.color != 2 && tree.right.color != 2) return tree;
//        兄弟为红,旋转树,新根节点转为黑,原根节点转为红if (has_red_child(tree)) {int flag = 0;tree.color = 0;if (tree.left.color == 0) {tree = right_rotate(tree);flag = 1;} else {tree = left_rotate(tree);}tree.color = 1;if (flag == 1) tree.right = erase_maintion(tree.right);else tree.left = erase_maintion(tree.left);return tree;}
//        兄弟为黑色并且没有红色子节点,子节点减黑,根节点加黑if (tree.left.color == 1 && !has_red_child(tree.left)|| tree.right.color == 1 && !has_red_child(tree.right)) {tree.color += 1;tree.left.color -= 1;tree.right.color -= 1;return tree;}
//        兄弟节点为黑并且有红色子节点
//            |-- 左子树为黑色
//              |-- 左子树的右子树为红色且左子树节点为黑 LR
//                  |-- 子树小左旋,新节点转黑,原节点转红,进入LL形态
//              |-- 左子树的左子树为红色 LL
//                  |-- 整树右旋,新节点改为原根节点的颜色,原根节点已经新叔叔节点转为黑色
//            |-- 右子树为黑色
//              |-- 右子树的左子树为红色且右子树节点为黑 RL
//                  |-- 子树小右旋,新节点转黑,原节点转红,进入RR形态
//              |-- 右子树的右子树为红色 RR
//                  |-- 整树左旋,新节点改为原根节点的颜色,原根节点已经新叔叔节点转为黑色if (tree.left.color == 1) {tree.right.color = 1;if (tree.left.left.color != 0) {tree.left.color = 0;tree.left = left_rotate(tree.left);tree.left.color = 1;}tree.left.color = tree.color;tree = right_rotate(tree);} else {tree.left.color = 1;if (tree.right.right.color != 0) {tree.right.color = 0;tree.right = right_rotate(tree.right);tree.right.color = 1;}tree.right.color = tree.color;tree = left_rotate(tree);}tree.left.color = 1;tree.right.color = 1;return tree;}//添加public void insert(int val) {root = insert(root, val);}private Node insert(Node tree, int val) {tree = __insert(tree, val);tree.color = 1;return tree;}private Node __insert(Node tree, int val) {if (tree == NIL) {return getNewNode(val);}if (val < tree.val) {tree.left = __insert(tree.left, val);} else if (val > tree.val) {tree.right = __insert(tree.right, val);}return insert_maintain(tree);}//添加调整private Node insert_maintain(Node tree) {if (!has_red_child(tree)) return tree;//节点双红if (tree.left.color == 0 && tree.right.color == 0) {if (!has_red_child(tree.left) && !has_red_child(tree.right)) return tree;tree.color = 0;tree.left.color = tree.right.color = 1;return tree;}if (tree.left.color == 0 && !has_red_child(tree.left)) return tree;if (tree.right.color == 0 && !has_red_child(tree.right)) return tree;// 左子树失衡if (tree.left.color == 0) {if (tree.left.right.color == 0) {tree.left = left_rotate(tree.left);}tree = right_rotate(tree);} else {if (tree.right.left.color == 0) {tree.right = right_rotate(tree.right);}tree = left_rotate(tree);}tree.color = 0;tree.left.color = tree.right.color = 1;return tree;}//打印输出public void preorder() {preorder(root, root.val, 0);}private void preorder(Node tree, int val, int flag) {if (tree == NIL) return;if (flag == 0) {System.out.printf("%d is root, color is %s\n", val, tree.color == 0 ? "red" : "black");} else {System.out.printf("%d is %d's %s child, color is %s\n", tree.val, val, flag == 1 ? "right" : "left", tree.color == 0 ? "red" : "black");}preorder(tree.left, tree.val, -1);preorder(tree.right, tree.val, 1);}
}

相关文章:

数据结构

一、栈 先进后出 二、队列 先进先出 三、数组 查询快&#xff0c;增加修改慢 四、链表 查询慢&#xff0c;增加修改慢 五、二叉树 节点&#xff1a; 查找二叉树 二叉查找树的特点 二叉查找树,又称二叉排序树或者二叉搜索树 每一个节点上最多有两个子节点 左子树上所…...

动态规划相关题目

文章目录 1.动态规划理论基础2.斐波那契数3.爬楼梯4.使用最小花费爬楼梯5.不同路径6.不同路径 II7. 整数拆分8. 不同的二叉搜索树 1.动态规划理论基础 1.1 什么是动态规划? 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一…...

iOS - Runtime - Class-方法缓存(cache_t)

文章目录 iOS - Runtime - Class-方法缓存(cache_t)1. 散列表的存取值 iOS - Runtime - Class-方法缓存(cache_t) Class内部结构中有个方法缓存&#xff08;cache_t&#xff09;&#xff0c;用散列表&#xff08;哈希表&#xff09;来缓存曾经调用过的方法&#xff0c;可以提高…...

2014年认证杯SPSSPRO杯数学建模B题(第一阶段)位图的处理算法全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 B题 位图的处理算法 原题再现&#xff1a; 图形&#xff08;或图像&#xff09;在计算机里主要有两种存储和表示方法。矢量图是使用点、直线或多边形等基于数学方程的几何对象来描述图形&#xff0c;位图则使用像素来描述图像。一般来说&#…...

【物联网项目】基于ESP8266的家庭灯光与火情智能监测系统——文末完整工程资料源码

目录 系统介绍 硬件配置 硬件连接图 系统分析与总体设计 系统硬件设计 ESP8266 WIFI开发板 人体红外传感器模块 光敏电阻传感器模块 火焰传感器模块 可燃气体传感器模块 温湿度传感器模块 OLED显示屏模块 系统软件设计 温湿度检测模块 报警模块 OLED显示模块 …...

Unity中控制帧率的思考

如何控制帧率&#xff1a; 在Unity中&#xff0c;你可以通过设置Application.targetFrameRate来限制帧率。 例如&#xff0c;如果你想将帧率限制为16帧&#xff0c; 你可以在你的代码中添加以下行&#xff1a; Application.targetFrameRate 16; 通常&#xff0c;这行代码会放在…...

阿里云子域名配置,且不带端口访问

进入阿里云控制台&#xff0c;创建一个SSL证书 # 域名名称child.domain.com创建完成后&#xff0c;将返回主机记录以及记录值&#xff0c;保存好&#xff0c;用于下一步使用 创建DNS解析 创建DNS的TXT类型解析 选择记录类型&#xff1a;TXT 填写主机记录&#xff1a;_dnsa…...

C#-ConcurrentDictionary用于多线程并发字典

ConcurrentDictionary 是 .NET Framework 中用于多线程并发操作的一种线程安全的字典集合类。它提供了一种在多个线程同时访问和修改字典时保持数据一致性的机制。 以下是 ConcurrentDictionary 类的一些重要特性和用法&#xff1a; 线程安全性&#xff1a;ConcurrentDictiona…...

深入探讨多线程编程:从0-1为您解释多线程(下)

文章目录 6. 死锁6.1 死锁原因 6.2 避免死锁的方法加锁顺序一致性。超时机制。死锁检测和解除机制。 6. 死锁 6.1 死锁 原因 系统资源的竞争&#xff1a;&#xff08;产生环路&#xff09;当系统中供多个进程共享的资源数量不足以满足进程的需要时&#xff0c;会引起进程对2…...

深度学习pytorch——减少过拟合的几种方法(持续更新)

1、增加数据集 2、正则化(Regularization) 正则化&#xff1a;得到一个更加简单的模型的方法。 以一个多项式为例&#xff1a; 随着最高次的增加&#xff0c;会得到一个更加复杂模型&#xff0c;模型越复杂就会更好的拟合输入数据的模型&#xff08;图-1&#xff09;&#…...

排序第五篇 归并排序

一 简介 归并排序(Merge Sort) 的基本思想是&#xff1a; 首先将待排序文件看成 n n n 个长度为1的有序子文件&#xff0c; 把这些子文件两两归并&#xff0c; 得到 n 2 \frac{n}{2} 2n​ 个长度为 2 的有序子文件&#xff1b; 然后再把这 n 2 \frac{n}{2} 2n​ 个有序的子…...

【Win】使用PowerShell和Webhooks轻松发送消息至Microsoft Teams

Microsoft Teams是一款由微软开发的团队协作和通讯工具。如果您对这个名字还不太熟悉&#xff0c;那么现在就是一个了解它的好时机。微软将Teams定位为其之前Skype for Business解决方案的继任者&#xff0c;并且它也提供了与其他基于频道的通讯应用程序&#xff08;例如Slack、…...

ESCTF-OSINT赛题WP

这你做不出来?check ESCTF{湖北大学_嘉会园食堂} 这个识图可以发现是 淡水渔人码头 但是 osint 你要发现所有信息 聊天记录说国外 同时 提示给了美国 你综合搜索 美国 渔人码头 在美国旧金山的渔人码头&#xff08;英语&#xff1a;Fisherman’s Wharf&#xff09;是一个著名旅…...

2024蓝桥杯省赛保奖突击班-Day2-前缀和、差分、尺取_笔记_练习题解

3月25日-课堂笔记 前缀和预处理 O ( n ) \mathcal{O}(n) O(n) s[1] a[1]; for(int i 2; i < n; i)s[i] s[i - 1] a[i];利用前缀和查询区间和 O ( 1 ) O(1) O(1) long long calc(int l, int r) {return l 1 ? s[r] : s[r] - s[l - 1]; }差分序列的求法 c[1] a[…...

C++基础之虚函数(十七)

一.什么是多态 多态是在有继承关系的类中&#xff0c;调用同一个指令&#xff08;函数&#xff09;&#xff0c;不同对象会有不同行为。 二.什么是虚函数 概念&#xff1a;首先虚函数是存在于类的成员函数中&#xff0c;通过virtual关键字修饰的成员函数叫虚函数。 性质&am…...

快速入门Kotlin①基本语法

前言 23年底读了一遍“Kotlin官方文档”&#xff0c;官方文档大而全&#xff0c;阅读下来&#xff0c;大有裨益。 此系列文章的目的是记录学习进程&#xff0c;同时&#xff0c;若能让读者迅速掌握重点内容并快速上手&#xff0c;那就再好不过了。 函数 带有两个 Int 参数、…...

【理解指针(四)】

文章目录 一、指针数组二、指针数组来模拟二维数组三、字符指针变量注意&#xff1a; 字符串的例子&#xff08;曾经的一道笔试题&#xff09; 四、数组指针变量1、什么是数组指针变量2、数组指针怎么初始化 五、二维数组传参的本质六、函数指针1、什么是函数指针变量2、函数的…...

Ribbon简介

目录 一 、概念介绍 1、Ribbon是什么 2、认识负载均衡 2.1 服务器端的负载均衡 2.2 客户端的负载均衡 3、Ribbon工作原理 4、Ribbon的主要组件 IClientConfig ServerList ServerListFilter IRule Iping ILoadBalancer ServerListUpdater 5、Ribbon支持…...

【感悟《剑指offer》典型编程题的极练之路】02字符串篇!

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章所属专栏&#xff1a;《剑指offer》典型编程题的极练之路 ​​​​​​ 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c…...

通过 Docker 实现国产数据库 OpenGauss 开发环境搭建

通过 Docker 实现国产数据库 OpenGauss 开发环境搭建 一 前置准备 2.1 下载镜像 docker pull enmotech/opengauss:5.0.1构建镜像的 Dockerfile&#xff0c;方便后期实现个性化定制&#xff1a; FROM ubuntu:22.04 as builderARG TARGETARCHWORKDIR /warehouseRUN set -eux;…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek&#xff1a;小白也能轻松搞定&#xff01; 如何给本地部署的 DeepSeek 投喂数据&#xff0c;让他更懂你 [实验目的]&#xff1a;理解系统架构与原…...

CppCon 2015 学习:REFLECTION TECHNIQUES IN C++

关于 Reflection&#xff08;反射&#xff09; 这个概念&#xff0c;总结一下&#xff1a; Reflection&#xff08;反射&#xff09;是什么&#xff1f; 反射是对类型的自我检查能力&#xff08;Introspection&#xff09; 可以查看类的成员变量、成员函数等信息。反射允许枚…...