【问题标题】:Resizing a HashMap with quadratic probing (backing array implementation)使用二次探测调整 HashMap 的大小(支持数组实现)
【发布时间】:2015-06-27 21:14:54
【问题描述】:

在我检查负载因子是否指示要调整后备数组的大小后,我实际上如何通过二次探测来调整大小?

这里是代码。 这只是课堂的一部分。另外,你能检查一下我是否正确地实现了 add 方法吗?

import java.util.*;

public class HashMap<K, V> implements HashMapInterface<K, V> {

// Do not make any new instance variables.
private MapEntry<K, V>[] table;
private int size;

/**
 * Create a hash map with no entries.
 */
public HashMap() {
    table = new MapEntry[STARTING_SIZE];
    size = 0;
}

@Override
public V add(K key, V value) {
    if (key == null || value == null) {
        throw new IllegalArgumentException("Passed in null arguments.");
    }
    if (getNextLoadFactor() > MAX_LOAD_FACTOR) {
        resize();
    }
    MapEntry<K, V> entry = new MapEntry<>(key, value);
    V val = null;
    int index = Math.abs(key.hashCode()) % table.length;
    int temp = index;
    int q = 1;
    do {
        if (table[index] == null) {
            table[index] = entry;
        } else if (table[index].getKey().equals(key)) {
            val = table[index].getValue();
            table[index].setValue(value);
        }
        index = index + q*q % table.length;
        q++;
    } while (temp != index);
    size++;
    return val;
}

private double getNextLoadFactor() {
    return (double) size / (double) table.length;
}

private void resize() {
    MapEntry<K, V>[] temp = table;
    table = new MapEntry[table.length * 2 + 1];
    for (int i = 0; i < table.length; i++) {

    }
}

【问题讨论】:

    标签: java resize hashmap quadratic-probing


    【解决方案1】:

    从 wiki 遵循以下内容:

     1. Get the key k
     2. Set counter j = 0
     3. Compute hash function h[k] = k % SIZE
     4. If hashtable[h[k]] is empty
             (4.1) Insert key k at hashtable[h[k]]
             (4.2) Stop
        Else
            (4.3) The key space at hashtable[h[k]] is occupied, so we need to find the next available key space
            (4.4) Increment j
            (4.5) Compute new hash function h[k] = ( k + j * j ) % SIZE
            (4.6) Repeat Step 4 till j is equal to the SIZE of hash table
     5. The hash table is full
     6. Stop
    

    根据上述情况,在我看来,您的add 方法有问题。注意步骤(4.1)和(4.2):如果table[index] == null,则已找到键的位置,您可以停止。你的do 将再次执行,因为在插入之后,你更新了索引,因此temp != index 将是真的。

    你也是计算下一个索引不正确,改一下

    index = index + q*q % table.length;
    

    index = (Math.abs(key.hashCode()) + q*q) % table.length;
    

    add 将因此更改为:

    MapEntry<K, V> entry = new MapEntry<>(key, value);
    V val = null;
    int index = Math.abs(key.hashCode()) % table.length;
    
    int q = 0;
    
    while (table[(index = (Math.abs(key.hashCode()) + q*q++) % table.length)] != null);
    
    table[index] = entry;
    size++;
    return val;
    

    可以证明,如果b &gt; 3 的第一个b/2 位置的表大小b 将是唯一的,因此可以安全地假设如果表小于一半(b/2 - 1),您会找到一个空的位置。这取决于您的MAX_LOAD_FACTOR

    为了调整大小,您需要将每个值重新散列到新表中。这是由于您的哈希函数使用表的大小作为模数。你的哈希函数基本变了,所以你需要创建size + 1的新数组,并将每个元素读入新数组。

    private void resize() {
        MapEntry<K, V>[] temp = table;
        table = new MapEntry[table.length * 2 + 1];
        for (MapEntry<K, V> entry:temp) {
            this.add(entry.getKey(), entry.getValue());
        }
    }
    

    注意:我没有对此进行测试,仅使用动态探测和哈希表背后的理论来调试您的代码。希望对您有所帮助!

    【讨论】:

    • 谢谢!我稍后再试。
    猜你喜欢
    • 2020-12-09
    • 1970-01-01
    • 2013-04-17
    • 2021-02-25
    • 2017-05-20
    • 2022-11-06
    • 1970-01-01
    • 2016-05-14
    • 2013-04-06
    相关资源
    最近更新 更多