IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 简述哈希表 -> 正文阅读

[数据结构与算法]简述哈希表


?

一、什么哈希表?

??????? 哈希表也叫散列表(HashTable)是能够通过给定的关键字的值直接访问到具体对应的值的一个数据结构。底层是数组+链表/红黑树,它借助哈希函数对数组这种数据结构进行扩展,利用的是数组支持按照下标随机访问元素的特性,是存储 Key-Value 映射的集合。

二、扩容问题

1.由于哈希算法被计算的数据是无限的,而计算后的结果范围有限,因此总会存在不同的数据经过计算后得到的值相同,这就是哈希冲突,即不同的关键字得到的值可能会相同。

????????哈希表是java.util.HashMap$Node类型的数组,Node是链表结构,所以一个索引值下可能会有多个元素。所以底层是哈希表的实现类基本上都没有索引值。

????????如下图:同一个索引值下可能挂了很多个元素,但是为了提高效率,最大不超过八个,方便元素的查找。当添加的元素的索引值下刚好八个时,元素A就会往下一个索引值下面的链表挂,数组默认长度是16,当数组空间不够时,就会扩容,

?????????

数组的长度默认为16;

为什么要进行扩容:为了减少哈希碰撞。
如果哈希表中的链太长,也就是哈希冲突比较高的时候,hash表的变量就会变成单链表,效率很低,所以我们要对哈希表进行适当的扩容。

负载因子(LoadFactor)=哈希表的有效元素个数/哈希表长度

负载因子的值越大,就说明冲突越严重,但是数组的的利用率较高(数组中存储的元素很多),反之负载因子越小,就说明冲突越小,数组的利用率越低(数组中存储的元素比较少)。负载因子就是在空间和时间中取平衡值。

哈希表容易出现的问题:

① 如果空间利用率高,那么经过的哈希算法计算存储位置的时候,会发现很多存储位置已经有数据了(哈希冲突);
② 为了避免发生哈希冲突,增大数组容量,就会导致空间利用率不高,所以引出负载因子。

扩容条件:1.同一索引值下元素个数>8,并且数组长度<64;

? ? ? ? ? ? ? ? ? 2.数组的索引值占有率>0.75;

扩容规则:新数组容量==旧数组容量的二倍

转红黑树原则:同一索引值下元素个数>8,并且数组长度>=64.

为什么负载因子是0.75:

//默认的负载因子0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;

默认的负载因子0.75是对空间和时间效率的一个平衡选择,一般情况下不要修改,除非在时间和空间比较特殊的情况下,如果内存空间很多而又对时间效率要求很高,可以降低负载因子Load factor的值;相反,如果内存空间紧张而对时间效率要求不高,可以增加负载因子loadFactor的值,这个值可以大于1。

扩容原理:

final Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table;
        //计算旧哈希表的容量,如果旧的哈希表为空,则长度返回0,否则返回旧哈希表的长度
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        //扩容阈值
        int oldThr = threshold;
        //初始化新表的长度、阈值
        int newCap, newThr = 0;
        if (oldCap > 0) {//旧表的长度,如果大于0则代表旧表不为空,即不进行初始化扩容,当容量达到最大的时候,就不在扩容
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                //新哈希表的长度扩容到原来的两倍,阈值页变为原来的两倍
                newThr = oldThr << 1; // double threshold
        }
        else if (oldThr > 0) // initial capacity was placed in threshold
    	// 能进入到这里,说明oldCap = 0,也就是初始化扩容,此时扩容的大小就应该是oldThr的值
            newCap = oldThr;
         else {
            //以上条件都不满足,则直接采用默认16长度 ,和12阈值
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        if (newThr == 0) {
            //针对上面没有计算扩容阈值的情况
            float ft = (float)newCap * loadFactor;
            //判断是否小于最大容量
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        //到这里完成了扩容的长度和阈值的计算,现在开始创建新的hash表
        @SuppressWarnings({"rawtypes","unchecked"})
        Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        //将扩容后的哈希表赋值给table
        table = newTab;
        

哈希表判断两个元素是否重复的规则:
?? ? ? 哈希值是否相同 && (地址值相同 || equals相同)

三.哈希表应用

????????Set<E>接口和Map<K,V>接口下几个常用实现类底层都用到了哈希表:

????????Set接口常用实现类:

1.HashSet:是无序的,底层是哈希表(数组+链表/红黑树)

2.LinkedHashSet:是有序的,底层是链表+哈希表,是有序的

????????Map接口常用实现类:

1.HashMap:无序,底层的数据结构是哈希表

2.LinkedHashMap:有序,底层的数据结构是链表+哈希表
?


  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 19:31:09  更:2022-08-19 19:33:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 18:55:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计