红黑树

HashMap源码分析

☆樱花仙子☆ 提交于 2019-12-15 12:31:19
HashMap 文章目录 HashMap 基本属性 构造函数 无参构造 HashMap(int,float)型构造函数 HashMap(int)型构造函数 `HashMap(Map)型构造函数` HashMap常用方法 put方法 hash方法 putVal方法 寻找key对应的映射关系: treeifyBin方法 treeify方法 get方法 resize方法 hashmap的实现原理:首先有一个每个元素都是链表(可能表述不准确)的数组,当添加一个元素时,就首先计算元素key的hash值,以此确定插入数组中的位置,但是可能存在同一hash值的元素已经被放在数组同一位置了,这时就添加到同一hash值的元素的后面,他们在数组的同一位置,但是形成了链表,同一各链表上的Hash值是相同的,所以说数组存放的是链表。而当链表长度太长时,链表就转换为红黑树,这样大大提高了查找的效率。 当链表数组的容量超过初始容量的0.75时,再散列将链表数组扩大2倍,把原链表数组的搬移到新的数组中 当table中的元素足够多时,发生冲突的概率就会大大增加,冲突的增多会导致每个桶中的元素个数变多,这样的话会使得查找元素效率变得低下,当同一个桶中元素个数达到8时,桶中的元素结构将转换为红黑树。 基本属性 public class HashMap < K , V > extends AbstractMap < K

红黑树

淺唱寂寞╮ 提交于 2019-12-15 12:28:56
2-3树 定义:每个节点有两个或三个节点 分类: 2-节点:一个节点有1个元素,且有两个孩子 3-节点:一个节点有2个元素,且有三个孩子 基本性质 满足二分搜索树的基本性质 一个节点可以存放一个或两个元素 2-3树是一颗绝对平衡的树(左右子树的高度相等) 2-3树元素的添加 添加元素的规则 新添加的元素不会添加到空节点上,而是添加到最后搜索到的叶子结点,再与之融合在一起 如果新加入的元素与2-节点融合,直接融合,形成3-节点 如果新加入的元素与3-节点融合,先融合形成4-节点,再进行拆分成每个节点有两个孩子的三个节点。 不能超过3-节点,即一个节点不能有超过三个孩子 添加的元素依次为 42,37,12,18,6,11,5 总结: 12为根节点不需要再向上与父节点融合,本次的添加操作结束 每一步的操作都体现了2-3树的绝对平衡性 一般流程:插入-融合-拆分 红黑树与2-3树的等价性 红黑树的基本性质 每个节点要么是红色要么是黑色 根节点是黑色 每一个叶子节点(最后的空节点)是黑色的 如果一个节点为红色,其孩子为黑色 从任意一个节点到叶子节点,经过的黑色节点的数量是一样的 红黑树的红色节点对应就是2-3树中3-节点的左结点 红黑树是“黑平衡”的二叉树,左右子树的黑色节点的高度差保持绝对的平衡。但不是平衡二叉树。最大高度h=2*log^n 经过log^n级别的黑色节点

ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)

☆樱花仙子☆ 提交于 2019-12-15 07:14:37
哈希表 1.介绍 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。 哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。 2.链式哈希表 链式哈希表从根本上说是由一组链表构成。每个链表都可以看做是一个“桶”,我们将所有的元素通过散列的方式放到具体的不同的桶中。插入元素时,首先将其键传入一个哈希函数(该过程称为哈希键),函数通过散列的方式告知元素属于哪个“桶”,然后在相应的链表头插入元素。查找或删除元素时,用同们的方式先找到元素的“桶”,然后遍历相应的链表,直到发现我们想要的元素。因为每个“桶”都是一个链表,所以链式哈希表并不限制包含元素的个数。然而,如果表变得太大,它的性能将会降低。 3.应用场景 我们熟知的缓存技术(比如redis、memcached)的核心其实就是在内存中维护一张巨大的哈希表,还有大家熟知的HashMap、CurrentHashMap等的应用。 ConcurrentHashMap与HashMap等的区别 1.HashMap 我们知道HashMap是线程不安全的,在多线程环境下,使用Hashmap进行put操作会引起死循环

