【问题标题】:Why does this implementation of Quadratic Probing fail when not overriding values on collision?为什么在不覆盖碰撞值时,这种二次探测的实现会失败?
【发布时间】:2019-06-12 00:55:54
【问题描述】:

当发生碰撞时,我当前的二次探测实现会用新项目覆盖存储在当前索引处的项目。我插入三个 Person 对象,这些对象是通过使用他们的姓氏作为键来存储的。为了测试实现的冲突解决方案,它们都具有相同的姓氏,即“Windmill”。

我需要实现来保留所有人员对象,但只需将它们移动到不同的索引而不是覆盖它们。

列表大小已设置为 7,存储在变量“M”中,用于插入函数中的取模。

插入函数

@Override
public void put(String key, Person value) {
   int tmp = hash(key);
   int i, h = 0;

    for (i = tmp; keys[i] != null; i = (i + h * h++) % M) {
        collisionCount++;

        if (keys[i].equals(key))  { 
            values[i] = value;
            return; 
        } 
    }

    keys[i] = key;
    values[i] = value;
    N++;
}

哈希函数

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

获取函数

@Override
public List<Person> get(String key) {
    List<Person> results = new ArrayList<>();

    int tmp = hash(key);
    int i = hash(key), h = 0;

    while (keys[i] != null)
    {
        if (keys[i].equals(key))
            results.add(values[i]);

        i = (i + h * h++) % M;
    }   

    return results;
}

当我删除覆盖先前值的代码时,索引 int 溢出并变成负数,导致程序崩溃。

【问题讨论】:

    标签: java hash quadratic-probing


    【解决方案1】:

    你得到溢出是因为你在一些导致溢出的整数操作之后执行% M。 您需要将i = (i + h * h++) % M 替换为一些基于模运算属性的附加运算(https://en.wikipedia.org/wiki/Modulo_operation):

    • (a + b) mod n = [(a mod n) + (b mod n)] mod n。
    • ab mod n = [(a mod n)(b mod n)] mod n.

    【讨论】:

    • 您能否更具体地说明我应该执行哪种附加操作?
    【解决方案2】:

    我认为您的代码有两个问题:

    1. 您不检查(多)地图是否已满。在实践中,您希望进行 2 次检查:

      • 检查是否N==M(或者可能是一些较小的阈值,例如M 的90%)
      • collisionCount设为局部变量,当它到达N时(不幸的是,为了避免一些病理情况,这个检查也是必要的)

    在这两种情况下,您都应该扩展存储区域并将旧数据复制到其中(重新插入)。仅此一项就可以解决M 的小值的错误,但对于真正大尺寸的地图,您仍然需要下一个东西。

    1. 您没有考虑到 mod (%) 操作在 Java 中是如何工作的。特别是对于a 的负值,a % b 的值也是负值。因此,当您插入大量值并检查下一个索引时,i + h^2 可能会溢出Integer.MAX_VALUE 并变为负数。要解决此问题,您可以使用如下方法:
    static int safeMod(int a, int b) {
         int m = a % b;
         return (m >= 0) ? m : (m+b);
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多