模拟散列表-java

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

一、模拟散列表

二、算法思路

1.散列表

2.拉链法

3.开放寻址法

三、代码如下

1.拉链法代码如下:

 2.开放寻址法代码如下:

3.读入数据

3.代码运行结果

总结


前言

本文主要介绍模拟散列表,并用拉链法和开放寻址法来解决哈希冲突。


提示:以下是本篇文章正文内容,下面案例可供参考

一、模拟散列表

维护一个集合,支持如下几种操作:

  1. I x,插入一个整数 x;
  2. Q x,询问整数 x 是否在集合中出现过;

现在要进行 N 次操作,对于每个询问操作输出对应的结果。

输入格式

第一行包含整数 N,表示操作数量。

接下来 N 行,每行包含一个操作指令,操作指令为 I xQ x 中的一种。

输出格式

对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No

每个结果占一行。

数据范围

1≤N≤100000
−1000000000≤x≤1000000000

二、算法思路

1.散列表

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。

计算索引的过程被称为 哈希(hash)

比如我们有一个从1到10^9个整数,然后我们有10^5个大小的空间,然后我们从1-10^9个数对10^5进行取余运算,然后得到的余数就是在空间中的位置,我们可以知道例如10^5+1在空间中的位置也是1,1在空间中的位置也是1,发生了冲突,这样就是哈希冲突。我们把对10^5进行取模运算叫做哈希函数

 注:我们对一个数和另一个书进行取模运算,模数尽量是质数且是大于当前数据规模大小的最小的一个质数,这样的冲突是最少的。

2.拉链法

图2.1拉链法示例 

拉链法是我们解决哈希冲突所使用的一种方法。比如我们用哈希函数hash(11) = 3就把11链接在3的位置,hash(23)=3也是放入3的位置,此时呢我们就把23链接在11的后面,故我们我们的每一个位置都是一条链表,故这种方法称为拉链法。

一般我们都是我们都是在散列表中进行增加和查找操作,很少进行删除操作;就算进行删除操作,我们也不是直接删除这个数,而是准备一个标志数组即可。

    //头插法
    public static void insert(int x){
        //因为负数对正数取余还是负数,所以我们加上一个N变成正数
        //k就是我们的哈希值
        int k = ( x % N + N ) % N;
        e[index] = x;
        ne[index] = h[k];
        h[k] = index;
        index++;

    }
    public static boolean query(int x){
        int k = (x % N + N ) % N;
        for(int i = h[k]; i != -1;i = ne[i]){
            if(e[i] == x){
                return true;
            }
        }
        return false;
    }

我们引入一维整型数组h,h[i]为第i个位置单链表的头结点,因为初始链表都为空,都初始化-1,然后我们采用头插法将结点插入链表。具体e数组、ne数组和尾插法、单链表的遍历的详细过程请看这篇博客。https://blog.csdn.net/m0_63267251/article/details/138202017

3.开放寻址法

 图3.1开放定址法示例图

开放寻址法解决冲突比如有10^5个数据,那么数组空间得开数据的2到3倍,这样才会减少冲突。

当h(x) = k的时候,然后第k个位置有元素,那么就往后移一位,如果后面一个位置还有元素,就接着往后移,知道有空白位置放即可。

我们查找也是从第k个位置开始,如果当前位置有人且是x那么我们就找到了x;如果当前位置有人但不是x,那我们就往后一位接着找;如果找到最后是一个空位且之前并没有找到x,就说明没有x。

删除操作我们不会直接把x删掉,而是在数组中打一个特殊的标记,标记一下x有没有删除(不常用)

    public static int find(int x){
        int k = (x % N + N) % N;
        while ( h[k] != x && h[k] != nu){
            k++;
            if(k == N){
                k = 0;
            }
        }
        return k;
    }

我们设置一个整型变量nu,当数组中的值等于nu的时候表示为空,当数组中的值不等于x且不为空时,往后移,当我们k移到最后一个位置,我们再让k从第一个位置开始查找空白位置,我们数组的空间是比较大的,够放置元素。找到了空白是说明没找到元素返回的空白处的数组下标,找到元素了返回的是找到位置的数组下标。

然后插入元素我们直接让 h[find(x)] = x即可。查询元素如果h[find(x)] == nu则说明没有该元素打印No,如果不等则说明找到该元素打印Yes。

 

三、代码如下

1.拉链法代码如下:

import java.io.*;
import java.util.*;
public class 模拟散列表 {
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(br);
    static int N = 100003;
    //存储每个链表中第一个结点在e数组中的下标
    static int[] h = new int[N];
    //存储链表中的值
    static int[] e = new int[N];
    static int[] ne = new int[N];
    //记录链表中新创建的结点
    static int index = 0;

