使用二次探测(支持数组实现)调整HashMap的大小

时间:2015-04-20 22:54:52

标签: java resize hashmap quadratic-probing

在检查负载因子是否表示要调整后备阵列的大小后,如何使用二次探测实际调整大小?

这是代码。 它只是课堂的一部分。另外,您能否检查我是否正确实施了添加方法?

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++) {

    }
}

1 个答案:

答案 0 :(得分: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;

可以证明,如果bb > 3位置的表格大小b/2将是唯一的,那么可以安全地假设如果表格小于一半完整(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());
    }
}

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