hash冲突是什么?

news2024/11/24 5:50:21

哈希(散列)原理及使用

哈希(散列)原理及避免哈希冲突

  • 哈希(散列)原理及使用
    • 哈希冲突
    • 常见哈希函数
    • 解决哈希冲突方案
      • 实现一个开散列哈希表

当我们在一堆数据中查找一个元素时,使用普通方法得到的时间复杂度是O(N),使用搜索树的时间复杂度为O(logn),而现在告诉你有一种数据结构可以只使用O(1)的时间复杂度就可以查找,对程序的效率提升是一种质的飞跃。而这就是哈希(散列)。

哈希函数:hash(key) = key % capacity;capacity为存储元素底层空间总的大小。

哈希冲突

//数组
arr = {1,3,6,5,8,2};

在这里插入图片描述

这就是哈希冲突!哈希冲突是永远存在的,只能尽可能的避免哈希冲突!

引起哈希冲突的因素:

  • 哈希函数设计不合理。

哈希函数设计规则:

  • 哈希函数的定义域必需包含需要存储的所有关键字,如果哈希表中允许有m个地址,那么这个值域必须在0~m-1之间
  • 哈希函数计算得到的地址应该均匀分布在整个哈希表中
  • 哈希函数应该简单易懂

常见哈希函数

  1. 直接定制法

针对比较小的空间且连续空间进行计算,需要先知道关键字的分布情况

  1. 除留余数法

设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:
Hash(key) = key% p(p<=m),将关键码转换成哈希地址

  1. 负载因子法

设置一个负载因子αα = 填入表中元素/哈希表的长度 ,通过这个公式可以知道当填入数据越多,α就会越大,也表明了产生冲突的可能性越大,所以要避免冲突就尽量将负载因子减小

解决哈希冲突方案

  1. 闭散列

    也称为“开放地址法”,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以
    把key存放到冲突位置中的“下一个” 空位置中去

线性探测:

在这里插入图片描述

插入元素,合理利用剩余空间,不过当删除3这个元素时,13就会丢失头部,而下标为3的元素此刻为空,意味着失去指示头,对13进行查找时可能会受到影响。

二次探测法

针对线性探测的把产生冲突的数据放在一起,与找下一个位置有关联,而找到下一个位置就填入,未免有点不太合理。二次探测为了避免这个问题,设立了一个寻找下一个位置的方法:H_i= (H_0 + i^2)%M

H_i : 代表的是当前元素的下标

H_0 : 是本来元素的下标

i : 是指当前发生冲突的次树,i从1开始计算

M : 是当前数组总长度

在这里插入图片描述

这里要清楚当计算出来的下标已经存在数字时,i+1,直到找到一个空,将数据填入。

不过这样会浪费很多空间,也是哈希的缺陷所在。

  1. 开散列

链地址法,开链法,首先对关键码集合用哈希函数计算地址,具有相同的码又归为一类集合,每一个集合称为一个桶!桶中的元数使用链表进行串联,头节点存储在哈希表中。

在这里插入图片描述

实现一个开散列哈希表

首先要明确需要一个链表和一个链表数组。

  1. 链表数组保存哈希值
  2. 链表保存后续值
public class HashBucket {
    //哈希链表
	private static class Node {
        private int key;
        private int value;
        Node next;
		//构造方法
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }

    private Node[]  array;//哈希数组
    private int size;   // 当前的数据个数
    private static final double LOAD_FACTOR = 0.75;
    private static final int DEFAULT_SIZE = 8;//默认桶的大小
	//设置一个哈希数组长度为DEFAULT_SIZE
    public HashBucket() {
        array = new Node[DEFAULT_SIZE];
    }
	//添加元素操作
    public int put(int key, int value) {
        //先查找是否存在这个值
        int index = key % array.length;//找到这个哈希值对应的数组下标
        Node cur = array[index];//找到链表头节点
        while (cur != null){
            if(cur.key == key){
                //查找
                cur.value = value;
                return value;
            }
            cur = cur.next;
        }
        //使用头插法
        Node node = new Node(key,value);
        node.next = array[index];
        array[index] = node;
        size++;
        //判断是否需要扩容
        if(loadFactor() == 1){
            resize();
        }
        return -1;
    }


