当前位置: 首页 > news >正文

哈希桶(详解创建)

一、什么是哈希桶?

二、创建哈希桶

        2.1创建节点以及哈希表。

         2.2、添加节点

        2.3、扩容(降低哈希冲突)

        2.4、获取key

        2.5、负载因子判断


一、什么是哈希桶?

        开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址(index = x % array.length()-1),具有相同地址的关键码归于同一子集合,每一个子集合称为一个哈希桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

 如图,哈希是数组+链表结构,按照传入的元素放在通过散列函数计算出的散列地址处,如果再加入新的相同散列地址则向后通过链表将其链接在一起。


二、创建哈希桶

        2.1创建节点以及哈希表。

key:关键码通过散列函数计算出的散列地址

val:节点对应的值

next:向后链接相同散列地址的节点地址

    

 节点的创建:

static class Node {
    public int key;
    int val;
    Node next;
    public Node(int key,int val) {
        this.key =key;
        this.val = val;
    }
}
public Node[] array;

散列表的创建:

public Node[] array;
public int usedsize;

这里需要了解一个概念:

负载因子:x = 填入表中元素的个数 / 散列表的长度。 

负载因子过高会提高哈希冲突率,所以我们想要增加元素并且降低冲突率就得增加散列表的长度

 

我们从源码中可以看到,DEFAULT_LOAD_FACTOR是源码默认的负载因子最大值为0.75f,所以我们在模拟创建中也以这个指标去扩展数组的长度 。


         2.2、添加节点

这里代码如下:grow代码在下一个

public void put(int key,int val) {
    int index = key%array.length-1;
    Node cur = array[index];
    while (cur!= null) {
        if (cur.key == key) {
            cur.val = val;
            return;
        }
    }
    Node node = new Node(key,val);
    node.next = array[index];
    array[index] = node;
    usedsize++;
    if (loadFactor() >= DEFAULT_LOAD_FACTOR) {
        grow();
    }
}

        2.3、扩容(降低哈希冲突)

这里需要先提前标记下cur的下一个节点,不可以使用cur = cur.next ;因为遍历的cur.next会先把新位置链表的头节点接在cur的后面。

我们默认数组扩容为2倍扩容,并且遍历旧哈希表每一个节点放在新对应的散列地址处,因为数组扩容到了2倍会造成 index = x % array.length()-1 的散列地址改变。

private void grow() {
    Node[] newArray = new Node[array.length*2];
    for (int i = 0; i < array.length; i++) {
        Node cur =array[i];
        while (cur != null) {
            int index = cur.key% newArray.length-1;
            Node next = cur.next;
            cur.next = newArray[index];
            newArray[index] = cur;
            cur = cur.next;
        }
    }
    this.array = newArray;
}

        2.4、获取key

通过遍历哈希表来找到对应的节点,如果不存在节点返回-1。

public int get(int key) {
    int index = key % array.length-1;
    Node cur = array[index];
    while (cur != null) {
        if (cur.key == key) {
            return cur.val;
        }
    }
    return -1;
}

        2.5、负载因子判断

public float loadFactor() {
    return usedsize*1.0f / array.length;
}

完整代码放在Gitee::HashBuck · 6442b0c · 404NOt/Repository-1 - Gitee.comicon-default.png?t=M85Bhttps://gitee.com/N_404NOt/repository-1/commit/6442b0c94269d7f7b8406ce52bfe8e5ba5c175c9

相关文章:

  • 回归预测 | MATLAB实现SSA-BP多输入单输出回归预测
  • 【雅思备考】听说读写攻略 | 雅思核心词汇之科技类
  • Python-列表,从基础到进阶用法大总结,进来查漏补缺
  • JDBC模拟SQL注入和避免SQL注入
  • flink在企业IT架构中如何定位-在选型流批一体技术与大数据架构时的避坑指南
  • JUC并发编程之CompletableFuture基础用法
  • SpringBoot+Mybatis-Plus多数据源使用
  • Colab-免费GPU算力
  • 【CH559L单片机】串口下载程序说明
  • CMake中macro的使用
  • windows利用msys2安装minGW64
  • (42)STM32——LCD显示屏实验笔记
  • 全国青少年软件编程等级考试标准Python(1-6级)
  • Java语法基本概念
  • 一文搞懂CSS盒子模型
  • ----------
  • 【译】JS基础算法脚本:字符串结尾
  • javascript 哈希表
  • Js基础——数据类型之Null和Undefined
  • MobX
  • Next.js之基础概念(二)
  • webpack4 一点通
  • 对超线程几个不同角度的解释
  • 深度学习中的信息论知识详解
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 树莓派 - 使用须知
  • 思否第一天
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 线上 python http server profile 实践
  • 学习ES6 变量的解构赋值
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​TypeScript都不会用,也敢说会前端?
  • #### go map 底层结构 ####
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #1014 : Trie树
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (1)Nginx简介和安装教程
  • (10)ATF MMU转换表
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • (转)重识new
  • (转载)Linux网络编程入门
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .bat批处理出现中文乱码的情况
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...
  • @SuppressWarnings(unchecked)代码的作用