【高阶数据结构】红黑树

文章目录

  • 前言
  • 什么是红黑树
  • 红黑树的性质
  • 红黑树结点的定义
  • 红黑树的插入
    • 情况一
    • 情况二
    • 情况三
    • 插入代码总结
  • 验证是否为红黑树
  • 红黑树的删除

前言

前面我们学习了 AVL 树——高度平衡的二叉搜索树,AVL 树保证了结点的左右子树的高度差的绝对值不超过 1,也就是结点的左右子树的高度是绝对平衡的,虽然这种结构的查询速度非常的快,但是因为它要保证左右子树的绝对平衡,所以对 AVL 树进行增加或者删除操作的时候,就需要进行多次旋转,而对树进行旋转也是需要时间的,所以 AVL 树只适合存储一些静态的不经常变化的数据。那么要想保证查询速度,也要对数据进行增加和删除操作的话,就需要使用另一个数据结构——红黑树。

什么是红黑树

红黑树是一种二叉搜索树,但在每个节点上增加了一个存储位表示节点的颜色,可以是 Red 或者 Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。

在这里插入图片描述

红黑树的性质

为了保证红黑树的查找速率以及增加和删除的速度,红黑树具有以下性质:

  1. 从根节点到叶子节点的路径中,最长路径最多是最短路径的二倍
  2. 每个节点不是红色就是黑色
  3. 根节点是黑色的
  4. 如果一个节点是红色的,则如果它的两个孩子节点是黑色的(一条路径上不存在两个连续的红色节点)
  5. 对于每个节点,从该结点到其所有后代节点的简单路径上,均包含相同数目的黑色节点(黑色节点的数量包括 NULL 节点)
  6. 每个叶子节点都是黑色的(此处的叶子结点指的是空结点)

这里对一些性质进行演示:

为什么从根节点到叶子节点的路径中,最长路径最多是最短路径的二倍?

这个性质是通过性质4、5得来的:
在这里插入图片描述

红黑树结点的定义

首先通过一个枚举类来表示颜色:

public enum COLOR {RED, BLACK;
}

红黑树节点的定义:

class RBTreeNode {public RBTreeNode left;public RBTreeNode right;public RBTreeNode parent;public rbtree.COLOR color = rbtree.COLOR.RED; //结点的颜色public int val;public RBTreeNode(int val) {this.val = val;this.color = COLOR.RED;}
}

在这里我们将节点的颜色默认设置为了红色,这是为什么呢?

因为红黑树的性质:从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点。将节点默认设置为红色,插入时不会违反红黑树的性质,因为红色的节点不会影响路径上黑色节点的数量。而如果默认颜色设置为黑色,每次插入新节点都可能违反红黑树的性质,需要频繁调整树的结构,导致效率降低。因此,将红黑树的结点默认颜色设置为红色是为了保持树的平衡,提高插入操作的效率。

红黑树的插入

因为红黑树也是属于特殊的二叉搜索树,所以在插入数据的时候,还是按照二叉搜索树插入的做法一样,当数据插入之后,我们需要做的就是检测新节点插入之后,红黑树的性质是否被破坏。

这里的破坏性质通常是指:因为新插入的节点的颜色默认是红色,如果新插入的节点的双亲节点的颜色是黑色的话,就没有破坏红黑树的性质,不需要做出修改;而如果插入的节点的双亲结点也是红色的话,就不符合红黑树的性质——红色结点的左右孩子节点的颜色都是黑色(在一条路径中不存在两个连续的红色节点),此时就需要对红黑树的结构进行修改。

这里我们将插入节点后需要调整红黑树结构的情况给列举出来:

这里我们约定:cur 节点为当前节点,p为父节点,g为祖父节点,u为叔叔节点

情况一

当 cur 为红色,p 为红色,g 为黑色,u 存在且为红色:

在这里插入图片描述

这里 cur 是新插入的节点,插入之后 p 为红色,cur 为红色,一条路径上存在两个连续的红色节点,此时就需要对红黑树的结构进行调整。这种情况还是比较容易解决的:这种情况,我们需要将 p 和 u 都改为黑色,并且为了保证路径上黑色节点的数量不变,还需要将 g 节点的颜色改为 RED,这样就没有破坏红黑树的性质。

在这里插入图片描述