    private void resize() {
        //重新哈希
        Node[] newArray = new Node[2*array.length];//创建一个两倍大小的新哈希表
        for (int i = 0; i <array.length ; i++) {
            Node cur = array[i];
            while (cur!=null){
                //找到了在新数组当中的位置
                int index = cur.key%newArray.length;//重新计算每个哈希值并填入新的哈希链表中
                Node nextNode = cur.next;
                cur.next = newArray[index];
                newArray[index] = cur;
                cur = nextNode;
            }
        }
        array = newArray;
    }
	//判断是否满了
    private double loadFactor() {
        return size * 1.0 / array.length;
    }
	//获取key,找到这个key值下的所有key,遍历找到后,返回value
    public int get(int key) {
        // write code here
        int index = key % array.length;
        Node cur = array[index];
        while (cur != null){
            if(cur.key == key){
                return cur.value;
            }
            cur = cur.next;
        }
        return -1;
    }
}

测试

public static void main(String[] args) {
        HashBucket hashBucket = new HashBucket();
        hashBucket.put(1,12);
        hashBucket.put(2,11);
        hashBucket.put(3,13);
        hashBucket.put(4,15);
        hashBucket.put(6,16);
        hashBucket.put(7,17);
        System.out.println(hashBucket.get(1));
        System.out.println(hashBucket.get(7));
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT: 交互式AI助手为互联网用户带来全新体验

目录 概述&#xff1a; 优势&#xff1a; 挑战&#xff1a; 未来发展方向&#xff1a; 概述&#xff1a; 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正以惊人的速度改变着我们的生活方式和体验方式。AI 的应用范围越来越广泛&#xff0c;从语音助手到…

Linux 内存详解,即top、free、vmstat、meminfo、Buffer和Cache的介绍

Linux 内存详解&#xff0c;即top、free、vmstat、meminfo、Buffer和Cache的介绍_用作内核缓存的内存量_zzhongcy的博客-CSDN博客 1、top linux下的任务管理器 top命令是Linux下常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用状况&#xff0c;类似于Win…

C#项目练习系列--1.倒计时器

C#项目练习系列--1.倒计时器 实操感想代码 实操 总体实现功能&#xff1a;选定计时时间—点击开始计时—进度条和剩余时间显示—提示时间到。 软件版本&#xff1a;VS2019 1.新建工程 选择c#&#xff0c;windows窗体应用&#xff0c;.NET Framework版本选择4或4以下时最后…

SpringBoot+WebSocket+Session共享

前言 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端 一、为什么需要WebSocket HTTP 是基于请求响应式的&#xff0c;即通信只能由客户端发起&#xff0c;服务端做出响应&#xff0c;无状态&…

Spring Boot 中的 PropertySource 是什么,原理,如何使用

Spring Boot 中的 PropertySource 是什么&#xff0c;原理&#xff0c;如何使用 介绍 在 Spring Boot 中&#xff0c;PropertySource 是一个非常重要的概念。它允许您在应用程序中定义属性&#xff0c;并将这些属性注入到 Spring 环境中。在本文中&#xff0c;我们将介绍 Spr…

GO富集绘图绘制方法,零基础教程,替换数据直接作图,完成版R语言脚本

速绘 丨 GO富集气泡图 本期分享一个快速绘制GO富集结果图的方法&#xff0c;主要使用R语言tidyverse包&#xff0c;只需导入数据即可一步出图&#xff0c;可以自定义显示的数目、颜色、筛选参数&#xff0c;从此以后绘制GO富集图只需1秒。 前言介绍 下面是一个GO富集分析的结果…

Python 控制 AWG70001

0. 实验准备 泰克 AWG70001 一台电脑 一根网线 使用网线连接 AWG70001 和电脑&#xff0c;并且配置 IP 在同一网段下 1. 环境要求 vxi11 numpy struct matplotlib 没有的库可以使用下面的命令安装 pip install vxi11 pip install numpy pip install struct pip install matp…

Android中构建多视图 RecyclerView的正确打开方式

Android中构建多视图 RecyclerView的正确打开方式 简介 漂亮的UI能极大提高用户留存率&#xff0c;相反糟糕的UI将导致App安装率下降。 UI体验对用户留存率有特别大的影响&#xff0c;较差的体验app我可能用不了2s就要卸载掉。 你需要学习内容如下&#xff1a; 使用单个R…

STM32F407开发板DS18B20应用案例

【1】DS18B20介绍 DS18B20是一种数字温度传感器&#xff0c;由Maxim Integrated公司生产。它采用单总线接口&#xff0c;能够在广泛的温度范围内测量温度&#xff0c;并通过数字方式输出温度值&#xff0c;具有较高的精度和稳定性。 以下是DS18B20温度传感器的主要特点和操作…

拯救者Lenovo Legion Y9000X IAH7 2022款(82TF)原装出厂Windows11系统恢复原厂OEM系统

Lenovo联想拯救者笔记本电脑 Legion Y9000X IAH7 2022款(82TF)出厂状态原装Win11系统&#xff0c;恢复原厂系统 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;ISO 文件大小&am…

人类最新版去水印+外卖CPS小程序源码+独立后台微擎模块

最新版去水印外卖CPS小程序源码 本版本为目前最新版本 修复上个版本后台用户列表加载失败问题 新增轮播图跳转小程序 新增外卖CPS系统

layui学习

官网&#xff1a;Layui镜像站-经典开源模块化前端 UI 框架(官方文档完整镜像) 下载&#xff1a;可以在首页进行下载 快速入门Layui | 枫桥夜泊 如果不知道样式在哪个模块下&#xff0c;引入总的核心样式文件&#xff1b;如果知道样式在哪个模块下&#xff0c;直接引入module…

线程间通信

1、需求 现在两个线程操作一个初始值为0的变量实现一个线程对变量增加1&#xff0c;一个线程对变量减少1交替&#xff0c;来10轮 2、多线程编程模板中 1&#xff09;判断 2&#xff09;干活 3&#xff09;通知 线程间通信&#xff1a; 1.生产者消费者 2.通知等待唤醒机制 3…

Aski AI: 基于人工智能的在线AI工具平台

【产品介绍】 Aski AI是一个基于人工智能的在线AI工具平台&#xff0c;它可以帮助用户快速、准确、全面地解决各种问题。无论是学习、工作、生活、娱乐还是其他领域&#xff0c;只要输入你的问题&#xff0c;Aski AI就会为你提供最合适的答案。此外还提供AI文章写作&#xff0c…

BHQ1 Mal,BHQ2 Maleimide,BHQ3 Mal,马来酰亚胺修饰的BHQ试剂有哪些特点?

一、BHQ-1 Maleimide 产品描述&#xff1a; BHQ-1 Maleimide黑洞猝灭剂-1(BHQ-1)被归类为暗猝灭剂&#xff0c;该淬灭剂能够将一定距离内荧光基团发出的光全部吸收&#xff0c;实现对荧光信号的淬灭&#xff0c;所以可得到更强的特异性&#xff0c;更优化的信噪比。 中文名&a…

【正点原子STM32连载】 第四十五章 FLASH模拟EEPROM实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

第四十五章 FLASH模拟EEPROM实验 STM32本身没有自带EEPROM&#xff0c;但是STM32具有IAP&#xff08;在应用编程&#xff09;功能&#xff0c;所以我们可以把它的FLASH当成EEPROM来使用。本章&#xff0c;我们将利用STM32内部的FLASH来实现第三十六章实验类似的效果&#xff0…

设计模式第18讲——中介者模式(Mediator)

目录 一、什么是中介者模式 二、角色组成 三、优缺点 四、应用场景 4.1 生活场景 4.2 java场景 五、代码实现 5.0 代码结构 5.1 抽象中介者&#xff08;Mediator&#xff09;——LogisticsCenter 5.2 抽象同事类&#xff08;Colleague&#xff09;——Participant 5…

nvm安装node

使用 Windows 系统的我选择使用其推荐的 nvm-windows 来管理 Node.js 版本。 在安装 nvm-windows 前&#xff0c;如果你的电脑中已经安装了 Node.js&#xff0c;那么可以选择卸载&#xff0c;也可以选择不卸载。因为在安装 nvm-windows 的过程中其会询问你是否需要将已安装的 N…

mysql数据库迁移到kingbase人大金仓

1. 启动数据迁移工具 2. 浏览器打开网址[http://localhost:8080/]进入可视化操作界面&#xff0c;在源数据库添加人大金仓数据库信息&#xff0c;测试成功后保存 3.在目标数据库填写需要同步的mysql数据库&#xff0c;添加对应的mysql数据库信息&#xff0c;测试成功后保存 4.在…

The Company Requires Superficial StudyPHP 打开执行PHP ②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; PHP MYSQL &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…