散列冲突

散列表:常见的散列冲突解决方法有哪些? 在使用散列表(哈希表)时,由于不同的键可能会映射到相同的哈希值,就会产生散列冲突。 阅读详情

概念:如果当一个元素被插入时与一个已经插入的元素散列到相同的值, 那么就会产生冲突, 这个冲突需要消除。解决这种冲突的方法有几种:本章介绍两种方法:分离链接法和开放定址法

1.分离链接法

    其做法就是将散列到同一个值得所有元素保留到一个表中。我们可以使用标准库的实现方法。如果空间很紧(因为表是双向链表的并且浪费空间)。
为执行一次查找,我们使用散列函数来确定是那一个链表, 然后我们在被确定的链表中执行一次查找。

    import java.util.LinkedList;
import java.util.List;

public class SeparateChainingHashTable<AnyType> {
    private static final int DEFAULT_TABLE_SIZE = 101;
    private List<AnyType>[] theLists;
    private int currentSize;

    public SeparateChainingHashTable(){
        this(DEFAULT_TABLE_SIZE);
    }
    public SeparateChainingHashTable(int size){
        theLists = new LinkedList[nextPrime(size)];

        for(int i = 0; i < theLists.length; i++)
            theLists[i] = new LinkedList<>();
    }

    public boolean contains(AnyType x){
        List<AnyType> whichList = theLists[myhash(x)];
        return whichList.contains(x);
    }

    /*
     * 数据的插入
     */
    public void insert(AnyType x){
        List<AnyType> whichList = theLists[myhash(x)];
        if(!whichList.contains(x)){
            whichList.add(x);

            //
            if(++currentSize > theLists.length)
                rehash();
        }
    }

    /*
     * 数据的删除
     */
    public void remove(AnyType x){
        List<AnyType> whichList = theLists[myhash(x)];
        if(whichList.contains(x))
        {
            whichList.remove(x);
            currentSize--;
        }
    }

    public void makeEmpty(){
        for(int i = 0; i < theLists.length; i++)
            theLists[i].clear();
        currentSize = 0;
    }

    private void allocateArray(){
        for(int i = 0; i < theLists.length; i++)
            theLists[i] = new LinkedList<>();
    }

    //将传过来的数变成质数
    private static int nextPrime(int n){
        if(n < 11)
            return 11;
        else if(isPrime(n))
            return n;   
        else
            while(true){
                n++;
                if(isPrime(n)){
                    return n;
                }
            }
    }

    //判断是不是质数
    private static boolean isPrime(int n){
        if(n % 2 != 0 && n % 3 != 0 && n % 5 != 0 && n % 7 != 0)
            return true;
        else
            return false;
    }

    /*
     * 对分离链接散列表和探测散列表的在散列
     */
    private void rehash(){
        List<AnyType> [] oldList = theLists;
        theLists = new LinkedList[theLists.length * 2];
        allocateArray();
        for(int i = 0; i < oldList.length; i++){
            List<AnyType> whichList = oldList[i];
            for (AnyType x : whichList) {
                insert(x);
            }
        }
    }

    /*
     * 散列表的myHash的方法
     */
    private int myhash(AnyType x){
        int hashVal = x.hashCode();

        hashVal %= theLists.length;
        if(hashVal < 0)
            hashVal += theLists.length;

        return hashVal;
    }

    /*测试*/
    public static void main(String[] args) {
        SeparateChainingHashTable<String> hash = new SeparateChainingHashTable<>();
        hash.insert("Tom");
        hash.insert("SanZi");
        System.out.println(hash.contains("Tom"));
    }
}

2.开放定址法

不用链表的散列表
2.1线性探测法

就是在插入冲突的时候, 当前位置有值存放的话, 那么就会到下一个位置存放。这种解决冲突的方法虽然在前期效果明显, 但是在插入数量比较庞大的时候。 它解决冲突的时间和链接法的时间相差无几。所以在线性探测这种情况下优化, (平方探测法)。

2.1平方探测法
public class QuadraicProbindHashTale<T> {