    public static void main(String[] args)throws Exception {
        int n = nextInt();
        //头结点下标全部初始化为-1
        Arrays.fill(h,-1);
        while (n-- > 0){
            String[] strs = nextLine().split(" ");
            String cmd = strs[0];
            int x = Integer.parseInt(strs[1]);
            if (cmd.equals("I")){
                insert(x);
            } else if (cmd.equals("Q")) {
                if (query(x)){
                    pw.println("Yes");
                }else {
                    pw.println("No");
                }
            }
        }
        pw.flush();
    }
    //头插法
    public static void insert(int x){
        //因为负数对正数取余还是负数,所以我们加上一个N变成正数
        //k就是我们的哈希值
        int k = ( x % N + N ) % N;
        e[index] = x;
        ne[index] = h[k];
        h[k] = index;
        index++;

    }
    public static boolean query(int x){
        int k = (x % N + N ) % N;
        for(int i = h[k]; i != -1;i = ne[i]){
            if(e[i] == x){
                return true;
            }
        }
        return false;
    }
    public static int nextInt()throws Exception{
        st.nextToken();
        return (int)st.nval;
    }
    public static String nextLine()throws Exception{
        return br.readLine();
    }
}

 2.开放寻址法代码如下:


import java.io.*;
import java.util.Arrays;

public class 开放定址法 {
    static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(br);
    static int N = 200003;
    static int[] h = new int[N];
    //如果数组中的数为m,则说明该位置为空
    static int nu = 0x3f3f3f3f;
    public static void main(String[] args) throws Exception{
        Arrays.fill(h,nu);
        int n = nextInt();
        while (n-- > 0){
            String[] strs = nextLine().split(" ");
            String cmd = strs[0];
            int x = Integer.parseInt(strs[1]);
            int k = find(x);
            if (cmd.equals("I")){
                h[k] = x;
            } else if (cmd.equals("Q")) {
                if(h[k] == nu){
                    pw.println("No");
                } else {
                    pw.println("Yes");
                }
            }
        }
        pw.flush();
    }
    public static int find(int x){
        int k = (x % N + N) % N;
        while ( h[k] != x && h[k] != nu){
            k++;
            if(k == N){
                k = 0;
            }
        }
        return k;
    }
    public static void insert(int x){
        int k = (x % N + N) % N;

    }
    public static int nextInt()throws Exception{
        st.nextToken();
        return (int)st.nval;
    }
    public static String nextLine()throws Exception{
        return br.readLine();
    }
}

3.读入数据

5
I 1
I 2
I 3
Q 2
Q 5

3.代码运行结果

Yes
No

总结

上述主要介绍了通过拉链发和开放寻址法来解决哈希冲突和模拟散列表的代码和思路。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

scipy.io.loadmat加载.mat文件,出现KeyError: ‘xxx‘

源代码: input_image loadmat(rC:\Users\admin\Downloads\Indian_Pines\SVM/aa.mat)[aa] #影像图 错误显示: 解决方法: 因为loadmat函数读取出来的高光谱数据是dict格式的所以需要定位才能进行后续操作,定位通常是通过列名&a…

GraphQL(4):GraphQL clients访问接口

下面演示在GraphQL clients访问GraphQL 接口 1 修改baseType.js 添加可供用户访问的静态资源路径 代码如下: const express require(express); const {buildSchema} require(graphql); const grapqlHTTP require(express-graphql).graphqlHTTP; // 定义schema…

深度学习500问——Chapter10:强化学习(1)

文章目录 10.1 强化学习的主要特点 10.1.1 定义 10.2 强化学习应用实例 10.3 强化学习和监督式学习、非监督式学习的区别 10.3.1 强化学习和监督式学习的区别 10.3.2 强化学习和非监督式学习的区别 10.1 强化学习的主要特点 其他许多机器学习算法中学习器都是学得怎样做&#…

0基础学习区块链技术——推演猜想

在《0基础学习区块链技术——入门》一文中,我们结合可视化工具,直观地感受了下区块的结构,以及链式的前后关系。 本文我们将抛弃之前的知识,从0开始思考和推演,区块链技术可能是如何构思出来的。 去中心 在一般的思维…

SpringSecurity6从入门到实战之SpringSecurity整合自动装配详解(源码级讲解,耐心看完)

SpringSecurity6从入门到实战之SpringSecurity整合自动装配详解 这里我先引出问题然后再来一步步进行剖析,SpringSecurity到底是如何实现引入依赖后所有请求都需要进行认证并且会弹出login登录表单页面. 接下来会对SpringBoot的自动装配进行详解,SpringSecurity也是通过自动装配…

【渗透测试】DC-1靶机实战(上)漏洞扫描获取反弹shell

目录 一、范围界定 二、信息收集 三、目标识别 1)主机发现 2)端口扫描 四. 服务枚举 1)网站首页 2)Web指纹识别 3)nikto报告 4)robots.txt 5)UPGRADE.txt 五. 漏洞映射 1&#xff…

【项目管理常见问题大揭秘】每个管理者都要Get的「五维思维」~