java之ConcurrentHashMap在jdk1.7和jdk1.8中的不同

你说的曾经没有我的故事 提交于 2019-12-14 19:53:21
1.底层结构发生变化 jdk 1.7底层结构是:数组(Segment)+ 链表(HashEntry节点)组成 使用分段锁技术,将整个数据结构分段(默认为16段)进行存储,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。如下图是ConcurrentHashMap的内部结构图: 从上面的结构我们可以了解到,ConcurrentHashMap定位一个元素的过程需要进行两次Hash操作。 第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部。 jdk1.8底层结构是:Node数组+链表 / 红黑树 其实就是JDK 1.8中的hashMap结构 Node数组使用来存放树或者链表的头结点,当一个链表中的数量到达一个数目时,会使查询速率降低,所以到达一定阈值时,会将一个链表转换为一个红黑二叉树,通告查询的速率。 相互转化跟JDK1.8版本的hashMap保持一致 2、代码层实现 (1)、put方法 步骤: 1、检查Key或者Value是否为null,如果是null抛出空指针异常 2、得到Kye的hash值 3、如果Node数组是空的,此时才初始化 initTable(), 4、如果找的对应的下标的位置为空,直接new一个Node节点并放入, break; 5

数据结构(树)

心已入冬 提交于 2019-12-14 17:39:14
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 树: 树是 n个结点 的有限集合,有且仅有一个 根结点, 其余结点可分为m个根结点的 子树。 度: 指的是一个节点拥有子节点的个数。如二叉树的节点的最大度为2。 高度/深度: 数的层数,根节点为第一层,依次类推。 叶子节点: 度为0的节点,即没有子节点的节点。 二叉树: 在二叉树中每个节点最多有两个子节点,一般称为左子节点和右子节点(或左孩子和右孩子) 前序遍历(前根遍历): 根 ——>左——>右 中序遍历(中根遍历):左——> 根 ——>右 后序遍历(后根遍历):左——>右——> 根 满二叉树: 在一棵二叉树中,如果所有分支结点都有左孩子和右孩子结点,并且叶子结点都集中在二叉树的最下层,这样的树叫做满二叉树 高度为h,由2^h-1个节点构成的二叉树。 完全二叉树: 二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边。 二叉查找树(BST): 又称二叉排序树,亦称二叉搜索树(Binary Search Tree)。 定义: 一棵空树,或者是具有下列性质的二叉树: 1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; 2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; 3)左

深入浅出HashMap的设计与优化

空扰寡人 提交于 2019-12-13 00:50:09
一:常用的数据结构 众所周知, ArrayList 是基于数组的数据结构实现的,LinkedList 是基于链表的数据结构实现的,而 HashMap 是基于哈希表的数据结构实现的。我们不妨一起来温习下常用的数据结构。 数组: 采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为 O(1),但在数组中间以及头部插入数据时,需要复制移动后面的元素。 链表: 一种在物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素)组成,结点可以在运行时动态生成。每个结点都包含“存储数据单元的数据域”和“存储下一个结点地址的指针域”这两个部分。由于链表不用必须按顺序存储,所以链表在插入的时候可以达到 O(1) 的复杂度,但查找一个结点或者访问特定编号的结点需要 O(n) 的时间。 哈希表: 根据关键码值(Key value)直接进行访问的数据结构。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数,存放记录的数组就叫做哈希表。 树: 由 n(n≥1)个有限结点组成的一个具有层次关系的集合,就像是一棵倒挂的树。 二:HashMap 的实现结构 了解完数据结构后,我们再来看下 HashMap 的实现结构。作为最常用的 Map 类,它是基于哈希表实现的,继承了 AbstractMap

ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)