    /**
     *  数据域
     * @param <T>   : 泛型,存放对象
     */
    private static class HashEntry<T>{
        public T element;
        public boolean isActive;

        public HashEntry(T e){
            this(e, true);
        }

        public HashEntry(T e, boolean i){
            element = e;
            isActive = i;
        }
    }

    /*
     * 默认的大小为11
     */
    private static final int DEFAULT_TABLE_SIZE = 11;

    private static int currentSize = 0;

    private HashEntry<T>[] array;

    public QuadraicProbindHashTale(){
        this(DEFAULT_TABLE_SIZE);
    }

    /**
     * 
     * @param size  : 表的大小
     */
    public QuadraicProbindHashTale(int size) {
        allocateArray(size);//先判断传过来的size是不是质数, 如果不是, 把它变成质数, 这样方便hash计算和不容易出现冲突情况
        makeEmpty();
    }

    /*
     * 判断对象是否在这个hash表当中
     */
    public boolean contains(T x){
        int currentPos = findPos(x);
        return isActive(currentPos);
    }

    /**
     * 数据的插入
     * @param x :数据的元素
     * 首先调用findPox方法来判断在第一次执行hash的时候里面有没有元素,如果没有直接插入
     * 如果有元素, 那么在存放的位置往后挪。(线性探测, 平方探测)
     */
    public void insert(T x){
        int currentPos = findPos(x);
        if(isActive(currentPos))
            return;

        array[currentPos] = new HashEntry<>(x, true);

        if(currentSize > array.length / 2)
            rehash();
    }

    /**
     * 数据的删除
     * @param x :要删除的数据
     * 在数据域内有识别这个内容是否有效的一个boolean类型, 当isActive是为true的时候, 表示有效
     * 如果有效的话, 那么就删除。
     */
    public void remove(T x){
        int currentPos = findPos(x);
        if(isActive(currentPos))
            array[currentPos].isActive = false;
    }

    /**
     */
    private void rehash(){
        HashEntry<T>[] oldArray = array;

        allocateArray(nextPrime(2 * oldArray.length));
        currentSize = 0;

        for(int i = 0; i < oldArray.length; i++)
            if(oldArray[i] != null && oldArray[i].isActive)
                insert(oldArray[i].element);
    }

    private boolean isActive(int currentPos){
        return array[currentPos] != null && array[currentPos].isActive;
    }

    /**
     * 查找在hash表中元素
     * @param x :要查找的元素
     * @return  所在数组中的位置
     */
    private int findPos(T x){
        int offset = 1;
        int currentPos = myhash(x);

        while(array[currentPos] != null && !array[currentPos].equals(x)){
            currentPos += offset;
            offset += 2;
            if(currentPos >= array.length)
                currentPos -= array.length;
        }

        return currentPos;
    }

    /*
     * 初始化hash表中的所有的值为空
     */
    public void makeEmpty(){
        currentSize = 0;
        for(int i = 0; i < array.length; i++)
            array[i] = null;
    }

    private void allocateArray(int arraySize){
        array = new HashEntry[nextPrime(arraySize)];
    }

    //将传过来的数变成质数
        private static int nextPrime(int n){
            if(n < 11)
                return 11;
            else if(isPrime(n))
                return n;   
            else
                while(true){
                    n++;
                    if(isPrime(n)){
                        return n;
                    }
                }
        }

        //判断是不是质数
        private static boolean isPrime(int n){
            if(n % 2 != 0 && n % 3 != 0 && n % 5 != 0 && n % 7 != 0)
                return true;
            else
                return false;
        }

        /*
         * 散列表的myHash的方法
         */
        private int myhash(T x){
            int hashVal = x.hashCode();

            hashVal %= array.length;
            if(hashVal < 0)
                hashVal += array.length;

            return hashVal;
        }
}
星座SAR动目标检测(GMTI) 参考代码 星座SAR动目标检测 www.youwenfan.com/contentcsg/52399.html。 阅读详情

相关推荐

