红黑树

hashmap原理

試著忘記壹切 提交于 2019-12-10 08:08:25
1.hashmap结构(jdk1.8) 结构:hashmap采用数组+链表+红黑树的结构, 数组用查询快的特点,但是插入数据慢,链表有插入快的特点,但是查询慢,所以hashmap结合两者,而红黑树是为了链表过长影响查询速度,将链表转化为红黑树. 源码: //hashmap默认初始化容量 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4 ; // aka 16 //最大容量 static final int MAXIMUM_CAPACITY = 1 << 30 ; //默认填充因子 static final float DEFAULT_LOAD_FACTOR = 0.75f ; //当大于时将链表转化为红黑树 static final int TREEIFY_THRESHOLD = 8 ; //当小于时,将树转化为链表 static final int UNTREEIFY_THRESHOLD = 6 ; //当table个数大于等于时才能转化为红黑树 static final int MIN_TREEIFY_CAPACITY = 64 ; //包含key-value个数 transient int size ; //hashmap被修改次数 transient int modCount ; //要调整大小的下一个大小值(容量

深入分析 JDK8 中 HashMap 的原理、实现和优化

久未见 提交于 2019-12-10 05:09:16
HashMap 可以说是使用频率最高的处理键值映射的数据结构,它不保证插入顺序,允许插入 null 的键和值。本文采用 JDK8 中的源码,深入分析 HashMap 的原理、实现和优化。首发于微信公众号 顿悟源码 . 1. 基本结构 HashMap 基于散列表实现,使用 拉链法 处理碰撞,在 JDK8 中,当链表长度大于 8 时转为 红黑树 存储,基本结构如下: HashMap 有一个 Node<K,V>[] table 字段,即哈希桶数组,数组元素是 Node 对象,结构定义如下: static class Node<K,V> implements Map.Entry<K,V> { final int hash; // 用于计算数组索引 final K key; V value; Node<K,V> next; // 后继节点,下一个 Node Node(int hash, K key, V value, Node<K,V> next) { ... } ... } 哈希桶数组会在首次使用时初始化,默认大小是 16,并根据需要调整大小,且长度总是 2 的次幂。如果构造函数设置的初始容量不是 2 的次幂,那么使用以下方法返回一个 大于且最靠近 它的 2 的次幂的值: static final int tableSizeFor(int cap) { int n = cap - 1; n

数据结构与算法(十)---跳表的实现

余生长醉 提交于 2019-12-09 22:40:46
一、概述 什么是跳表 跳表怎么实现 二、跳表 1. 跳表的定义和实现意义 我们知道二分查找法的前提是有序数组,那么有没有类似的让链表也证婚词类似"二分"查找的算法,那就是 跳表 了:它支持快速的插入、删除、查找操作,实现方式没有红黑树那么复杂,甚至可以代替它。Redis的有序集合就是使用跳表实现的, 链表的随机访问数据的时间复杂度是O(n),我们在链表的基础上,每两个结点提取一个结点到上一级,我们把抽出来的那一级叫作 索引 或 索引层 。图中的 down 表示 down 指针,指向下一级结点。 假如我们要差早16这个元素,我们通过第一级索引进行遍历,当到达13是,发现下一索引元素的值为17,那么16就应该在13和17之间,然后从索引层的13利用down指针,查找到原始链表的13,开始往后遍历得到需要查找的元素,原来需要对遍历10个,现在只需要6个节点;效率提高了;**如果在第一级索引上,在提取一层索引,会怎样呢? 这里直接查找1-64个元素,体验下效率: 查找效率从62次到了11次,这就是跳表。 2. 跳表的时间复杂度 普通链表的时间复杂度是O(N),怎么计算跳表的时间复杂度呢? 每两个结点会抽出一个结点作为上一级索引的结点,那第一级索引的结点个数大约就是 n/2,第二级索引的结点个数大约就是 n/4,第三级索引的结点个数大约就是 n/8,依次类推,也就是说,第 k

集合相关

假如想象 提交于 2019-12-09 21:48:52
集合笔记 集合架构 Collection(接口): API: 遍历方式: Set(接口): HashSet: HashSet研究的两个问题: LinkedHashSet: TreeSet: TreeSet的排序: List(接口): ArrayList: 遍历方式 LinkedList: 遍历方式:同ArrayList(略) LinkedList和ArrayList的区别 Vector:(淘汰) 遍历方式:同ArrayList(略) 总结: map(接口): HashMap: LinkedHashMap: HashTable: TreeMap: IdentityHashMap: ConcurrentHashMap: Properties: 集合工具类 Collections工具类: 集合架构 Collection(接口): 所有单例集合的父类Collection集合的功能所有单例集合都可以直接使用; API: public boolean add(E e): 把给定的对象添加到当前集合中 。 public void clear() :清空集合中所有的元素。 public boolean remove(E e): 把给定的对象在当前集合中删除。 public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。 public boolean

百度实习生一面与二面、用友实习生一面(Java开发)

时光毁灭记忆、已成空白 提交于 2019-12-09 17:44:47
百度一面: 电话面试,问的东西比较广,时长34分59秒 1、自我介绍 2、介绍一下项目 3、知识点的连环攻击,问到你不会为止 GC回收算法 主要有计数器算法和可达性算法 计数器算法:即对象被引用 为其加一 ,未被引用,为其减一 ,如果计数器数字为0,即可将对象GC回收 可达性算法(root):可达性算法是根据有向图的方式进行对象间关系的连接的,如果一个对象并没有被root进行有向图走向连接到的话,这个就可以进行GC回收 如果相对一个对象进行回收,也可以手动调用System.gc()的方法 标记清除、标记整理、复制、分代 标记清除:就是将要被回收的对象标记出来,然后进行清除,但是这样会造成很多的,内存碎片 标记整理:就是同样将要被回收的对象标记出来,但是进行清除时,会将 后面的对象进行移动,减少了内存碎片的产生,但是会造成资源的浪费 复制:将内存区域分为了左右两个区域,将不需要回收的对象复制到另一边,但是这种情况会让我们实际能够进行应用的内存区域缩短了一半 分代:主要是将内存区域分为新生代和老年代,新生代包括eden和from suvior和to suvior区 比例时8:1:1,主要使用的是复制算法 老年代中存放的是在每一次换区都会为他们进行+1,好像+到6就可以被存放到老年代,然后老年代使用的就是标记整理算法了,可能也是在老年代的元素不会轻易的就被删除

看了这篇文章,再也不怕关于树的面试题了

拜拜、爱过 提交于 2019-12-09 14:50:08
基础知识就像是一座大楼的地基,它决定了我们技术的高度 在面试中,关于树的问题是很多的,例如简单点的会问你关于树的前中后序的遍历顺序是怎样的?难点会让你手写关于树的算法题,又或是在Java后端面试中也会涉及到一些树的知识,例如在 HashMap 中产生哈希冲突生成的链表到一定条件下为什么要转成红黑树?,为什么要用红黑树而不用B+树呢?在Mysql中索引的存储为什么用B+树而不用其他树等等。其实这些东西我们在日常开发过程中都会用到,其实每个程序员都不甘心每天工作只是 CRUD ,那么这些数据结构其实就是内功,我们学会了它在日常工作分析问题,选用什么集合,排序怎么排,这些问题中我们会多一些选择。 什么是树 树(英语:tree)是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 再完备的定义也没有图直观,我们先来看一下图(这里借用数据结构与算法作者王争老师的图,下面看到类似风格的图都是如此)。 我们可以看到这里的树和我们现实生活的树是十分相像的,其中每个元素我们称之为节点,而用直线相连的关系我们称之为父子关系。那么什么才能称之为树呢? 每个节点都只有有限个子节点或无子节点 没有父节点的节点称为根节点

数据结构 树(下)

独自空忆成欢 提交于 2019-12-08 05:02:33
数据结构 树(下) 一、概述    AVL树、伸展树、红黑树搜索树算法保证最坏情况或者一系列操作情况下,搜索、插入和删除的操作的时间复杂度是 O(logn) 。本文 主要内容包含:平衡搜索树中的AVL树、伸展树、(2,4)树、红黑树 和(a,b)树、B树等实际运用的树数据结构。 二叉搜索树的删除 二、AVL树 1、基本知识 1、AVL树是维持对数 O(logn) 的高度的特殊二叉搜索树。“高度”指根节点到叶子节点最长路径上的节点的数量。“None”的孩子的高度是0,叶子节点的高度是1,父节点是叶子节点的高度加1 2、AVL树具有 高度平衡属性:对于树T的每个位置P,P的孩子的高度最多相差 1。AVL树子树也是一颗AVL树! 3、一个高度为h(h≥3)的拥有最少节点的AVL树,必须有两颗子树:一颗高度 h-1,另一颗高度为 h-2:n(h)=1+n(h-1)+n(h-2) h≥3 (n(1)=1、n(2)=2) 4、AVL树的高度h和节点总数n的关系: h < 2log n +2 5、AVL树平衡因子是指位置p的两颗子树高度差 (左树减右树/右树减左树) ,平衡因子 的绝对值 不大于1。 2、更新操作 1、插入,AVL树在叶子节点产生一个新的节点插入新节点p,导致p的祖先节点不满足高度平衡属性,通过trinode重组,两次“旋转”重建树T,使其满足AVL树的高度平衡属性 2、删除

手写一棵红黑树

懵懂的女人 提交于 2019-12-08 04:19:03
笔者博客地址: https://charpty.com 我记得面试的时候,经常问问别人 hashmap 实现,说着说着就免不了讲讲红黑树,平常都是用现成的,考察别人红黑树也只是看下是否喜欢专研、有学习劲。 有一次有个同学告诉我他讲不清楚但是可以写一下,很惭愧,全忘了,一下子让我写一个,伪代码都够呛了,跑起来更不行。 我给自己想了个简单的记法,父红叔红就变色,父红叔黑靠旋转,删黑两孩很麻烦,叔黑孩最很简单。 – 红黑树 红黑树是AVL树的进一步加强,正是二叉平衡查找树有问题才引出了红黑树,和典型数据结构一样,在适当的场景使用红黑树可以很大程度的提高性能。 红黑树首先是一棵二叉查找树,节点的左孩子都比节点小,节点的右孩子都比节点大,与AVL平衡树期望带到的效果一样,都想左右子树的深度相差不要太大,尽量平衡,以便提供平均查找效率。 先记住一下红黑树的以下几个特性,不用急着回忆,后面代码写着写着自然就想起来了。 节点要么是黑色要么是红色,根节点固定为黑色,叶子节点也固定为黑色(不关键特性3合一) 子节点和父节点不能同时为红色,子父不连红。 从一个节点到其通向到所有叶子节点路径中,所包含的黑色节点数目相同。保证树平衡的关键。 前面两点都很好理解,第2点是用来修改树时判断树是否还是红黑树的主要条件。 第3点不直观,但是可以这样想,插入或删除一个节点,影响的只是它周边那几个节点

Java集合类--HashMap

青春壹個敷衍的年華 提交于 2019-12-06 16:53:46
一、HashMap基本源码实现 1、HashMap基本结构 HashMap继承AbstractMap抽象类,AbstractMap实现Map接口。 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { private static final long serialVersionUID = 362498820763181265L; .... } public abstract class AbstractMap<K,V> implements Map<K,V> { protected AbstractMap() { } ... } 二、HashMap的基本数据结构 jdk1.8之前,HashMap是由“数组+链表”的结构组成,jdk1.8之后,HashMap得到很大的改善;数据结构也发生了改变:“数组+链表+红黑树”;当链表节点大于8时,会转换为红黑树;否则仍然以链表结构。 头节点指的是table表上索引位置的节点,也就是链表的头节点 根节点(root节点)指的是红黑树最上面的那个节点,也就是没有父节点的节点 红黑树的根节点不一定是索引位置的头节点 转为红黑树节点后,链表的结构还存在,通过next属性维持

【集合系列】- 深入浅出分析HashMap

坚强是说给别人听的谎言 提交于 2019-12-06 16:27:29
一、摘要 在集合系列的第一章,咱们了解到,Map的实现类有HashMap、LinkedHashMap、TreeMap、IdentityHashMap、WeakHashMap、Hashtable、Properties等等。 关于HashMap,一直都是一个非常热门的话题,只要你出去面试,我保证一定少不了它! 本文主要结合JDK1.7和JDK1.8的区别,就HashMap的数据结构和实现功能,进行深入探讨,废话也不多说了,直奔主题! 二、简介 在程序编程的时候,HashMap是一个使用非常频繁的容器类,它允许键值都放入null元素。除该类方法未实现同步外,其余跟Hashtable大致相同,但跟TreeMap不同,该容器不保证元素顺序,根据需要该容器可能会对元素重新哈希,元素的顺序也会被重新打散,因此不同时间迭代同一个HashMap的顺序可能会不同。 HashMap容器,实质还是一个哈希数组结构,但是在元素插入的时候,存在发生hash冲突的可能性; 对于发生Hash冲突的情况,冲突有两种实现方式, 一种开放地址方式(当发生hash冲突时,就继续以此继续寻找,直到找到没有冲突的hash值),另一种是拉链方式(将冲突的元素放入链表) 。 Java HashMap采用的就是第二种方式,拉链法。 在jdk1.7中,HashMap主要是由数组+链表组成,当发生hash冲突的时候