哈希表、红黑树

哈希表

哈希表的底层实现

哈希表的底层实际上是基于数组来存储的。

当插入键值对时,并不是直接插入该数组中,而是通过对进行Hash运算得到Hash值,

然后使用哈希值和数组长度来确定键值对存储的位置(索引),得到在数组中的位置后分两种情况:

  • 如果索引位置为空:直接插入键值对。
  • 如果索引位置不为空
    • 遍历链表(或者红黑树)以检查是否有相同的键。如果有,更新值。
    • 如果没有相同的键,将新节点添加到链表末尾或树中。

取值时,先对指定的键求Hash值,再和容量取模得到底层数组中对应的位置,如果指定的键值与存贮的键相匹配,则返回该键值对,如果不匹配,则表示哈希表中没有对应的键值对。这样做的好处是在查找、插入、删除等操作可以做到O(1),最坏的情况是O(n),当然这种是最极端的情况,极少遇到。

不管哪门语言,实现一个HashMap的过程均可分为三大步骤:

  • 实现一个Hash函数
  • 合理解决Hash冲突
  • 实现HashMap的操作方法

Hash函数

Hash函数非常重要,一个好的Hash函数不仅性能优越,而且还会让存储于底层数组中的值分配的更加均匀,减少冲突发生。之所以是减少冲突,是因为取Hash的过程,实际上是将输入键(定义域)映射到一个非常小的空间中,所以冲突是无法避免的,能做的只是减少Hash碰撞发生的概率。具体实现时,哈希函数算法可能不同,在Rust及很多语言的实现中,默认选择SipHash哈希算法。

影响Hash碰撞(冲突)发生的除了Hash函数本身意外,底层数组容量也是一个重要原因。很明显,极端情况下如果数组容量为1,哪必然发生碰撞,如果数组容量无限大,哪碰撞的概率非常之低。所以,哈希碰撞还取决于负载因子。负载因子是存储的键值对数目与数组容量的比值,比如数组容量100,当前存贮了90个键值对,负载因子为0.9。负载因子决定了哈希表什么时候扩容,如果负载因子的值太大,说明存储的键值对接近容量,增加碰撞的风险,如果值太小,则浪费空间。

所以,既然冲突无法避免,就必须要有解决Hash冲突的机制方法。

处理哈希冲突的几种方法

主要有四类处理冲突的方法:

  • 外部拉链法(常用)
  • 开放定址法(常用)
  • 公共溢出区(不常用)
  • 再Hash法(不常用)
外部链表法

当发生哈希冲突时,会将新的元素存入计算好的索引值位置,将旧元素挂在新元素的下面(Node链表)。 

开放地址法

发生哈希冲突时,新的元素会继续寻找下一块未被占用的索引位置,并在该位置存放。

哈希表的优缺点

优点:

  • 无论数据有多少,处理起来都特别的快
  • 能够快速的进行增删改查

缺点:

  • 哈希表中的元素没有顺序
  • 哈希表中的元素不可以重复

哈希表什么时候转化为红黑树?

Hash冲突解决办法:HashMap在1.8之前采用数组 + 链表组合作为底层数据结构。在JDK1.8版本中,为了对HashMap做进一步优化,我们引入了红黑树。当链表长度太长(默认超过8)时,链表就转换为红黑树。我们可以利用红黑树快速增删改查的特点,提高HashMap的性能。当红黑树结点个数少于8个的时候,又会将红黑树转化为链表。因为在数据量较小的情况下,红黑树要维护平衡,比起链表来,性能上的优势并不明显。 

红黑树

红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:

  • 每个节点不是红色就是黑色
  • 根节点为黑色
  • 每个红色结点的两个子结点一定都是黑色
  • 任意一结点到每个叶子结点的路径都包含数量相同的黑结点

从性质4又可以推出:

  • 性质4.1:如果一个结点存在黑子结点,那么该结点肯定有两个子结点

根据上述规则,新增节点必须为红;新增节点父结点必须是黑。当不能满足时,就需要进行调整颜色并旋转。

 红黑树的变换:(插入节点默认为红色)
**改变颜色、左旋、右旋:**红黑树总是通过旋转和变色达到自平衡

  • 左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。
  • 右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。
  • 变色:结点的颜色由红变黑或由黑变红。

 例如:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值