人走茶凉 提交于 2019-12-12 22:51:24
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 哈希表 1.介绍 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。 哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。 2.链式哈希表 链式哈希表从根本上说是由一组链表构成。每个链表都可以看做是一个“桶”,我们将所有的元素通过散列的方式放到具体的不同的桶中。插入元素时,首先将其键传入一个哈希函数(该过程称为哈希键),函数通过散列的方式告知元素属于哪个“桶”,然后在相应的链表头插入元素。查找或删除元素时,用同们的方式先找到元素的“桶”,然后遍历相应的链表,直到发现我们想要的元素。因为每个“桶”都是一个链表,所以链式哈希表并不限制包含元素的个数。然而,如果表变得太大,它的性能将会降低。 3.应用场景 我们熟知的缓存技术(比如redis、memcached)的核心其实就是在内存中维护一张巨大的哈希表,还有大家熟知的HashMap、CurrentHashMap等的应用。 ConcurrentHashMap与HashMap等的区别 1.HashMap 我们知道HashMap是线程不安全的

HashMap底层源码

China☆狼群 提交于 2019-12-12 12:39:15
​ 这里是修真院后端小课堂,每篇分享文从 本篇分享的是:【HashMap 】 (1)背景介绍: 不讲HashMap的使用方法,看一看底层的源码是什么? 思考:HashMap使用key,·value进行存储,使用的数据结构是什么? 我们知道数组和链表两种数据结构 数组: 优点:查询速度快 缺点:增加和删除慢 链表: 优点:增加和删除快 缺点:查询速度慢 那我们可不可以将两者的优点结合一下,达到查询、增加、删除效率都非常快呢? 所以我们猜测一下,HashMap能否源码底层数据结构是采用的链表+数组的形式呢? (2)知识剖析: 1.HashMap数据底层具体存储的是什么? Java是一门面向对象开发的语言,可以把所有东西可以看做是对象。 通过查看源码可知:map里面的key和value都保存在了这个Node对象里面。 class Node<K,V>{ private K key; //用来定位数组索引位置 private V value; private Node<K,V> next; //链表的下一个node } 2.数组怎么表示? transient Node< K,V>[] table; 每个列表被称为桶,即哈希桶数组,是一个Node的数组。 HashMap使用哈希表进行存储。怎样得到表中对象的索引位置? key.hashCode( )----->hashCode-----

HashMap源码学习

…衆ロ難τιáo~ 提交于 2019-12-12 08:49:47
HashMap 简介 HashMap 主要用来存放键值对,它基于哈希表的Map接口实现,是常用的Java集合之一。 JDK1.8 之前 HashMap 由 数组+链表 组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突).JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树),以减少搜索时间,具体可以参考 treeifyBin 方法。 底层数据结构分析 JDK1.8之前 JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列 。 HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。 所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞 JDK 1

用c++实现红黑树的插入、删除、遍历操作

自闭症网瘾萝莉.ら 提交于 2019-12-10 10:00:44
红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。 红黑树是满足下面红黑性质的二叉搜索树: 每个节点,不是红色就是黑色的; 根节点是黑色的; 如果一个节点是红色的,则它的两个子节点是黑色的; 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点; 每个叶子节点都是黑色的(这里的叶子节点是指的空节点) 思考:为什么满足上面的颜色约束性质,红黑树能保证最长路径不超过最短路径的两倍? 如图:所能增加的红节点数最多和黑节点数目一样多,故红黑树能保证最长路径不超过最短路径的两倍。 一、判断是否是红黑树: //判断是否是红黑树 bool isRBTree() { int BlackNodeNum = 0; int curBlackNodeNum = 0; Node* cur = _root; while (cur) { if (cur->_col == BLACK) { BlackNodeNum++; } cur = cur->_left; } return _isRBTree(_root, BlackNodeNum, curBlackNodeNum); } bool _isRBTree(Node* root, int