走上管理岗☸要懂得五维思维 💼自我管理——做自己的CEO 严于律己:严格要求自己,注重个人品牌建设 宽以待人:接纳不同观点,提升团队凝聚力 尊重事实:鼓励团队成员发挥优势,避免负面评价 坚守诚…

Mysql基础教程(15):别名

MySQL 别名 在本文中,我们讨论了 MySQL 中的列别名,表别名和派生表别名,以及使用别名来简化 SQL 和提高 SQL 的可读性。 如果在一个 SQL 中涉及到多个表,我们需要使用 table_name.column_name 这样的方式来引用每个表的字段&…

《科技和产业》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问:《科技和产业》是不是核心期刊? 答:不是,是知网收录的第一批认定学术期刊 问:《科技和产业》是什么级别的? 答:国家级。主管单位:中国科学技术协会 主办单位&…

猫毛过敏的克星!宠物空气净化器,铲屎官的终极武器~

现在很多人都喜欢养猫,但约有10%的人会对猫咪产生过敏反应。常见的症状包括打喷嚏、流鼻涕,严重时甚至会呼吸困难。 过敏源依附在宠物的毛发和皮屑上,通过空气传播,遍布家中的各个角落,如地面、衣物和家具。这不仅增加…

Jenkins+Rancher2.7部署构建

在Jenkins中使用rancher插件时需要去查找工作负载地址 在Rancher2.7没有查看Api按钮了需要自己去查找 1.进入https://192.168.x.xx:6443/v3/projects/ 2.输入在rancher中要查找的的项目名称并点击deployment连接进入下一个页面 3.找到自己的deployment随便点一个进去 4.浏览…

【数据结构】树与二叉树——二叉树的概念

二叉树的概念 导读一、二叉树的定义及其主要特性1.1 二叉树的定义1.2 二叉树的主要特性 二、特殊的二叉树2.1 满二叉树2.2 完全二叉树2.3 二叉排序树2.4 平衡二叉树 三、二叉树的性质3.1 性质一3.2 性质二3.3 性质三3.4 性质四3.5 性质五 结语 导读 大家好,很高兴又…

MFC 使用sapi文字转换为语音

文章目录 添加头文件声明变量 添加头文件 声明变量 pSpVoice NULL; //默认构造函数中初始化为空 bool CChKBarSCCodeApp::InitSpVoice() {HRESULT hr ::CoInitialize(NULL); // COM初始化if (!SUCCEEDED(hr)){AfxMessageBox(_T("声音环境初始化失败!…

高中数学:解三角形-大题练习(第二问解题方法整理)

一、题型归纳 1、最值问题 例题1、例题2 2、恒等变换 例题3、例题4、例题5、例题6 3、图形问题 例题7、例题8 例题1 解析 第二小问 首先,正弦定理和余弦定理都可以解决这一题。下面我给出两种解法 1、余弦定理基本不等式 2、正弦定理辅助角公式 例题2 解析…

智能投顾:重塑金融理财市场,引领行业新潮流

一、引言 在数字化浪潮的推动下,金融行业正经历着前所未有的变革。其中,智能投顾作为金融科技的重要分支,以其高效、便捷和个性化的服务,逐渐成为金融理财市场的新宠。本文旨在探讨智能投顾如何引领金融理财新潮流,通过丰富的案例及解决方案,展示其独特的魅力和价值。 二…

记一次使用mysql存储过程时,游标取值为空问题

call modify_collation(num,count_num) > 1146 - Table test.table_name doesnt exist > 时间: 0.009s 我在使用mysql存储过程时,打印时游标取值为空,报错找不到表。我的过程语句是这样的: drop procedure if exists modify_collation…

推荐系统学习 二

双塔模型的结构 用户的特征,我们知道用户ID还能从用户填写的资料和用户行为中获取很多特征,包括离散特征和连续特征。所有这些特征不能直接输入神经网络,而是要先做一些处理,比如用embedding层把用户ID映射到一个向量 跟之前我们…

BioTech - 计算大量 蛋白质结构预测结果 的聚类中心(Cluster)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/139419653 CASP16 的 H0215 样本,聚类之后,10个类别的最高置信度结果。 Agglomerative Clustering,即凝聚层次聚类,属于层次聚类算法,通过逐步合并或聚集数据点,…

璞华科技荣获《数据(产品)登记证书》,璞华易表进入地方数据资产入表、数据资产运营管理市场!

随着数字经济时代的飞速发展,数据要素在社会经济中的地位也变得越来越重要,成为超越传统土地、劳动力、技术和资金的新型关键资源,被誉为“第五要素”。这一变化不仅凸显了数据在当今社会的巨大价值,也引发了对数据确权、数据交易…

『大模型笔记』Transformer系列技术博文汇总!

Transformer系列技术博文汇总! 文章目录 第1篇:矩阵乘法概念解释第2篇:使用缩放点积方法的自注意力第3篇:深入探讨多头注意力、自注意力和交叉注意力第4篇:Transformer 架构第5篇:PostLN,PreLN…