红黑树

Java8——重新认识HashMap

拟墨画扇 提交于 2019-12-04 00:00:20
摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文结合JDK1.7和JDK1.8的区别,深入探讨HashMap的结构实现和功能原理。 简介 Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap、Hashtable、LinkedHashMap和TreeMap,类继承关系如下图所示: 下面针对各个实现类的特点做一些说明: (1) HashMap:它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap。 (2) Hashtable:Hashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类

数据结构中各种树

a 夏天 提交于 2019-12-03 23:09:33
阅读目录 1. 二叉树 2. 二叉查找树 3. 平衡二叉树 3.1 平衡查找树之AVL树 3.2 平衡二叉树之红黑树 4. B树 5. B+树 6. B*树 7. Trie树   数据结构中有很多树的结构,其中包括二叉树、二叉搜索树、2-3树、红黑树等等。本文中对数据结构中常见的几种树的概念和用途进行了汇总,不求严格精准,但求简单易懂。 回到顶部 1. 二叉树   二叉树是数据结构中一种重要的数据结构,也是树表家族最为基础的结构。 二叉树的定义: 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2 i-1 个结点;深度为k的二叉树至多有2 k-1 个结点;对任何一棵二叉树T,如果其终端结点数为n 0 ,度为2的结点数为n 2 ,则n 0 =n 2 +1。 二叉树的示例 : 满二叉树和完全二叉树:   满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点。也可以这样理解,除叶子结点外的所有结点均有两个子结点。节点数达到最大值,所有叶子结点必须在同一层上。   满二叉树的性质:   1) 一颗树深度为h,最大层数为k,深度与最大层数相同,k=h;   2) 叶子数为2 h ;   3) 第k层的结点数是:2 k-1 ;   4) 总结点数是:2 k-1 ,且总节点数一定是奇数。   完全二叉树

面试准备 | 树相关的总结整理

前提是你 提交于 2019-12-03 21:33:19
树的遍历 前中后序遍历的6种实现方法(每种都有递归和循环两种)。 https://blog.csdn.net/liujiayu1015/article/details/52535829 剑指offer T26 34 55 7 33 (P62) 层序遍历:T32 二叉搜索树:左<根<右,O(logn)实现搜索,T36 68 堆和红黑树:堆分为最大堆和最小堆(快速查找最大、最小值)。 红黑树:把树中的节点定义为红、黑两种颜色,通过规则确保从根节点到叶节点的最长路径的长度不超过最短路径的两倍。 C++的STL基于红黑树的结构:set multiset map multimap 等 unordered_map? T40 来源: https://www.cnblogs.com/shona/p/11809684.html

红黑树

点点圈 提交于 2019-12-03 20:18:51
二叉查找树特点 1.左子树上所有结点的值均小于或等于它的根结点的值。 2.右子树上所有结点的值均大于或等于它的根结点的值。 3.左、右子树也分别为二叉排序树。 红黑树特点 1、节点是红色或者黑色 2、根节点是黑色 3、每个叶子的节点都是黑色的空节点(NULL) 4、每个红色节点的两个子节点都是黑色的 5、从任意节点到每个叶子节点的所有路径都包含相同的黑色节点 二叉查找树调整为红黑树的方法 变色、旋转 来源: https://www.cnblogs.com/nachdenken/p/11806628.html

快速看懂HashMap

余生颓废 提交于 2019-12-03 19:49:14
在开始之前,先过一遍本博客的重点 • HashMap寻值的速度快是因为HashMap的键会被映射成Hash值,从而避开用equal方法遍历来加快寻值速度。 • HashMap有初始容量和加载因子两个参数来控制性能。当条目大于容量*加载因子时,容量翻一倍。 • HashMap和Hashtable的区别在于线程安全性,同步,以及速度。 下面开始正文 1.HashMap的具体实现 Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap、Hashtable、LinkedHashMap和TreeMap,类继承关系如下图所示: HashMap中我们最常用的就是put(K, V)和get(K)。我们都知道,HashMap的K值是唯一的,所以查询和修改数据的时候只要用equal遍历所有的key值就可以了,但我们知道直接遍历查询的时间复杂度为O(n),在数据量比较大时效率不高,所以在java中运用Hash算法来对所有的key进行运算加入数组中。查询的时候直接用数组下标来访问数据(时间复杂度变成了O(1)),以此绕开了用equal遍历带来的效率损失。 HashMap根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap最多只允许一条记录的键为null

epoll反应堆

。_饼干妹妹 提交于 2019-12-03 15:05:40
1 /* 2 * epoll基于非阻塞I/O事件驱动 3 */ 4 #include <stdio.h> 5 #include <sys/socket.h> 6 #include <sys/epoll.h> 7 #include <arpa/inet.h> 8 #include <fcntl.h> 9 #include <unistd.h> 10 #include <errno.h> 11 #include <string.h> 12 #include <stdlib.h> 13 #include <time.h> 14 15 #define MAX_EVENTS 1024 //监听上限数 16 #define BUFLEN 4096 17 #define SERV_PORT 8080 18 19 void recvdata(int fd, int events, void *arg); 20 void senddata(int fd, int events, void *arg); 21 22 /* 描述就绪文件描述符相关信息 */ 23 24 struct myevent_s { 25 int fd; //要监听的文件描述符 26 int events; //对应的监听事件 27 void *arg; //泛型参数 28 void (*call_back)(int fd,