修改 p、u 和 g 的颜色之后,还没有结束,因为红黑树的性质中还有一条性质就是:根节点的颜色必须为黑色,所以我们在进行上面的操作了之后,不管根节点为啥颜色,都需要进行 root.color = COLOR.BLACK 的操作。

通过代码体现就是这样:

while (parent != null && parent.color == COLOR.RED) {RBTreeNode grandfather = parent.parent; //grandfather不可能为null,因为如果parent为红色,那么就一定存在父亲节点,因为红黑树的根节点是黑色RBTreeNode uncle = null;if (grandfather.left == parent) {uncle = grandfather.right;}else {uncle = grandfather.left;}if (uncle != null && uncle.color == COLOR.RED) {//情况一parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandfather.color = COLOR.RED;//当grandfather的节点颜色变为了红色之后,可能又会破坏其他树的结构,所以需要继续向上调整cur = grandfather;parent = cur.parent;}
}
root.color = COLOR.BLACK; //将根节点的颜色修改为黑色

情况二

当 cur 为红色,p 为红色,g 为黑色,u 不存在或者 u 存在且为黑色:

这种情况往往不是刚插入时候造成的,而是因为在调整的过程中出现的:

在这里插入图片描述

所以这种情况只可能在向上调整的过程中才会出现:

在这里插入图片描述

对于这种情况的解决方式就是对 g 的左右子树进行右旋操作之后,将 p 的颜色改为黑色,g 的颜色改为红色:

在这里插入图片描述

这是 u 不存在的情况:

在这里插入图片描述

同样的,这里是右旋,将上面的情况进行镜像处理,就需要进行左旋操作了:

在这里插入图片描述

所以当 cur 为红色,p 为红色,g 为黑色。u不存在或者 u 存在且颜色为黑色的做法就可以总结为:

  1. 当 p 为 g 的左孩子,cur 为 p 的左孩子的时候:
  • (1)将 g 节点的左右子树进行右旋操作
  • (2)将 g 节点的颜色修改为红色,p 节点的颜色修改为黑色
  1. 当 p 为 g 的右孩子,cur 为 p 的右孩子的时候:
  • (1)将 g 节点的左右子树进行左旋操作
  • (2) 将 g 节点的颜色修改为红色,p 节点的颜色修改为黑色

通过代码体现就是这样:

while (parent != null && parent.color == COLOR.RED) {RBTreeNode grandfather = parent.parent; //grandfather不可能为null,因为如果parent为红色,那么就一定存在父亲节点,因为红黑树的根节点是黑色RBTreeNode uncle = null;if (grandfather.left == parent) {uncle = grandfather.right;if (uncle != null && uncle.color == COLOR.RED) {//情况一parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandfather.color = COLOR.RED;//当grandfather的节点颜色变为了红色之后,可能又会破坏其他树的结构,所以需要继续向上调整cur = grandfather;parent = cur.parent;}else {//else 就表示uncle为空或者uncle不为空且uncle颜色为黑色的情况if (cur == parent.left) {rotateRight(grandfather);grandfather.color = COLOR.RED;parent.color = COLOR.BLACK;}}}else {uncle = grandfather.left;if (uncle != null && uncle.color == COLOR.RED) {//情况一parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandfather.color = COLOR.RED;//当grandfather的节点颜色变为了红色之后,可能又会破坏其他树的结构,所以需要继续向上调整cur = grandfather;parent = cur.parent;}else {//else 就表示uncle为空或者uncle不为空且uncle颜色为黑色的情况if (cur == parent.right) {rotateLeft(grandfather);grandfather.color = COLOR.RED;parent.color = COLOR.BLACK;}}}
}
root.color = COLOR.BLACK;
return true;

右旋操作:

public void rotateRight(RBTreeNode parent) {RBTreeNode subL = parent.left;RBTreeNode subLR = subL.right;parent.left = subLR;if (subLR != null) {subLR.parent = parent;}RBTreeNode pParent = parent.parent;if (root == parent) {root = subL;subL.parent = null;}else {if (pParent.left == parent) {pParent.left = subLR;}else {pParent.right = subLR;}subLR.parent = pParent;}subL.right = parent;parent.parent = subL;
}

左旋操作:

public void rotateLeft(RBTreeNode parent) {RBTreeNode subR = parent.right;RBTreeNode subRL = subR.left;RBTreeNode pParent = parent.parent;parent.right = subRL;if (subRL != null) {subRL.parent = parent;}if (root == parent) {root = subR;root.parent = pParent;}else {if (pParent.left == parent) {pParent.left = subR;else {pParent.right = subR;}subR.parent = pParent;}subR.left = parent;parent.parent = subR;
}

情况三

第三种情况还是 cur 为红色,p 为红色,g 为黑色,u 不存在或者 u 存在且为黑色,但是呢?这种情况不是和第二种情况一样,p 位于 g 的左侧,cur 位于 p 的左侧、p 位于 g 的右侧,cur 位于 p 的右侧这种相同方向的情况,而是 p 位于 g 的左侧,cur 位于 p 的右侧、p 位于 g 的右侧,cur 位于 g 的左侧:

在这里插入图片描述
同样这种情况也是在调整的过程中才会出现的:

在这里插入图片描述

当出现这种情况的时候,通过右旋 g 节点的左右子树,然后修改 p 和 g 的颜色是无法解决的:

在这里插入图片描述

当出现这种情况的时候,需要先对 p 节点的左右子树进行左旋操作:

在这里插入图片描述

对 p 的左右子树进行左旋操作之后,就变成了第二类情况,接下来对 g 的左右子树进行右旋操作之后,将 g 节点的颜色修改为红色、p 节点的颜色修改为黑色就可以达到目的了。

这是当 p 为 g 的左子树,cur 为 p 的右子树的情况,对于 p 为 g 的右子树,cur 为 p 的左子树的解决方法是类似的:

在这里插入图片描述

通过代码展示就是这样的:

当 p 为 g 的左子树,cur 为 p 的右子树:

rotateLeft(parent);
RBTreeNode tmp = parent;
parent = cur;
cur = tmp;
rotateRight(grandfather);
grandfather.color = COLOR.RED;
parent.color = COLOR.BLACK;

当 p 为 g 的右子树,cur 为 p 的左子树:

rotateRight(parent);
RBTreeNode tmp = parent;
parent = cur;
cur = tmp;
rotateLeft(grandfather);
grandfather.color = COLOR.RED;
parent.color = COLOR.BLACK;

插入代码总结

public class RBTree {class RBTreeNode {public RBTreeNode left;public RBTreeNode right;public RBTreeNode parent;public rbtree.COLOR color; //结点的颜色public int val;public RBTreeNode(int val) {this.val = val;this.color = COLOR.RED;}}private RBTreeNode root;public boolean insert(int data) {RBTreeNode node = new RBTreeNode(data);if (root == null) {root = node;node.color = COLOR.BLACK;return true;}RBTreeNode cur = root, parent = null; //parent节点记录cur节点的双亲节点while (cur != null) {if (cur.val < data) {parent = cur;cur = cur.right;}else if (cur.val > data) {parent = cur;cur = cur.left;}else {return false; //二叉搜索树中不存在重复的元素}}if (data > parent.val) {parent.right = node;}else {parent.left = node;}node.parent = parent;cur = node;while (parent != null && parent.color == COLOR.RED) {RBTreeNode grandfather = parent.parent; //grandfather不可能为null,因为如果parent为红色,那么就一定存在父亲节点,因为红黑树的根节点是黑色RBTreeNode uncle = null;if (grandfather.left == parent) {uncle = grandfather.right;if (uncle != null && uncle.color == COLOR.RED) {//情况一parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandfather.color = COLOR.RED;//当grandfather的节点颜色变为了红色之后,可能又会破坏其他树的结构,所以需要继续向上调整cur = grandfather;parent = cur.parent;}else {//else 就表示uncle为空或者uncle不为空且uncle颜色为黑色的情况if (cur == parent.right) {rotateLeft(parent);RBTreeNode tmp = parent;parent = cur;cur = tmp;}rotateRight(grandfather);grandfather.color = COLOR.RED;parent.color = COLOR.BLACK;}}else {uncle = grandfather.left;if (uncle != null && uncle.color == COLOR.RED) {//情况一parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandfather.color = COLOR.RED;//当grandfather的节点颜色变为了红色之后,可能又会破坏其他树的结构,所以需要继续向上调整cur = grandfather;parent = cur.parent;}else {//else 就表示uncle为空或者uncle不为空且uncle颜色为黑色的情况if (cur == parent.left) {rotateRight(parent);RBTreeNode tmp = parent;parent = cur;cur = tmp;}rotateLeft(grandfather);grandfather.color = COLOR.RED;parent.color = COLOR.BLACK;}}}root.color = COLOR.BLACK;return true;}public void rotateRight(RBTreeNode parent) {RBTreeNode subL = parent.left;RBTreeNode subLR = subL.right;parent.left = subLR;if (subLR != null) {subLR.parent = parent;}RBTreeNode pParent = parent.parent;if (root == parent) {root = subL;subL.parent = null;}else {if (pParent.left == parent) {pParent.left = subLR;}else {pParent.right = subLR;}subLR.parent = pParent;}subL.right = parent;parent.parent = subL;}public void rotateLeft(RBTreeNode parent) {RBTreeNode subR = parent.right;RBTreeNode subRL = subR.left;RBTreeNode pParent = parent.parent;parent.right = subRL;if (subRL != null) {subRL.parent = parent;}if (root == parent) {root = subR;root.parent = pParent;}else {if (pParent.left == parent) {pParent.left = subR;}else {pParent.right = subR;}subR.parent = pParent;}subR.left = parent;parent.parent = subR;}
}

验证是否为红黑树

验证是否为红黑树,首先需要验证是否为二叉搜索树,然后验证每个路径上的黑色节点的数量是否相等,还需要验证在一条路径中是否存在两个连续的红色节点:

检验是否为二叉搜索树:

private int prev = Integer.MIN_VALUE;public boolean isBinarySearchTree(RBTreeNode root) {if (root == null) return true;boolean l = isBinarySearchTree(root.left);if (!l) return false;if (prev < root.val) {prev = root.val;return isBinarySearchTree(root.right);}else return false;
}

校验所有路径中的黑色节点的数量是否相等:

//先计算出红黑树中其中一条路径中黑色节点的数量
public int blackNum(RBTreeNode root) {if (root == null) return 0;int count = 0;RBTreeNode cur = root;if (root.left != null) {while (cur != null) {if (cur.color == COLOR.BLACK) count++;cur = cur.left;}}else if (root.right != null){while (cur != null) {if (cur.color == COLOR.BLACK) count++;cur = cur.right;}}else {count = root.color == COLOR.BLACK ? 1 : 0;}return count;
}//根据传入的路径中黑色节点的数量判断是否所有路径上的黑色节点的数量相同
public boolean checkBlackNum(RBTreeNode root, int pathBlackNum, int blackNum) {if (root == null) return true;if (root.color == COLOR.BLACK) pathBlackNum++;if (root.left == null && root.right == null) {if (pathBlackNum == blackNum) return true;else return false;}return checkBlackNum(root.left, pathBlackNum, blackNum)&& checkBlackNum(root.right, pathBlackNum, blackNum);
}

判断一条路径上是否存在两个连续的红色节点:

public boolean checkRedColor(RBTreeNode root) {if (root == null) return true;if (root.color == COLOR.RED) {if (root.left != null && root.left.color == COLOR.RED) return false;if (root.right != null && root.right.color == COLOR.RED) return false;}return checkRedColor(root.left) && checkRedColor(root.right);
}

整理接口:

public boolean checkRBTree(RBTreeNode root) {int blackNum = blackNum(root);return isBinarySearchTree(root) && checkBlackNum(root,0,blackNum)&& checkRedColor(root);
}

红黑树的删除

红黑树的删除操作主要涉及以下几个步骤:

  1. 定位节点:找到要删除的节点。如果要删除的节点有两个子节点,则需要找到该节点的后继节点(通常是右子树中的最小节点)来替代要删除的节点。
  2. 执行删除:执行标准的二叉搜索树(BST)的删除操作。这涉及到将后继节点的值复制到当前节点,并删除后继节点。如果后继节点有子节点,这些子节点将被转移到被删除节点的位置。
  3. 修复红黑树性质:删除节点后,可能会破坏红黑树的性质。因此,需要通过一系列的旋转和颜色更改操作来修复这些性质。这些操作包括左旋、右旋以及重新着色节点,以确保满足红黑树的五大特征。
  4. 处理特殊情况:在删除操作中,可能会遇到一些特殊情况,例如要删除的节点是黑色且拥有两个红色子节点,或者要删除的节点是根节点等。这些情况需要特殊的处理方式来确保红黑树的性质得到维护。

这里我就不为大家详细介绍了,大家下去可以自己了解了解。

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

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

相关文章

【正点原子STM32】STM32时钟系统(时钟树、时钟源、分频器和倍频系数、锁相环、STM32CubeMX时钟树、系统时钟配置步骤)

一、认识时钟树 1.1、什么是时钟&#xff1f;1.2、认识时钟树&#xff08;F1&#xff09;1.3、认识时钟树&#xff08;F4&#xff09;1.4、认识时钟树&#xff08;F7&#xff09;1.5、认识时钟树&#xff08;H7&#xff09; 二、配置系统时钟 2.1、系统时钟配置步骤2.2、外设…

绝世唐门:霍挂六个十万年魂环,一穿七灭团再现,淘汰赛顺利晋级

Hello,小伙伴们&#xff0c;我是拾荒君。 国漫《斗罗大陆2绝世唐门》第32期超前爆料&#xff0c;霍雨浩开局便释放六个十万年魂环&#xff0c;以绝对的气场碾压天灵学院代表队。首次参与高级魂师大赛&#xff0c;霍雨浩便大放异彩秀出超级霍挂&#xff0c;此等操作就连当初的唐…

如何修复鼠标不工作的问题?这里提供几个方法

如果你的鼠标无法连接到你的电脑,或者只能间歇性工作,那就是一个问题。你需要买一个新的吗?不一定。虽然换个便宜的无线鼠标很容易,但在你花钱买一款符合人体工程学的新鼠标或游戏鼠标之前,有一些事情需要尝试。 检查电源 像任何其他外设一样,鼠标需要电源。许多鼠标上都…

人口增长问题 T1063

#include<bits/stdc.h> using namespace std; int main(){int n;double x;cin>>x>>n;for(int i1;i<n;i){xx*1.001;}printf("%.4lf",x);return 0; }

【lesson35】基础IO之fd周边问题

文章目录 基础IO要讲的知识点介绍fd周边问题 基础IO要讲的知识点介绍 1.复习一下C语言的接口 2.直接使用系统接口 3.分析系统接口的细节&#xff0c;引入fd&#xff08;文件描述符&#xff09; 4.fd的周边问题&#xff08;fd的理解、fd和file的关系、fd分配规则、fd重定向…&a…

【数据结构】并查集(路径压缩)

文章目录 并查集1.朴素版本2.路径压缩3.按秩合并4.启发式合并5.练习题 并查集 1.朴素版本 1. 并查集解决的是连通块的问题&#xff0c;常见操作有&#xff0c;判断两个元素是否在同一个连通块当中&#xff0c;两个非同一连通块的元素合并到一个连通块当中。 并查集和堆的结构…

Unity 图片不改变比例适配屏幕

Unity 图片不改变比例适配屏幕 前言项目场景布置代码编写添加并设置脚本效果 前言 遇到一个要让图片适应相机大小&#xff0c;填满屏幕&#xff0c;但不改变图片比例的需求&#xff0c;记录一下。 项目 场景布置 代码编写 创建AdaptiveImageBackground脚本 using System.C…

ConcurrentModificationException异常原因,解决方法,线程安全的单例模式

异常简介 ConcurrentModificationException&#xff08;并发修改异常&#xff09;是基于java集合中的 快速失败&#xff08;fail-fast&#xff09; 机制产生的&#xff0c;在使用迭代器遍历一个集合对象时&#xff0c;如果遍历过程中对集合对象的内容进行了增删改&#xff0c;…

Fink CDC数据同步(二)MySQL数据同步

1 开启binlog日志 2 数据准备 use bigdata; drop table if exists user;CREATE TABLE user(id INTEGER NOT NULL AUTO_INCREMENT,name VARCHAR(20) NOT NULL DEFAULT ,birth VARCHAR(20) NOT NULL DEFAULT ,gender VARCHAR(10) NOT NULL DEFAULT ,PRIMARY KEY(id) ); ALTER TA…

刘知远团队大模型技术与交叉应用L6-基于大模型文本理解和生成介绍

介绍 NLP的下游运用可以分为&#xff1a;NLU(理解)和NLG(生成) 信息检索&#xff1a;NLU 文本生成&#xff1a;NLG 机器问答&#xff1a;NLUNLG 大模型在信息检索 大模型在机器问答 大模型在文本生成 信息检索-Information Retrieval (IR) 背景 谷歌搜索引擎目前同时集成了…

NLP入门系列—Attention 机制

NLP入门系列—Attention 机制 Attention 正在被越来越广泛的得到应用。尤其是 [BERT]火爆了之后。 Attention 到底有什么特别之处&#xff1f;他的原理和本质是什么&#xff1f;Attention都有哪些类型&#xff1f;本文将详细讲解Attention的方方面面。 Attention 的本质是什…

Mac M1使用PD虚拟机运行win10弹出“内部版本已过期立即安装新的windows内部版本”

一、问题 内部版本已过期立即安装新的windows内部版本 二、解决 1、如图所示打开zh-CN目录 C:\windows\system32\zh-CN找到licensingui.exe文件 将该文件重命名为licensingui_bak.exe 2、修改完成效果如下 &#xff08;1&#xff09;但操作中发现&#xff0c;需要TrustedIns…

闲的无聊,做了几个微信红包封面,才发现好像没啥用,索然无味

这几天闲的无聊&#xff0c;正好也快要过年了&#xff0c;心血来潮搞几个微信红包封面。 折腾了大半天&#xff0c;又是ps&#xff0c;又是开通微信红包封面平台。 弄了100多个图&#xff0c;选出来50个&#xff0c;最后就提交了1个到微信平台&#xff0c;也通过审核了。 最…

【Kafka】服务器Broker与Controller详解

这里写自定义目录标题 Broker概述Broker总体工作流程Broker重要参数 Controller为什么需要Controller具体作用数据服务Leader选举选举流程脑裂问题羊群效应触发leader选举 Broker 概述 Kafka服务实例&#xff0c;负责消息的持久化、中转等功能。一个独立的Kafka 服务器被就是…

vue2 对接 海康摄像头插件 (视频WEB插件 V1.5.2)

前言 海康视频插件v.1.5.2版本运行环境需要安装插件VideoWebPlugin.exe&#xff0c;对浏览器也有兼容性要求&#xff0c;具体看官方文档 对应下载插件 去海康官网下载插件 里面有dome等其他需要用到的 地址&#xff1a; 安装插件 打开下载的文件里的bin文件 安装一下Video…

修改Vim编辑器的缩进和显示行数

一、Vim编辑器的缩进和显示行数 1.指令 sudo vi /etc/vim/vimrc2.插入内容 set tabstop4 set shiftwidth4 set nu 注意输入的格式&#xff0c;前后不要留空格 tabstop是输入按下tab缩进4个 shiftwidth是批量缩进4个 nu是显示行数

革命性的写作:MDX 让你的 Markdown 全面动起来

1. MDX MDX 是一种标记语法&#xff0c;它结合了 Markdown&#xff08;一种流行的文本到 HTML 的转换工具&#xff09;和 JSX&#xff08;React 中用于描述 UI 组件的语法扩展&#xff09;。MDX 允许你在 Markdown 文档中直接写入 JSX&#xff0c;这意味着你可以在 Markdown 内…

IPv6协议讲解

IPv6协议讲解 IPv6是互联网协议的第六版(Internet Protocol Version 6)&#xff0c;它用于在互联网上路由数据包&#xff0c;旨在替代IPv4&#xff0c;它提供了更多的IP地址和改进的网络功能。IPv6是为了应对互联网快速发展带来的挑战而设计的&#xff0c;它的引入不仅解决了地…

【教学类-40-08】A4骰子纸模制作8.0(2.97CM嵌套骰子表格相连 一页7个 油墨打印A4铅画纸)

作品展示&#xff08;一页7个骰子&#xff0c;表格连在一起&#xff0c;一行一个&#xff08;2嵌套&#xff09;&#xff09; 背景需求&#xff1a; 制作三嵌套盒子并实践后&#xff0c;感觉套起来很紧&#xff0c;还是用2嵌套的铅画纸做骰子比较好&#xff0c; https://blog…

代码随想录算法训练营|day24

第七章 回溯算法 77.组合代码随想录文章详解总结 77.组合 以n5,k3为例 (1)for循环遍历&#xff0c;递归选择符合要求的值加入path&#xff0c;len(path)k时&#xff0c;返回 statrtIndex保证每次递归取到的值不重复 剪枝&#xff1a;i<n-(k-len(path))1 后续需要k-len(pat…