C++红黑树(图文详解)

2023-10-26

原文链接



红黑树简介

红黑树是一种自平衡的二叉查找树,是一种高效的查找树。它是由 Rudolf Bayer 于1978年发明,在当时被称为对称二叉 B 树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的红黑树。红黑树具有良好的效率,它可在 O(logN) 时间内完成查找、增加、删除等操作。因此,红黑树在业界应用很广泛,比如 Java 中的 TreeMap,JDK 1.8 中的 HashMap、C++ STL 中的 map 均是基于红黑树结构实现的。考虑到红黑树是一种被广泛应用的数据结构,所以我们很有必要去弄懂它。

在这里插入图片描述

红黑树的性质

学过二叉查找树的同学都知道,普通的二叉查找树在极端情况下可退化成链表,此时的增删查效率都会比较低下。为了避免这种情况,就出现了一些自平衡的查找树,比如 AVL,红黑树等。这些自平衡的查找树通过定义一些性质,将任意节点的左右子树高度差控制在规定范围内,以达到平衡状态。以红黑树为例,红黑树通过如下的性质定义实现自平衡:

  1. 节点是红色或黑色。
  2. 根是黑色。
  3. 所有叶子都是黑色(叶子是NIL节点)。
  4. 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
  5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点(简称黑高)。

有了上面的几个性质作为限制,即可避免二叉查找树退化成单链表的情况。但是,仅仅避免这种情况还不够,这里还要考虑某个节点到其每个叶子节点路径长度的问题。如果某些路径长度过长,那么,在对这些路径上的及诶单进行增删查操作时,效率也会大大降低。这个时候性质4和性质5用途就凸显了,有了这两个性质作为约束,即可保证任意节点到其每个叶子节点路径最长不会超过最短路径的2倍。原因如下:

当某条路径最短时,这条路径必然都是由黑色节点构成。当某条路径长度最长时,这条路径必然是由红色和黑色节点相间构成(性质4限定了不能出现两个连续的红色节点)。而性质5又限定了从任一节点到其每个叶子节点的所有路径必须包含相同数量的黑色节点。此时,在路径最长的情况下,路径上红色节点数量 = 黑色节点数量。该路径长度为两倍黑色节点数量,也就是最短路径长度的2倍。举例说明一下,请看下图:

在这里插入图片描述

上图画出了从根节点 M 出发的到其叶子节点的最长和最短路径。这里偷懒只画出了两条最长路径,实际上最长路径有4条,分别为:

M -> Q -> O -> N
M -> Q -> O -> p
M -> Q -> Y -> X
M -> Q -> Y -> Z

 
 
 
 
  • 1
  • 2
  • 3
  • 4

长度为4,最短路径为 M -> E,长度为2。最长路径的长度正好为最短路径长度的2倍。

前面说了关于红黑树的一些性质,这里还需要补充一些其他方面的东西。在红黑树简介一节中说到红黑树被发明出来的时候并不叫红黑树,而是叫做对称二叉 B 树,从名字中可发现红黑树和 B 树(这里指的是2-3树)或许有一定的关联,事实也正是如此。如果对红黑树的性质稍加修改,就能让红黑树和B树形成一一对应的关系。关于红黑树和 B 树关系的细节这里不展开说明了,有兴趣的同学可以参考《算法》第4版,那本书上讲的很透彻。

红黑树操作

红黑树的基本操作和其他树形结构一样,一般都包括查找、插入、删除等操作。前面说到,红黑树是一种自平衡的二叉查找树,既然是二叉查找树的一种,那么查找过程和二叉查找树一样,比较简单,这里不再赘述。相对于查找操作,红黑树的插入和删除操作就要复杂的多。尤其是删除操作,要处理的情况比较多,不过大家如果静下心来去看,会发现其实也没想的那么难。好了,废话就说到这,接下来步入正题吧。

旋转操作

在分析插入和删除操作前,这里需要插个队,先说明一下旋转操作,这个操作在后续操作中都会用得到。旋转操作分为左旋和右旋,左旋是将某个节点旋转为其右孩子的左孩子,而右旋是节点旋转为其左孩子的右孩子。这话听起来有点绕,所以还是请看下图:

在这里插入图片描述

上图包含了左旋和右旋的示意图,这里以右旋为例进行说明,右旋节点 M 的步骤如下:

  1. 将节点 M 的左孩子引用指向节点 E 的右孩子
  2. 将节点 E 的右孩子引用指向节点 M,完成旋转

在这里插入图片描述

上面分析了右旋操作,左旋操作与此类似,大家有兴趣自己画图试试吧,这里不再赘述了。旋转操作本身并不复杂,这里先分析到这吧。

插入

红黑树的插入过程和二叉查找树插入过程基本类似,不同的地方在于,红黑树插入新节点后,需要进行调整,以满足红黑树的性质。性质1规定红黑树节点的颜色要么是红色要么是黑色,那么在插入新节点时,这个节点应该是红色还是黑色呢?答案是红色,原因也不难理解。如果插入的节点是黑色,那么这个节点所在路径比其他路径多出一个黑色节点,这个调整起来会比较麻烦(参考红黑树的删除操作,就知道为啥多一个或少一个黑色节点时,调整起来这么麻烦了)。如果插入的节点是红色,此时所有路径上的黑色节点数量不变,仅可能会出现两个连续的红色节点的情况。这种情况下,通过变色和旋转进行调整即可,比之前的简单多了。

接下来,将分析插入红色节点后红黑树的情况。这里假设要插入的节点为 N,N 的父节点为 P,祖父节点为 G,叔叔节点为 U。插入红色节点后,会出现5种情况,分别如下:

情况一

插入的新节点 N 是红黑树的根节点,这种情况下,我们把节点 N 的颜色由红色变为黑色,性质2(根是黑色)被满足。同时 N 被染成黑色后,红黑树所有路径上的黑色节点数量增加一个,性质5(从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点)仍然被满足。

在这里插入图片描述

情况二

N 的父节点是黑色,这种情况下,性质4(每个红色节点必须有两个黑色的子节点)和性质5没有受到影响,不需要调整。

在这里插入图片描述

情况三

N 的父节点是红色(节点 P 为红色,其父节点必然为黑色),叔叔节点 U 也是红色。由于 P 和 N 均为红色,所有性质4被打破,此时需要进行调整。这种情况下,先将 P 和 U 的颜色染成黑色,再将 G 的颜色染成红色。此时经过 G 的路径上的黑色节点数量不变,性质5仍然满足。但需要注意的是 G 被染成红色后,可能会和它的父节点形成连续的红色节点,此时需要递归向上调整。

在这里插入图片描述

情况四

N 的父节点为红色,叔叔节点为黑色。节点 N 是 P 的右孩子,且节点 P 是 G 的左孩子。此时先对节点 P 进行左旋,调整 N 与 P 的位置。接下来按照情况五进行处理,以恢复性质4。

在这里插入图片描述

情况五

N 的父节点为红色,叔叔节点为黑色。N 是 P 的左孩子,且节点 P 是 G 的左孩子。此时对 G 进行右旋,调整 P 和 G 的位置,并互换颜色。经过这样的调整后,性质4被恢复,同时也未破坏性质5。

在这里插入图片描述

插入总结

上面五种情况中,情况一和情况二比较简单,情况三、四、五稍复杂。但如果细心观察,会发现这三种情况的区别在于叔叔节点的颜色,如果叔叔节点为红色,直接变色即可。如果叔叔节点为黑色,则需要选选择,再交换颜色。当把这三种情况的图画在一起就区别就比较容易观察了,如下图:

在这里插入图片描述

删除

相较于插入操作,红黑树的删除操作则要更为复杂一些。删除操作首先要确定待删除节点有几个孩子,如果有两个孩子,不能直接删除该节点。而是要先找到该节点的前驱(该节点左子树中最大的节点)或者后继(该节点右子树中最小的节点),然后将前驱或者后继的值复制到要删除的节点中,最后再将前驱或后继删除。由于前驱和后继至多只有一个孩子节点,这样我们就把原来要删除的节点有两个孩子的问题转化为只有一个孩子节点的问题,问题被简化了一些。我们并不关心最终被删除的节点是否是我们开始想要删除的那个节点,只要节点里的值最终被删除就行了,至于树结构如何变化,这个并不重要。

红黑树删除操作的复杂度在于删除节点的颜色,当删除的节点是红色时,直接拿其孩子节点补空位即可。因为删除红色节点,性质5(从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点)仍能够被满足。当删除的节点是黑色时,那么所有经过该节点的路径上的黑节点数量少了一个,破坏了性质5。如果该节点的孩子为红色,直接拿孩子节点替换被删除的节点,并将孩子节点染成黑色,即可恢复性质5。但如果孩子节点为黑色,处理起来就要复杂的多。分为6种情况,下面会展开说明。

在展开说明之前,我们先做一些假设,方便说明。这里假设最终被删除的节点为X(至多只有一个孩子节点),其孩子节点为NX的兄弟节点为SS的左节点为 SL,右节点为 SR。接下来讨论是建立在节点 X 被删除,节点 N 替换X的基础上进行的。这里说明把被删除的节点X特地拎出来说一下的原因是防止大家误以为节点N会被删除,不然后面就会看不明白。

在这里插入图片描述

在上面的基础上,接下来就可以展开讨论了。红黑树删除有6种情况,分别是:

情况一

N 是新的根。在这种情形下,我们就做完了。我们从所有路径去除了一个黑色节点,而新根是黑色的,所以性质都保持着。

上面是维基百科中关于红黑树删除的情况一说明,由于没有配图,看的有点晕。经过思考,我觉得可能会是下面这种情形:

要删除的节点 X 是根节点,且左右孩子节点均为空节点,此时将节点 X 用空节点替换完成删除操作。

可能还有其他情形,大家如果知道,烦请告知。

情况二

S 为红色,其他节点为黑色。这种情况下可以对 N 的父节点进行左旋操作,然后互换 P 与 S 颜色。但这并未结束,经过节点 P 和 N 的路径删除前有3个黑色节点(P -> X -> N),现在只剩两个了(P -> N)。比未经过 N 的路径少一个黑色节点,性质5仍不满足,还需要继续调整。不过此时可以按照情况四、五、六进行调整。

在这里插入图片描述

情况三

N 的父节点,兄弟节点 S 和 S 的孩子节点均为黑色。这种情况下可以简单的把 S 染成红色,所有经过 S 的路径比之前少了一个黑色节点,这样经过 N 的路径和经过 S 的路径黑色节点数量一致了。但经过 P 的路径比不经过 P 的路径少一个黑色节点,此时需要从情况一开始对 P 进行平衡处理。

在这里插入图片描述

情况四

N 的父节点为红色,叔叔节点为黑色。节点 N 是 P 的右孩子,且节点 P 是 G 的左孩子。此时先对节点 P 进行左旋,调整 N 与 P 的位置。接下来按照情况五进行处理,以恢复性质4。

在这里插入图片描述

这里需要特别说明一下,上图中的节点 N 并非是新插入的节点。当 P 为红色时,P 有两个孩子节点,且孩子节点均为黑色,这样从 G 出发到各叶子节点路径上的黑色节点数量才能保持一致。既然 P 已经有两个孩子了,所以 N 不是新插入的节点。情况四是由以 N 为根节点的子树中插入了新节点,经过调整后,导致 N 被变为红色,进而导致了情况四的出现。考虑下面这种情况(PR 节点就是上图的 N 节点):

在这里插入图片描述

如上图,插入节点 N 并按情况三处理。此时 PR 被染成了红色,与 P 节点形成了连续的红色节点,这个时候就需按情况四再次进行调整。

情况五

S 为黑色,S 的左孩子为红色,右孩子为黑色。N 的父节点颜色可红可黑,且 N 是 P 左孩子。这种情况下对 S 进行右旋操作,并互换 S 和 SL 的颜色。此时,所有路径上的黑色数量仍然相等,N 兄弟节点的由 S 变为了 SL,而 SL 的右孩子变为红色。接下来我们到情况六继续分析。

在这里插入图片描述

情况六

S 为黑色,S 的右孩子为红色。N 的父节点颜色可红可黑,且 N 是其父节点左孩子。这种情况下,我们对 P 进行左旋操作,并互换 P 和 S 的颜色,并将 SR 变为黑色。因为 P 变为黑色,所以经过 N 的路径多了一个黑色节点,经过 N 的路径上的黑色节点与删除前的数量一致。对于不经过 N 的路径,则有以下两种情况:

  1. 该路径经过 N 新的兄弟节点 SL ,那它之前必然经过 S 和 P。而 S 和 P 现在只是交换颜色,对于经过 SL 的路径不影响。
  2. 该路径经过 N 新的叔叔节点 SR,那它之前必然经过 P、 S 和 SR,而现在它只经过 S 和 SR。在对 P 进行左旋,并与 S 换色后,经过 SR 的路径少了一个黑色节点,性质5被打破。另外,由于 S 的颜色可红可黑,如果 S 是红色的话,会与 SR 形成连续的红色节点,打破性质4(每个红色节点必须有两个黑色的子节点)。此时仅需将 SR 由红色变为黑色即可同时恢复性质4和性质5(从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。)。

在这里插入图片描述

删除总结

红黑树删除的情况比较多,大家刚开始看的时候可能会比较晕。可能会产生这样的疑问,为啥红黑树会有这种删除情况,为啥又会有另一种情况,它们之间有什么联系和区别?和大家一样,我刚开始看的时候也有这样的困惑,直到我把所有情况对应的图形画在一起时,拨云见日,一切都明了了。此时天空中出现了4个字,原来如此、原来如此、原来如此。所以,请看图吧:

在这里插入图片描述

总结

红黑树是一种重要的二叉树,应用广泛,但在很多数据结构相关的书本中出现的次数并不多。很多书中要么不说,要么就一笔带过,并不会进行详细的分析,这可能是因为红黑树比较复杂的缘故。本人在学习红黑树的时候也找了很多资料,但总体感觉讲的都不太好。尤其是在我学习删除操作的时候,很多资料是实在人看不下去,看的我很痛苦。直到我看到维基百科上关于红黑树的分析时,很是欣喜。这篇文章分析的很有条理,言简意赅,比很多资料好了太多。本文对红黑树的分析也主要参考了维基百科中的红黑树分析,并对维基百科中容易让人产生疑问和误解的地方进行了说明。同时维基百科中文版红黑树文中的图片较为模糊,这里我重新进行了绘制。需要说明的是,维基百科中文版无法打开了,文中关于维基百科的链接都是英文版的。

最后,如果你也在学习红黑树,希望这篇文章能够帮助到你。另外,由于红黑树本身比较复杂,加之本人水平有限,难免会出一些错误。如果有错,还望大家指出来,我们共同讨论。

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

