算法6-3:解决哈希冲突之线性探针

线性探针是另外一种解决哈希冲突的办法。这种办法的基本思想就是当遇到哈希冲突时,寻找下一个空位,直到找到空位为止。

示例

先插入一个值S,如下图。

插入其他的一些值,这些值的哈系没有冲突,得到下图的结果。

再插入一个值H,由于H与A的哈系冲突,因此需要寻找一个空的位置。

找到了空位

插入

代码

public class LinearProbeST<Key, Value> {
    private static final int M = 100;

    private Key[] keys = (Key[])new Object[M];
    private Value[] values = (Value[])new Object[M];

    public LinearProbeST() {
    }

    public Value get(Key key) {
        int hash = hash(key);
        for(int i=0; i < M; i++) {
            int index = (hash + i) % M;
            Key key2 = keys[index];

            // 找不到该键
            if(key2 == null) return null;

            // 找到了该键
            if(key.equals(key2)) {
                return values[index];
            }
        }
        return null;
    }

    public void put(Key key, Value value) {
        int hash = hash(key);
        for(int i=0; i < M; i++) {
            int index = (hash+i) % M;
            Key key2 = keys[index];

            // 找到了空位
            if(key2 == null) {
                keys[index] = key;
                values[index] = value;
                return;
            }

            // 找到了已经存在的值
            if(key.equals(key2)) {
                values[index] = value;
                return;
            }
        }
    }

    private int hash(Key key) {
        return (key.hashCode() & 0x7fffffff) % M;
    }
}

性能

随着数据量的增加,由于冲突的哈希值增加因此速度会越来越慢。在冲突很少的情况下,每个操作的复杂度近似为1。在冲突非常多的情况下,每个操作的复杂度可达到N。所以一般取M=N/2,这样性能最佳,又不浪费空间。

Knuth停车问题

有一个固定大小的停车场,每辆车都会在随机的位置i停下,如果停车位i已经被占用了,那么寻找停车位i+1、i+2等。

线性探针算法其实就是Knuth停车问题。http://arxiv.org/abs/math/0502220

算法6-3:解决哈希冲突之线性探针

时间: 2024-10-12 12:23:23

算法6-3:解决哈希冲突之线性探针的相关文章

算法学习 - HashTable开放地址法解决哈希冲突

开放地址法解决哈希冲突 线性开放地址法 线性开放地址法就是在hash之后,当发现在位置上已经存在了一个变量之后,放到它下一个位置,假如下一个位置也冲突,则继续向下,依次类推,直到找到没有变量的位置,放进去. 平方开放地址法 平方地址法就是在hash之后,当正确位置上存在冲突,不放到挨着的下一个位置,而是放到第2^0位置,假如继续冲突放到2^1的位置,依次2^3... 直到遇到不冲突的位置放进去. 双散列开放地址法 双散列同上,不过不是放到2^的位置,而是放到key - hash(key, tab

算法学习 - Hash Table操作,分离链接法解决哈希冲突

分离链接法 hash table是映射机制的,最大的优点就是它的操作是O(1)级别的.但是会出现哈希冲突,这就需要几种办法来解决.这里先说一种:分离链接法. 就是当插入的位置已经存在一个值之后,那么在这个值之后插入,就可以了,也叫拉链法.(但是其实会降低查找速度,变成O(n)级别) 下面是代码: // // main.cpp // HashTable_SeparateChaining // // Created by Alps on 14-8-5. // Copyright (c) 2014年

算法6-2:解决哈系冲突之独立链表

独立链表是解决哈希冲突的一种办法.它的基本思想就是将哈希值相互冲突的几个对象放到一个链表中. 代码 public class HashST<Key, Value> { private static class Node { Object key; // 由于无法创建泛型数组,只能将对象设置为Object类 Object value; Node next; public Node(Object key, Object value, Node next) { this.key = key; thi

【干货】C++哈希桶(开链法解决哈希冲突)类的实现

开链法(哈希桶)是解决哈希冲突的常用手法,结构如下: 数据结构的设计思路是这样的,定义一个K-V的链式节点(Node),以数组方式存储节点指针 实现代码如下: #include<vector> #include"HashTable.h" size_t GetSize() { static size_t index = 0; const int _PrimeSize = 28; static const unsigned long _PrimeList[_PrimeSize]

处理哈希冲突的线性探测法

哈希表,是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录的数组称做散列表.(摘自维基百科) 对不同的关键字可能得到同一散列地址,即k1!=k2,而f(k1)=f(k2),这种现象称为碰撞(英语:Collision),也叫哈希冲突. 处理哈希冲突的方法有很多种: 闭散列法 开链法(哈希桶) 素数表 字符串哈希算法 在这里我们讨论最简单的闭散

浅谈算法和数据结构: 十一 哈希表

在前面的系列文章中,依次介绍了基于无序列表的顺序查找,基于有序数组的二分查找,平衡查找树,以及红黑树,下图是他们在平均以及最差情况下的时间复杂度: 可以看到在时间复杂度上,红黑树在平均情况下插入,查找以及删除上都达到了lgN的时间复杂度. 那么有没有查找效率更高的数据结构呢,答案就是本文接下来要介绍了散列表,也叫哈希表(Hash Table) 什么是哈希表 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 哈希的思路很简单

【数据结构】哈希表的线性探测算法

构造哈希表常用的方法是: 除留余数法--取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址.HashKey= Key % P. 直接定址法--取关键字的某个线性函数为散列地址HashKey= Key 或 HashKey= A*Key + BA.B为常数. 我在这里主要使用一下除留余数法Hash(key) =Key%P,(P这里是哈希表的长度)p最好是素数考虑降低哈希冲突的原因,我并没有在这上面过于追究此处哈希表长度10,见线性探测图. 哈希表经常遇到的一个问题就是哈希冲突. 哈希冲突

一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)

面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部结构 Linux 查询含有某字符串内容的命令grep 查询进程.GC状态.杀死进程 Hadoop五种节点介绍 -----------------------------------------------------------------------------------------------

算法与数据结构之哈希表

哈希表:是一种key-value存储数据的结构 使用哈希表的两个步骤: 1.无序数组:将键值key转化为对应的索引(f(key)),根据索引来寻找对应的值(value) 2.解决哈希冲突:当key值不同,但f(key)相同 哈希函数:将key映射到对应的索引的映射函数f(x)即为哈希函数. 1.键为整数时,哈希函数一般为除留余数法.即对于大小为素数M的数组,对于任意正整数k,计算k除以M的余数.M一般取素数. 2.键为字符串时, 1>.将组成字符串的每一个字符取值然后进行哈希    h = s[