PLL Performance,Simulation and Design 4th学习笔记——Chapter1

Chapter1:基本PLL概述 VCO:Voltage-Controlled Oscillator压控振荡器,对于给定的一个输入电压,输出特定频率的振荡信号。 PLL:Phase-Locked Loops锁相环,输出特定频率,特定相位的振荡信号。 基本PLL操作和术语 基本模块 基本模块 输入 输出 传输函数 说明 XTAL - 参考频率ϕref\phi_{ref}ϕref​ - 稳定的晶振提供输入参考频率(这里用相位,便于理解鉴相器) R Counter ϕref\phi_{ref

张硕的博客 1551

散列表及散列冲突解决方案

https://blog.youkuaiyun.com/u010530712/article/details/93166430 1、散列表 看过HashMap源码的同学应该知道,HashMap是基于哈希表(散列表)的 Map 接口的非同步实现。 在我们put了一条key-value数据后,如下图,程序会先将key通过hash(key)这个函数转化成整形,这个整形做为数组的下标,插入数据或查找数据。 我们发现,散列

yygr的博客 2489

哈工大OS实验四——进程运行轨迹的跟踪与统计

进程运行轨迹的跟踪与统计 进程从创建(Linux 下调用 fork())到结束的整个过程就是进程的生命期,进程在其生命期中的运行轨迹实际上就表现为进程状态的多次切换,如进程创建以后会成为就绪态;当该进程被调度以后会切换到运行态;在运行的过程中如果启动了一个文件读写操作,操作系统会将该进程切换到阻塞态(等待态)从而让出 CPU;当文件读写完毕以后,操作系统会在将其切换成就绪态,等待进程调度算法来调度该进程执行…… process.c解读 void cpuio_bound(int last, int cpu_

优快云-ych 1001

数据结构与算法:处理散列冲突的方法

数据结构与算法:处理散列冲突的方法

学习中 542

Fluent实战——残差震荡分析与收敛优化策略

本文深入探讨了Fluent仿真中残差震荡的成因与优化策略。残差震荡是流场物理或数值问题的关键信号,文章系统分析了网格质量、边界条件、物理模型非定常性及求解设置四大主因,并提供了库朗数与松弛因子的调参心法,以及针对超音速流、共轭传热等典型场景的实战优化方案,旨在帮助用户有效提升计算收敛性与结果可靠性。

w1x2y3的博客 313

一文入门BMS(电池管理系统)

本文章是基于曾师兄的文稿《具有组网扩展功能的新能源汽车电池管理系统》而写的文章。该文章主要是对BMS(Battery Management System,电池管理系统)做一些简要的介绍,借此助各位也助我入门BMS。有纰漏请指出,转载请说明。学习交流请发邮件 1280253714@qq.com。

weixin_45817947的博客 2万+

数据结构中处理散列冲突的四种方法

数据结构中处理散列冲突的四种方法

吴名氏的博客 5万+

5步搞定ABB机器人RobotStudio与S7-1500PLC的Profinet通讯(附PLCSIM调试技巧)

本文详细介绍了如何利用RobotStudio与TIA Portal软件,结合PLCSIM Advanced仿真器,在零硬件条件下实现ABB机器人与西门子S7-1500 PLC之间的Profinet通讯虚拟调试。通过五个核心步骤,从环境搭建、网络配置、信号映射到联合仿真与高级调试,帮助工程师在项目前期高效验证逻辑、压缩现场调试周期,并掌握实用的PLCSIM调试技巧。

weixin_29188043的博客 505

数据结构(七)——散列表

对于散列函数 H(key)=key%13 来说,1 和 14 是“同义词”,可以构造更适合的散列函数,让各个关键字尽可能地映射到不同的存储位置,从而减少“冲突”冲突(碰撞)︰在散列表中插入一个数据元素时,需要根据关键字的值确定其存储地址,若该地址已经存储了其他元素,则称这种情况为“冲突(碰撞)”Step 2∶若关键字不匹配,则根据“探测序列”对比下一个地址的关键字,直到“查找成功”或“查找失败”例︰长度为13的散列表状态如下图所示,散列函数H(key)=key%13,采用线性探测法解决冲突。

señoritaw的博客 6981

OpenVPN 新增 windows 客户端

虚拟私人网络(Virtual Private Network,简称VPN)是一种网络技术,它允许用户通过公共网络(如互联网)建立一个安全的连接通道。本文介绍如何添加 windows 客户端。

利昂的技术存档 3764

点云语义分割:PointNet训练S3DIS数据集

文章目录一、数据准备1.1、数据下载二、训练三、测试 项目地址:pointnet 此次我们是用pointnet网络来做语义分割。代码在pointnet项目中的sem_seg文件夹下,里面也有README.md介绍了训练的过程。 一、数据准备 1.1、数据下载 原始数据下载 处理好的h5格式数据下载 二、训练 三、测试 ...

zhaoguanhua的博客 4176

散列函数之双重散列算法解决冲突问题

1. 问题 问题同《简单散列函数算法》,这个例子并不是特别恰当,当在于简单,数字小,方便验证,方便理解,特别是计算概率的部分。 设有10个非负整数,用不多于20个的储存单元来存放,如何存放这10个数,使得搜索其中的某一个数时,在储存单元中查找的次数最少? 问题类似于,有10个带号码的球,放到编号为{0, 1, 2, …, 19}共20个盒子中,每个盒子最多放一个,问如何放,使能够用最少的次数...

weixin_30827565的博客 2283

DSI3协议介绍

分布式系统接口(DSI)是一种通用且功能强大的总线协议,旨在将多个遥感器和执行器设备互连到中央控制模块。该网络的主要目标应用是汽车安全系统。这种应用的一些特点是需要低成本、高鲁棒性、中速互连,仅限于两根导线。此外,它必须具有故障安全性、确定性和良好的EMC特性。即使具有所有级别的智能和可编程性的设备都可以连接到网络,远程设备也必须能够通过简单的状态机实现。由于模块尺寸非常重要,因此中央模块和远程单元中的最小组件至关重要。

汽车电子软件领域知识分享 1万+

散列表与散列冲突

目录 散列表与散列冲突 解决散列冲突的方法 1.分离链接法(拉链法) 2.开放寻址法 再散列 散列表与散列冲突 HashTable,音译为哈希表,是根据关键字(key)而直接进行访问的数据结构。关键字k,值存放在f(k)的存储位置上,则f为散列函数。关键字(key)通过散列函数直映射到表中一个位置,以加快查找速度。 散列冲突,因为存储单元数目是有限的,当关键字数量增大时,两个不同的...

鹿与森的博客 1887

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

散列表、常见散列函数及处理冲突的方法

文章目录散列表的概念常见的散列函数处理冲突的方法处理冲突的开放地址法处理冲突的拉链法散列查找及性能分析 散列表的概念 散列法  散列法又称哈希法或杂凑法,它在元素的存储位置与元素关键码之间建立一个确定的对应函数关系Hash(),使得每个关键码与结构中的一个唯一的存储位置相对应: Address=Hash(key) Address = Hash(key)Address=Hash(key)  在插入时,依此函数计算存储位置并按此位置存放。  在查找时,对元素的关键码进行同样的函数计算,把求得的函数值当作元素的

薛定谔的猫的博客 3858

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

散列、散列函数、冲突处理

1、散列:理想的散列表数据结构只不过是一个包含有关键字的具有固定大小的数组。典型情况下,一个关键字就是带有相关值的字符串。2、散列的基本思想:以关键字key为自变量,通过一个确定的函数 h(散列函数),计算出对应的函数值h(key),作为数据对象的存储地址。3、冲突:可能不同的关键字会映射到同一个散列地址上, 即h(keyi) = h(keyj)(当keyi ≠keyj),称为“冲突(Collisi

beichengll的博客 4539

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

查找——散列表的散列函数及冲突的处理办法

查找8.7 散列表8.7.1 散列表的基本概念8.7.2 散列函数1.直接定址法2.数字分析法3.除留余数法4.乘余取整法5.平方取中法6.随机数法7.折叠法8.7.3 处理冲突的闭 8.7 散列表 8.7.1 散列表的基本概念 所谓查找,实际上就是要确定关键字(Key)等于给定值(k)的数据元素的存储地址(Addr)。故查找问题本质上是确定关键字集合K到地址空间A的映射(即函数):H:K->A。因而,任何查找算法,都是计算函数H(k)的值的过程。 由于k与H(k)之间没有简单直接的对应关系,函数H

lseaJK的博客 3003

解决散列表冲突方法

1 解决冲突方法1.1 链接法又叫拉链法,将具有同一散列地址的记录存储在一条线性链表中1.2 开放定址法通过对原hash函数进行修改,添加探查函数,当出现冲突时,往下一个地址写数据图中p(i)为探查函数探查函数分为以下四种:        线性探查法:(p(i)为1,2,...,...n)        二次探查法        随机探查法:(p(i)为随机数)        双散列函数法使用开放...

LishcCai的博客 1万+

处理散列冲突的方法

1. 开放定址法 一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。 发生冲突,另寻他处 我们把这种解决冲突的方法称为线性探测法。 我们在解决冲突的时候,还会碰到比如说一个数 48, 它所在的位置已经被占用,它只能往后延,但是又与后面的冲突 ,本来两个数一点关系都没有,但是发生冲突,这种现象称为堆积, 堆积的出现使得我们需要不断处理冲突,即48要不...

qq_44587855的博客 3215

散列冲突解决的方式

一、散列思想 散列表的英文叫Hash Table,也叫哈希表或者Hash表。散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。 散列表时间复杂度是O(1)的特性。我们通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应下标的位置。当我们按照键值查询元素时,我们用同样的...

u013085496的博客 1944

散列表处理冲突的方法

一、开放地址法 所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。 1.1 线性探测法 fi ( key ) = ( f ( key ) + di ) MOD m (di=1,2,3,4,…,m-1) 会出现不是同义词却需要争夺一个地址的情况,我们称这种情况为堆积。 1.2 二次探测法 关键字集合『12,67,56,16,25...

CarmenIsOK的博客 3711

散列表、散列函数和散列冲突

散列表(HashTable,也叫哈希表),是根据键(Key)直接访问在内存存储位置的数据结构。 其实现原理是:通过散列函数(也叫哈希函数)将元素的键映射为数组下标(转化后的值叫做散列值或哈希值),然后在对应下标位置存储记录值。当我们按照键值查询元素时,就是用同样的散列函数,将键值转化数组下标,从对应的数组下标的位置取数据: 散列表用的是数组支持按照下标随机...

weixin_30298497的博客 414

客观题——散列冲突

22.设数字 {4371, 1323, 6173, 4199, 4344, 9679, 1989} 在大小为10的散列表中根据散列函数 h(X)=X%10得到的下标对应为 {1, 3, 4, 9, 5, 0, 2}。3.采用线性探测冲突解决策略,hi(k)=(H(k)+i)mod 11,将散列函数值分别等于2、2、3、3的四个对象a1、a2、a3、a4都插入一个大小为11的空散列表(哈希表)中。20.现有长度为 7、初始为空的散列表HT,散列函数H(k)=k%7,用线性探测再散列法解决冲突。

xz857的博客 3798

散列表是什么(散列函数、散列冲突、HashMap、LinkedHashMap)

一、什么是散列表 ? 散列表用的是数组支持下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。 举个例子,我们将参赛选手设置一个编号,比如051167,表示 5 年级 11 班 67 号选手,然后在数组索引下标对应 67 的位置存储该选手,这就是典型的散列思想,我们将参赛选手的编号叫做键(key)或者关键字,用它来标识一个选手,把参赛编号转化为数组下标的映射方法就叫作散列函数...

Seina 8233
上一篇: 散列
下一篇: 标准库中的集合与映射
LuFei_java
博客等级 码龄10年 1粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值