多路复用

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-03 12:13:16
为什么会考虑到深入理解多路复用?在Http/2,Redis等内容中,反复提到多路复用带来的效率提升,也只有了解了基础概念,才能掌握它们,一步一步来吧。 了解多路复用前,先对五中IO模型进行初步了解。 省略--后续补充 多路复用最重要的知识点是因为内部用了一个红黑树记录添加的socket,用了一个双向链表接收内核触发的事件(双向链接描述错误,“双向链表的每个节点都是基于epitem结构中的rdllink成员”) 红黑树 就是因为多了这个存储,可以直接拿到就绪socket,而不用像select那样一个个检查。由于epoll需要往这个结构里添加或删除数据,就要求这个结构能够快速的添加和删减元素,双向链表刚好比较适合。 情况分类|添加|删除 双向链表 时间复杂度 情况分类 添加 删除 最好头节点 O(1) O(1) 最好尾节点 O(1) O(1) 平均 O(n) O(n) 细节 当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体,这个结构体中有两个成员与epoll的使用方式密切相关。eventpoll结构体如下所示: - struct eventpoll{ .... /*红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件*/ struct rb_root rbr; /*双链表中则存放着将要通过epoll

HashMap源码分析

核能气质少年 提交于 2019-12-03 07:40:32
一、前言   在分析jdk1.8后的HashMap源码时,发现网上好多分析都是基于之前的jdk,而Java8的HashMap对之前做了较大的优化,其中最重要的一个优化就是桶中的元素不再唯一按照链表组合,也可以使用红黑树进行存储,总之,目标只有一个,那就是在安全和功能性完备的情况下让其速度更快,提升性能。好~下面就开始分析源码。 二、HashMap数据结构      说明:上图很形象的展示了HashMap的数据结构(数组+链表+红黑树),桶中的结构可能是链表,也可能是红黑树,红黑树的引入是为了提高效率。所以可见,在分析源码的时候我们不知不觉就温习了数据结构的知识点,一举两得。 三、HashMap源码分析   3 .1 类的继承关系  public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable   可以看到HashMap继承自父类(AbstractMap),实现了Map、Cloneable、Serializable接口。其中,Map接口定义了一组通用的操作;Cloneable接口则表示可以进行拷贝,在HashMap中,实现的是浅层次拷贝,即对拷贝对象的改变会影响被拷贝的对象;Serializable接口表示HashMap实现了序列化

HashMap?

馋奶兔 提交于 2019-12-03 05:32:36
HashMap HashMap是Java集合中重要的一个数据结构,作为 key-value 形式的存在,被广泛使用 虽在平常开发中经常使用HashMap来存放数据,并且很多框架也使用了Map,但对HashMap的了解一直不够深入 HashMap在JDK 1.7中的实现 1.7中的数据结构 1.7中HashMap几个关键的成员变量 初始化桶大小,因为底层是数组,所以这是数组默认的大小。 桶最大值。 默认的负载因子(0.75) table 真正存放数据的数组。 Map 存放数量的大小。 桶大小,可在初始化时显式指定。 负载因子,可在初始化时显式指定 负载因子 给定的默认容量为 16,负载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作 Entry类 Entry 是 HashMap 中的一个内部类,从他的成员变量很容易看出: key 就是写入时的键。 value 自然就是值。 开始的时候就提到 HashMap 是由数组和链表组成,所以这个 next 就是用于实现链表结构。 hash 存放的是当前 key 的 hashcode。 put 方法 public V put(K key, V value) { if (table == EMPTY

ConcurrentHashMap怎么保证安全的

最后都变了- 提交于 2019-12-03 05:31:57
HashMap是一个线程不安全的容器,当容量大于 总量*负载因子 发生扩容时可能会出现环形链表从而导致死循环 扩容就是rehash,这个会重新将原数组的内容重新hash到新的扩容数组中,在多线程的环境下,存在同时其他的元素也在进行put操作,如果hash值相同,可能出现同时在同一数组下用链表表示 因此引进了线程安全的容器 ConcurrentHashMap ConcurrentHashMap 在JDK1.7 和 JDK1.8中的实现有所不同 JDK1.7中的实现 先来看看1.7中数据结构实现的图示 由图中可以看出ConcurrentHashMap是由 Segment数组 , HashEntry数组 组成的。这里和 HashMap 一样,都是 数组+链表 的形式 ConcurrentHashMap采用了分段锁的技术,其中一个 Segement 就是一个Lock,其继承自 ReentrantLock ,这样当一个线程占用了锁访问一个 Segment 时,不会影响到其它的 Segment Segment 数组的意义就是将一个大的table分成多个小的table来进行加锁,而一个Segment存储的是HashEntry数组+链表,这和HashMap的数据结构一致 Segment的大小最多65536个,没有指定concurrencyLevel元素初始化