4

HashMap与红黑树学习总结

 3 years ago
source link: https://szuwest.github.io/hashmap-redblacktree.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

HashMap与红黑树学习总结

2021-06-11

HashMap与红黑树学习总结

HashMap解读(JDK1.8)

带着问题去看代码:

  • 里面是怎么存储数据的(使用到的数据结构)?
  • 怎么计算哈希值,怎么解决哈希冲突?
  • 初始化容量是多少?不断加入数据时,如何进行扩容? 扩容后数据的存储位置是怎么样的
  • 查找数据的时间复杂度
  • 为什么要用红黑树?这里的红黑树实现有什么特点

HashMap特性

  • hash算法效率好,高低位异或
  • 数组⻓度是2的n次幂,采用&运算来代替模运算
  • 采用modCount来实现failFast
  • 为LinkHashMap预留方法实现
  • 效率高,用链接来解决哈希冲突。插入数据时链接过长转为红黑树,删除数据时红黑树高度变低了转化为链表。
  • 数组扩容时链表会一分为二,红黑树也一样,红黑树甚至会转化为链表
  • 线程不安全。
  • 源代码里语句很简洁,经常一行代码包括N多赋值与判断,变量命名过 于简单

Hashtable是线程安全的,它是经典的哈希表实现(数组+ 链表),没有红黑树。同样是哈希表,HashMap跟Hashtable的实现天差地别,可以看出HashMap追求极致的性能,而Hashtable是线程安全的,有加锁操作,性能不会好,所以就采用了最简单的实现

红黑树的由来

要完全理解红黑树,必须把下面这些概念都完全搞清楚。

树》二叉树》二叉排序树》自平衡二叉树》2-3树和2-3-4树 (B树)》红黑树

  • 树,只有一个父节点,有若干个子节点
  • 二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),又称 二叉搜索树。任意一个节点,它的值比它左孩子的值要大,比它右孩子的值要小
  • 平衡二叉树, 又叫AVL树(它的名字是它的发明者们的缩写),是一个二叉搜索树,它的任意一个节点的左右孩子高度差不超过1

B树

  • B树是一种平衡的多路搜索树
  • 1 个节点可以存储超过 2 个元素(多个元素从小到大排 列)、可以拥有超过 2 个子节点。一个节点存储的元素个 数是它的儿子个数减1
  • 拥有二叉搜索树的一些性质
  • 绝对平衡:每个节点的所有子树高度一致
  • 2-3树和2-3-4树是B树的特例,2-3树是最简单的B树

2-3树、2-3-4树与红黑树

  • 2-3树、2-3-4树虽然能保持平衡,但是计算机不好实现
  • 红黑树(Red Black Tree) 是一种自平衡二叉查找树。红黑树是近似平衡 的二叉树,左右子树高差有可能大于 1,但是他的平均性能要好于AVL树
  • 红黑树对应的理论模型可以是2-3树,也可以是2-3-4树。普遍红黑树的实 现是采用2-3-4树模型

因为2-3(2-3-4)树不好实现,所有把它当做一种模型,采用二叉树的方式(代码较好实现)来实现这个模型。这个就是红黑树。这就是红黑树的由来(当然这是我的猜测)。

红黑树怎么实现这个模型的呢?2-3树一个节点能存两个值,二叉树只能存一个值,所以要把2-3树拆分成两个节点:一个红色,一个黑色。红色代码它可以向上跟它的父节点合并成一个节点,对应的就是2-3树里有两个值元素的节点。这是就是基础。剩下就的就是定各种规则来让红黑树符合2-3树的特征。也就有了红黑树的5个规则。

一张重要的图:2-3-4树与红黑树

2-3-4树与红黑树

红黑树5个特性

  • 1) 节点是红色或黑色
  • 2) 根节点是黑色
  • 3) 空节点(NIL节点,有些文章也叫叶子节点)是黑色的
  • 4) 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所 有路径上不能有两个连续的红色节点)
  • 5 )从任一节点到其每个叶子的路径上包含的黑色节点数量都相同
  • 附加特性:插入的节点设为红色