C++红黑树(图文详解) 的相关文章

  • 无法使用 rtools40 和 R 4.0 构建 RDCOMClient

    不久前 我创建了 RDCOMClient 包的一个分支 以使其与 R 3 6 一起工作 https github com dkyleward RDCOMClient https github com dkyleward RDCOMClien
  • Hololens 应用程序将不再构建 - 引用元数据文件丢失且找不到 c-Sharp.firstpass

    我已按照 Microsoft 在其多个项目下列出的确切步骤进行操作微软全息 学院 https developer microsoft com en us windows holographic academy教程 我完成了所有这些 并且从创
  • 为什么我需要显式编写“auto”关键字?

    我正在从 C 98 转向 C 11 并且已经熟悉了auto关键词 我想知道为什么我们需要明确声明auto编译器是否能够自动推导类型 我知道 C 是一种强类型语言 这是一条规则 但如果不显式声明变量就不可能实现相同的结果auto 放弃显式的a
  • 在 TPL Dataflow 中,是否可以在创建块之后但使用之前更改 DataflowBlockOptions?

    有效果吗 我想推迟设置 ExecutionDataflowBlockOptions SingleProducerConstrained 属性 直到我准备好将网络链接在一起 因为 我想将创建块及其语义与将网络及其语义链接在一起分开 但据我所知
  • 进入嵌入式[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • C# SMO 远程数据库备份到本地机器

    我有一个执行 SQL 数据库备份和恢复的应用程序 这在本地计算机上运行良好 但是如果我针对另一台计算机上托管的 SQL 服务器运行此应用程序 则会出现以下错误 Microsoft SqlServer Management Smo Faile
  • 从 C# 访问 COM vtable

    C 中有没有办法访问 COM 对象的虚拟方法表以获取函数的地址 经过大量搜索和拼凑不同的部分解决方案后 我弄清楚了如何做到这一点 首先 您需要为您尝试访问的对象定义 COM 组件类 ComImport Guid InterfaceType
  • ICSharpCode.Decompiler + Mono.Cecil -> 如何为单个方法生成代码?

    我可以使用 Mono Cecil 和 ICSharpCode Decompiler 生成类型或程序集的代码 但是 如果我尝试为单个方法生成代码 我将收到错误 对象引用未设置为对象的实例 你们能给我任何关于这个的提示吗 提前感谢您的所有帮助
  • 使用 C# 启动 Outlook

    我可以让 C 在代码中启动 Outlook 吗 在 VB6 中 我们使用对象 Outlook Application 并编写 Set oOutlook CreateObject Outlook Application Set oNameSp
  • std::string substr 方法问题

    你好 我正在写这个方法 我希望它从给定缓冲区中提取给定位置的一部分 我有一个像这样的字符串something one something two我想要得到 一个 这是我的想法 static std string Utils getHeade
  • 不使用 DAO 压缩 Microsoft Access 数据库

    我用CDatabase类开一个ACCDB访问数据库 司机是 T Microsoft Access Driver mdb accdb 我可以打开并使用数据库 已经这样做很多年了 if DatabaseExist m strMDBPath AJ
  • autofac 中的条件组件注册

    是否可以根据其他组件的状态有条件地注册组件 就像是 ContainerBuilder RegisterConditionally
  • 如何声明返回相同类型的 Func Delegate 的 Func Delegate?

    我想编写一个方法 该方法可以完成一些工作 并最终返回另一个与原始方法具有相同签名的方法 这个想法是根据前一个字节值顺序处理字节流 而不进行递归 通过这样调用它 MyDelegate executeMethod handleFirstByte
  • 将 jstring 转换为 QString

    我正在调用一个返回字符串的 Java 函数 QAndroidJniObject obj QAndroidJniObject callStaticObjectMethod
  • 通用 lambda 的数量

    可以通过访问非泛型 lambda 的数量来推断其数量operator template
  • 在 C++ 中运行 python [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个用 C 编写的应用程序和一个测试系统 也是用 C 编写的 测试系统非常复杂并且很难改变 我只想做一些小的改变 我的班级是这样的
  • 通过 C++ 标头在 C++ 和 C# 中使用枚举

    我有一个用 C 编写的服务器 位于命名管道的末端 嗯 提供服务 可以发送到服务器的命令在位于头文件中的枚举中定义 enum e doThing1 e doThing2 e doLastThing 所需枚举的值被放入发送到服务器的消息的第一个
  • 您可以从 AuthorizeAttribute 返回 HTTP 响应而不引发异常吗?

    我在各种控制器上使用 AuthorizeAttribute 可能需要根据请求本身的某些属性返回 403 或 429 请求过多 我完全在自定义 OnAuthorization 实现中实现了它 然后在必要时抛出一个带有适当响应代码的新 Http
  • C# p/Invoke 如何使用 DirectX 游戏的 SendInput 模拟 keyPRESS 事件

    我经常为各种机器人或其他 GUI 自动化程序模拟键盘按下事件而苦苦挣扎 我已经成功地使用以下方法模拟按键事件 INPUT kInput new INPUT 1 kInput j type SendInputEventType InputKe
  • 从 C# 应用程序调用 ASP.net Web 服务

    我有个问题 我如何调用 Web 服务并从 C 桌面应用程序获取结果 我正在制作一个桌面应用程序 我希望它能够连接到我的在线 ASP net Web 服务 这怎么可能 在 解决方案资源管理器 中 右键单击项目节点并选择 添加 Service参

随机推荐

  • 机器学习实战:AdaBoost预测病马率

    import numpy as np 函数说明 加载数据集 Parameters filename 文件名 Returns dataMat 数据集 labelMat 标签 def loadDataSet filename numFeat l
  • select epool

    一 问题引出 联系区别 问题的引出 当需要读两个以上的I O的时候 如果使用阻塞式的I O 那么可能长时间的阻塞在一个描述符上面 另外的描述符虽然有数据但是不能读出来 这样实时性不能满足要求 大概的解决方案有以下几种 1 使用多进程或者多线
  • Deepin 20.1 安装nvidia显卡驱动 爬坑

    前言 之前用的是ubuntu系统 装得也是双系统 然后最近看到了deepin 系统 然后就装了下 在装nvidia显卡时 遇到了重启蓝屏的问题 在反复重装N多次系统同时查阅N多次网友资料时 总结出以下几点 当然如果你想安装的话直接滑下方 不
  • 【计算机视觉

    文章目录 一 检测相关 8篇 1 1 Attending Generalizability in Course of Deep Fake Detection by Exploring Multi task Learning 1 2 Harv
  • 基于参数shared_pool_reserved_size进一步理解共享池shared pool原理

    结论 1 与共享池相关的参数为 shared pool size shared pool reserved size shared pool reserved pct shared pool reserved min alloc 2 sha
  • String的三种遍历方式

    include include using namespace std int main string s1 string s2 hello bite string s3 s2 1 for循环 for size t i 0 i lt s2
  • JUC学习系列十一(并发类容器)

    首先了解一下并发类容器和同步类容器的概念 以及这两类的区别 一 同步类容器 同步类容器都是线程安全的 但在某些场景下可能需要加锁来保护复合操作 复合类操作如 迭代 反复访问元素 遍历完容器中的所有元素 跳转 根据指定的顺序找到当前元素的下一
  • Android——WebView控件访问网页

    目录 一 WebView 1 基本使用 2 最简单的demo 3 注意 二 小练手 1 EditView补充内容 2 案例 一 WebView Webview 是一个基于webkit的引擎 可以解析DOM 元素 展示html页面的控件 我们
  • 前端基础,超全html常用标签大汇总

    标签 整个html文件都会放在html标签里面 标签 表示网页的头部信息 一般是为浏览器提供对应的网站需要的相关信息 浏览器中是不会显示的 比如 标题title 引入css 字符编码等 但是title标题会在浏览器的标题栏显示 标签 里面的
  • 服务器中毒怎么办,如何防御?

    数据中心在为用户提供服务器空间和网络服务时 往往也会为用户提供日常维护服务 用户在服务器运行使用中会突然就发现自己的服务器存在中毒和疑似中毒的现象 那么如何进行中毒行为的排查和清理 为用户提供日常维护服务的过程中经常听到用户抱怨自己使用的服
  • uniapp 选择地址

    uni getLocation OBJECT uni app官网 wx getSetting success res gt if res authSetting scope userLocation wx authorize scope s
  • 【Node】Deepin和Centos 简单快速安装Node和npm和pnpm

    1 deepin 进行安装 安装npm sudo apt install npm 安装node sudo npm install g n 升级node到稳定版 sudo n stable 升级到最新版 sudo n latest 升级npm
  • Databend Cloud 入选中国信通院《云原生产品目录》

    近日 在中国信通院召开的云原生产业大会上 正式发布了 2022 年度首批 云原生产品目录 Databend Cloud 产品成功入选 云原生产品目录 中国信通院为解决云原生用户选型困境 全面拉齐行业认知 推动云原生产业蓬勃发展 而发起 征集
  • pip install 安装路径的修改

    一般我们需要安装第三方库的时候 都是进入cmd中用pip命令来进行安装 安装各类包 但是默认安装路径在C盘 极大占用空间 下面我们就来修改一下默认的安装路径 1 查看pip默认的安装路径 打开命令提示符 win r 输入cmd 输入命令如下
  • 全国计算机二级WPS Office题库(四)

    根据最新考试大纲要求 结合近年来考试真题的重难点进行汇编整理组成的全真模拟试题 考生们可以根据文章进行专项训练 查漏补缺巩固知识点 我们对热点考题和重难点题目都进行了仔细的整理和编辑 相信考生在经过了针对性的刷题联系后 对于考试内容会更加有
  • tensorflow-gpu版本安装教程(过程详细)

    准备工作 在开始安装前 如果你的电脑装过tensorflow 请先把他们卸载干净 包括依赖的包 tensorflow estimator tensorboard tensorflow keras applications keras pre
  • myBatis 常见问题(一)查询结果字段为null

    问题描述 查询认购单详情
  • 使用python爬爬菜价

    第一步我们先导入需要用到的库 from requests html import HTMLSession import pymysql import json 然后打开网站 点击查看更多 点击下一页 发现网页地址栏没有变化 由此可知这是一个
  • rollup函数(分组后对每组数据分别合计)

    需求 sql通过分组查询后 对每组数据进行小计 然后对总的数据总计 rollup的作用 用 ROLLUP 汇总数据 在生成包含小计和合计的报表时 ROLLUP 运算符很有用 例子 SQL gt select deptno job sum s
  • C++红黑树(图文详解)

    原文链接 文章目录 红黑树简介 红黑树的性质 红黑树操作 旋转操作 插入 情况一 情况二 情况三 情况四 情况五 插入总结 删除 情况一 情况二 情况三 情况四 情况五 情况六 删除总结 总结 红黑树简介 红黑树是一种自平衡的二叉查找树 是