红黑树

HashMap详解

爷,独闯天下 提交于 2020-03-11 19:26:50
hashmap的数据结构 Hashmap的底层数据结构是由数组+链表组成的,是线程不安全,允许key和value为null。底层结构数组叫哈希桶,而桶内则是链表,链表中的节点Node存放着实际的元素。 JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。 当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。 针对这种情况,JDK 1.8 中引入了 红黑树(查找时间复杂度为 O(logn))来优化这个问题。 新增的操作:桶的树形化 treeifyBin() 新增的操作: 红黑树中添加元素 putTreeVal() 新增的操作: 红黑树中查找元素 getTreeNode() 新增的操作: 树形结构修剪 split() JDK 1.8 以后哈希表的 添加、删除、查找、扩容方法都增加了一种 节点为 TreeNode 的情况: 添加时,当桶中链表个数超过 8 时会转换成红黑树; 删除、扩容时,如果桶中结构为红黑树,并且树中元素个数太少的话,会进行修剪或者直接还原成链表结构; 查找时即使哈希函数不优,大量元素集中在一个桶中,由于有红黑树结构,性能也不会差。 (图片来自:http:/

图解红黑树

社会主义新天地 提交于 2020-03-10 20:58:14
图解红黑树 一、红黑树的五条规则 红黑树除了符合二叉搜索树的基本规则外,还添加了以下特性: 规则1:节点是红色或黑色的; 规则2:根节点是黑色的; 规则3:每个叶子节点都是黑色的空节点(NIL节点); 规则4:每个红色节点的两个子节点都是黑色的(从每个叶子到根的所有路径上不可能有两个连续的红色节点); 规则5:从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点; 红黑树的相对平衡 前面5条规则的约束确保了以下红黑树的关键特性: 从 根到叶子节点 的 最长路径 ,不会超过 最短路径 的 两倍 ; 结果就是这棵树 基本 是平衡的; 虽然没有做到绝对的平衡,但是可以保证在最坏的情况下,该树依然是高效的; 为什么可以做到 最长路径不超过最短路径的两倍 呢? 性质4 决定了路径上不能有两个相连的红色节点; 所以,最长路径一定是红色节点和黑色节点交替而成的; 由于根节点和叶子节点都是黑色的,最短路径可能都是黑色节点,并且最长路径中一定是黑色节点多于红色节点; 性质5 决定了所有路径上都有相同数目的黑色节点; 这就表明了没有路径能多于其他任何路径两倍长。 二、红黑树的三种变换 插入一个新节点时,有可能树不再平衡,可以通过三种方式的变换使树保持平衡: 变色 ; 左旋转 ; 右旋转 ; 2.1.变色 为了重新符合红黑树的规则,需要把 红色 节点变为 黑色 ,或者把 黑色 节点变为 红色 ;

JDk1.8HashMap的源码分析

久未见 提交于 2020-03-10 20:27:38
JDk1.8HashMap的源码分析 HashMap用数组存放数据(总结) 调用键的hashCode()获得键的哈希值 用哈希值,计算一个下标值 i 新建Entry对象来封装键和值 Entry对象放在 i 位置 空位置,直接放入 有数据,依次用equals()比较是否相等 找到相等的,覆盖值 没有相等的,链表连接在一起 负载率、加载因子到0.75 新建翻倍容量的新数组 所有数据,重新哈希,放入新数组 jdk1.8 链表长度到8,转成红黑树 红黑树数据量减少到6,转回成链表 hashCode() Object的方法 Object中默认实现是使用内存地址,作为哈希值 如果对象作为键,放入HashMap,应该重写hashCode(),使用属性数据,来计算哈希值 HashMap中根据hash值求得index的 // 先用key求得hash值 static final int hash ( Object key ) { // h = key.hashCode() 为第一步 取hashCode值 // h ^ (h >>> 16) 为第二步 高位参与运算 int h ; return ( key == null ) ? 0 : ( h = key . hashCode ( ) ) ^ ( h >>> 16 ) ; } JDK1.8HashMap的put方法源码如下 /** * (1)

HashMap源码分析(jdk12)

房东的猫 提交于 2020-03-10 15:06:41
1. 初始化 ,hashMap初始化容量默认大小为16,默认负载因子为0.75F 一共有3个构造器 无参 带初始化容量 带初始化容量和初始化加载因子 前两个构造器都是调用第三个构造器。如果没有设置初始化容量或负载因子,以默认值创建。值得一提的是: 在调用构造器创建HashMap时不会立即创建容器,(在jdk1.8之后为 Node<K,V>[] table 用于存储键值对)。而是会在你第一次put元素的时候调用resize方法创建。 容器的大小必须为2的倍数。你在设置初始化容器大小时,如果输入的不是2的倍数,那会自动调整为最接近的大于输入值的2的倍数。主要在tableSizeFor这个方法实现。 该方法,先获取 输入数-1 的32位二进制前导零数目(这里-1理解一下就好了,不-1那对于恰好是2的倍数的,会扩大一倍)。-1无符号右移前导零数目位,这样就得到了最接近 输入数 的 2的倍数-1。最后判断n的大小, 如果n=-1表示cap=1,那就设置容量为1; 如果n>0,如果大于最大容量,那就设置为最大容量,否则设置为n+1。 hashMap有最大容量。2^30 链表长度阈值 当长度大于8时,会从链表转化为红黑树。至于为什么设置为8主要是理想状态下,设置合理的HashMap,根据泊松分布计算得到链表长度达到8的概率极低( 0.00000006)

java基础(三)hashMap底层原理

戏子无情 提交于 2020-03-08 17:29:59
HashMap底层原理 hashMap底层原理主要是jdk1.7和1.8以上的区别。 jdk1.7中底层是由数组(也有叫做“位桶”的)+链表实现;jdk1.8中底层是由数组+链表/红黑树实现。 参考学习: https://blog.csdn.net/jswd_50x/article/details/86542240 HashMap面试题 1.谈一下HashMap的特性? 2.谈一下HashMap的底层原理是什么? 3.谈一下hashMap中put是如何实现的? 4.谈一下hashMap中什么时候需要进行扩容,扩容resize()又是如何实现的? 5.谈一下hashMap中get是如何实现的? 6.谈一下HashMap中hash函数是怎么实现的?还有哪些hash函数的实现方式? 7.为什么不直接将key作为哈希值而是与高16位做异或运算? 8.为什么是16?为什么必须是2的幂?如果输入值不是2的幂比如10会怎么样? https://blog.csdn.net/sidihuo/article/details/78489820 https://blog.csdn.net/eaphyy/article/details/84386313 9.谈一下当两个对象的hashCode相等时会怎么样? 10.如果两个键的hashcode相同,你如何获取值对象? 11.

hashmap学习笔记

♀尐吖头ヾ 提交于 2020-03-08 13:21:41
最近开始在阅读一些源码之类的学习,趁着周末,今天详细学习了一些HashMap底层的知识,遂记录下来。有很多理解或者描述不当之处,望请指正。 ## 一、数据底层结构图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190526213014826.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21pYW9wYXMx,size_16,color_FFFFFF,t_70) 首先放一张HashMap底层结构图,由于现在JDK几乎都用8及以上了,因此本文记录的都是基于JDK8的HashMap。 在JDK8以后,HashMap底层采用数组+链表+红黑树的形式来进行存储。 HashMap底层用一个数组来存放节点,节点在数组中的位置是由一个特殊的算法计算出来的(下文会提到)。如果两个节点计算出来的hash值相同,那么就将新的节点以链表的形式,连接在已存在的节点的后面。如果同一位置的节点数超过8个,那么会将链表改成红黑树的形式进行存储。 这样说有点抽象,结合源码一起看吧。 ## 二、HashMap源码解读 首先我们来看HashMap中的基本单位,节点,包括链表节点和红黑树节点。 链表节点: ``` /**

HashMap,TreeMap,WeakHashMap,HashTable

自作多情 提交于 2020-03-08 11:10:02
1,HashMap hashmap数据结构为一个hash表,具体的代码实现就是一个数组,每个数据里面存放一个链表,初始化的时候默认的数组大小为16,负载因子为0.75(这个值可以保证碰撞最低并且空间利用率最高),当元素的个数大于(负载因子*数组长度)的时候,会进行数组扩容,扩大为2倍(所以当内存比较吃紧的时候,可以适当地增加负载因子,当内存很充足的时候,可以减少负载因子)。前面的叙述是针对jdk7及以下版本的,jdk8的hashmap稍稍做了一些改变,就是当数组中的链表达到一定的阈值的时候,这个链表会转化成一颗红黑树,这个优势就很明显了,在红黑树里面查询一个数据可比在链表中查询效率高多了。 2,TreeMap 可以说不论是添加操作,还是查找操作,treeMap的效率都没有hashMap高,因为在操作之前他们都是需要定位的,而hashMap只需要算出hash值就可以找到相应的数组小标,从而定位到相应的位置,而treemap是需要从树的顶端往下寻找,时间复杂度为log(n),那这个treemap的价值是什么呢?别忘了treemap实现了一个接口叫做SortedMap,也就说treemap是一个有序的map,当你需要按顺序输出一组数据的时候就可以选择treemap了。 treemap的内部数据结构是红黑树(R-B Tree)

TreeMap分析

帅比萌擦擦* 提交于 2020-03-08 06:15:22
TreeMap分析 一、直接使用红黑树进行数据存储 HashMap 是使用数组+红黑树的方式进行存储 红黑树算法这里不做介绍(建议看视频进行学习) 二、为什么TreeMap是有序的 实现步骤: 内置比较器 private final Comparator < ? super K > comparator ; //比较器定义,一经赋值,不能修改 public TreeMap ( ) { // 无参创建对象时,比较器为空 comparator = null ; } public TreeMap ( Comparator < ? super K > comparator ) { //传入比较器,然后创建map this . comparator = comparator ; } 放值时进行排序 此处调用compare()方法,或者强制转换,将键进行比较,然后按照红黑树的数据结构进行存储 public V put ( K key , V value ) { Entry < K , V > t = root ; if ( t == null ) { compare ( key , key ) ; // 调用compare()方法 root = new Entry < > ( key , value , null ) ; size = 1 ; modCount ++ ; return null

mysql索引数据结构

你。 提交于 2020-03-07 07:00:55
什么是索引?索引就是排好序的数据结构,可以帮助我们快速的查找到数据 推荐一个网站,可以演示各种数据结构:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html --------------------------------------------------------------- 图解几种数据结构: 二叉树:如果数据是单边增长的情况 那么出现的就是和链表一样的数据结构了,树高度大 红黑树:在二叉树的基础上多了树平衡,也叫二叉平衡树,不像二叉树那样极端的情况会往一个方向发展。 同样我们查找6,在二叉树中我们需要经过6个节点才能找到(1-2-3-4-5-6),红黑树中我们只需要3个节点(2-4-6),但是mysql索引的数据结构并不是红黑树,因为如果数据量大了之后,树的高度就会很大。 B树:在红黑树的基础上,每个节点可以存放多个数据 这个时候我们查找6 只需要2个节点就可以了,而且树的高度也比红黑树矮。 B+树:B树的变种 你会发现非叶子节点是会重复的,就像上面4,在叶子节点上面也出现了4,这是为什么呢?因为它需要在叶子上面存放数据。那又是怎么存放数据的呢? --------------------------------------------------------------- mysql索引为什么用B

红黑树基础与代码(一)

…衆ロ難τιáo~ 提交于 2020-03-05 23:59:38
一. 定义和性质 红黑树是一种含有红黑结点并能自平衡的二叉查找树,红黑树并不是一个完美平衡二叉查找树,红黑树的左子树和右子树的黑结点的层数是相等的,也即任意一个结点到到每个叶子结点的路径都包含数量相同的黑结点。所以我们叫红黑树这种平衡为黑色完美平衡. 它必须满足下面性质: 性质1:每个节点要么是黑色,要么是红色 性质2:根节点是黑色 性质3:每个叶子节点(NIL)是黑色 性质4:每个红色结点的两个子结点一定都是黑色 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。(如果一个结点存在黑子结点,那么该结点肯定有两个子结点) 二. 为何很多应用选择红黑树作为平衡树的实现 插入或删除节点时,平衡二叉树为了维持平衡,需要对其进行平衡纠正,这需要较大的开销。 例如,有种AVL树, 是高度平衡树,结构比红黑树更加平衡,这也表示其增删节点时也更容易失衡,失衡就需要纠正,增删节点时开销会比红黑树大。但不可否认的是AVL树搜索的效率是非常稳定的。 因此在大量数据需要插入或者删除时,AVL需要平衡调整的频率会更高。因此,红黑树在需要大量插入和删除节点的场景下,效率更高。自然,由于AVL高度平衡,因此AVL的Search效率略高。 红黑树不是高度平衡树,但平衡的效果已经很好了。所以,可以认为红黑树是一种折中的选择,其综合性能较好。 三.红黑树涉及的基本操作 在进行红黑树基本操作前