解决哈希冲突的四种方法

在哈希表中,哈希冲突是指不同的键值对被映射到相同的哈希桶中的情况。解决哈希冲突是哈希表设计中的一个重要问题。本文将介绍四种常见的解决哈希冲突的方法,并提供相应的Java代码示例。

方法一:链地址法(Separate Chaining)

链地址法是一种简单而常用的解决哈希冲突的方法。在链地址法中,每个哈希桶都是一个链表,当多个键值对映射到同一个哈希桶时,它们都会被存储在链表中。当需要查找或删除某个键值对时,需要遍历链表来查找对应的元素。

下面是一个使用链地址法解决哈希冲突的示例代码:

import java.util.LinkedList;

public class SeparateChainingHash {
    private LinkedList<Pair>[] hashTable;
    private int capacity;

    public SeparateChainingHash(int capacity) {
        this.capacity = capacity;
        this.hashTable = new LinkedList[capacity];
        for (int i = 0; i < capacity; i++) {
            hashTable[i] = new LinkedList<>();
        }
    }

    private int hash(int key) {
        return key % capacity;
    }

    public void put(int key, int value) {
        int index = hash(key);
        LinkedList<Pair> bucket = hashTable[index];
        for (Pair pair : bucket) {
            if (pair.key == key) {
                pair.value = value;
                return;
            }
        }
        bucket.add(new Pair(key, value));
    }

    public int get(int key) {
        int index = hash(key);
        LinkedList<Pair> bucket = hashTable[index];
        for (Pair pair : bucket) {
            if (pair.key == key) {
                return pair.value;
            }
        }
        return -1;
    }

    public void remove(int key) {
        int index = hash(key);
        LinkedList<Pair> bucket = hashTable[index];
        for (Pair pair : bucket) {
            if (pair.key == key) {
                bucket.remove(pair);
                return;
            }
        }
    }

    private class Pair {
        int key;
        int value;

        Pair(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }
}

方法二:开放地址法(Open Addressing)

开放地址法是另一种解决哈希冲突的方法。在开放地址法中,当发生哈希冲突时,会顺序地寻找下一个可用的哈希桶,直到找到一个空桶或者遍历完所有的桶。开放地址法有多种实现方式,比如线性探测、二次探测等。

下面是一个使用线性探测解决哈希冲突的示例代码:

public class LinearProbingHash {
    private int[] keys;
    private int[] values;
    private int capacity;
    private int size;

    public LinearProbingHash(int capacity) {
        this.capacity = capacity;
        this.keys = new int[capacity];
        this.values = new int[capacity];
    }

    private int hash(int key) {
        return key % capacity;
    }

    public void put(int key, int value) {
        if (size >= capacity) {
            throw new IllegalStateException("Hash table is full.");
        }
        int index = hash(key);
        while (keys[index] != 0 && keys[index] != -1) {
            if (keys[index] == key) {
                values[index] = value;
                return;
            }
            index = (index + 1) % capacity;
        }
        keys[index] = key;
        values[index] = value;
        size++;
    }

    public int get(int key) {
        int index = hash(key);
        while (keys[index] != 0) {
            if (keys[index] == key) {
                return values[index];
            }
            index = (index + 1) % capacity;
        }
        return -1;
    }

    public void remove(int key) {
        int index = hash(key);
        while (keys[index] != 0) {
            if (keys[index] == key) {
                keys[index] = -1;
                values[index] = 0;
                size--;
                return;
            }
            index = (index + 1) % capacity;
        }
    }
}

方法三:再哈希法(Double Hashing)

再哈希法是一种开放地址法的改进方法