红黑树5个特性(Why)

  • 1)红色在2-3-4树模型中代表要跟父节点合并成一个节点
  • 2)根节点没有父节点,没有办法合并,所以根节点不能是红色的
  • 3)由于根据特性1任何节点都有颜色,空节点也应该有颜色,被定义为 黑色在代码实现上比较方便(看TreeMap的实现就很明显)。
  • 第4和第5特性要结合一起来看,第5点规定从根到叶子节点的路径上只 算黑色节点数,而第4点规定红色节点不能连续,这两点保证了红黑树 的左右两个子树的高度差不会太大。这也是它性能不错的原因。
  • 附加特性:在代码实现红黑树的时候,插入的代码设为红色,红色的节 点不影响平衡(第5点特性),这样可以减少对树的旋转操作

如果你理解了上面的why,就不会再怕记不住它的5条规则了。

节点插入与删除涉及操作

为了保持红黑树的平衡(即符合红黑树的5个特性),节点 插入或删除需要做一些操作: 1. 变色 2. 左旋转或右旋转,或者将两种旋转组合 3. 涉及到的节点:当前插入的节点,兄弟节点,当前节点的父节点,爷爷节点,叔叔节点

插入总结

先看父,再看叔叔,然后看爷爷。若爷孙三代不在直线, 先父转,再变色, 再爷转。 这一句话概括了几乎所有情况。

删除总结

要想理解红黑树的删除,必须先理解二叉排序树的删除操作。

二叉查找树的结点无非是有两个子结点,有一个子结点和叶子结 点三种,其中有两个子结点的 M 结点的删除逻辑是: 首先寻找 M 结点左子树最大或右子树最小的结点 X 然后把 X 结点的值复制到 M 结点 * 最后删除 X 结点,而这个结点要么是叶子结点,要么就只有一个 孩子

所以,删除任一结点的问题就简化成了: 删除一个最多只有一个孩 子的结点的情况(要么没有孩子,要么只有一个孩子)

红黑树删除节点要领

  • 删除红色叶子节点不影响平衡
  • 删除黑色节点会影响树的平衡,所以想办法从孩子节点, 或者兄弟节点,或者父节点借一个红色节点过来,并把它 变黑,这样树就恢复平衡了。
  • 如果没办法借到红色节点,只能将平衡交给父节点处理,递归向上调整。

红黑树的实现

  • HashMap中的红黑树特性:代码复杂,成员变量多,包含 双向链表结构,空间冗余
  • TreeMap: 按照2-3-4树模型实现,代码可读性强
  • 重复造轮子:手动实现一个红黑树

TreeMap是学习红黑树的最佳源码,没有之一。HashMap里的红黑树相当复杂,在删除一个具有两个孩子节点的地方不太一样,它是直接交换两个节点的,这点开始看得我头疼。

对网上红黑树参考资料吐槽

  • 没有把红黑树规则3说清楚(说叶子节点是黑色的很容易让 人误解)
  • 大部分没有讲红黑树怎么来的,有什么用
  • 没有讲解红黑树的删除操作(删除比插入更复杂)
  • 对代码的解读只是简单的代码注释,估计作者也是半懂不 懂的

我写了个《HashMap、红黑树与B树》的PPT给我们团队做技术分享。该PPT已转为PDF传到了GitHub,感兴趣的可以看看。地址在这

  • 红黑树最差情况是怎样的?
  • 基于2-3树和基于2-3-4树模型实现的红黑树有什么区别?
  • HashMap里的红黑树数据结构什么搞那么复杂?(包含双向链表, 空间冗余)

如果你觉得这篇文章有用,请打赏小钱喝杯咖啡^_^ 打赏

Category: 技术

Tagged: HashMap 红黑树

Comments


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK