Skip to content

跳房子散列注释 #16

@fuzhengwei

Description

@fuzhengwei
public class HashMap06ByHopscotchHashing<AnyType> {

    private static final int DEFAULT_TABLE_SIZE = 8; // 默认哈希表大小
    private static final int RANGE = 8; // 范围
    private HashEntry<AnyType>[] array; // 哈希表数组
    private int occupied; // 已占用的槽位数量
    private int theSize; // 哈希表中元素的数量

    public HashMap06ByHopscotchHashing() {
        this(DEFAULT_TABLE_SIZE); // 使用默认哈希表大小初始化哈希表
    }

    public HashMap06ByHopscotchHashing(int size) {
        allocateArray(size); // 分配哈希表数组的空间
        doClear(); // 清空哈希表
    }

    private void allocateArray(int arraySize) {
        array = new HashEntry[arraySize]; // 创建指定大小的哈希表数组
    }

    private void doClear() {
        occupied = 0; // 已占用槽位数量置为0
        Arrays.fill(array, null); // 将哈希表数组中的元素都置为null
    }

    private int myhash(AnyType x) {
        int hashVal = x.hashCode(); // 获取元素的哈希值

        hashVal %= array.length; // 取模运算,将哈希值映射到哈希表数组的索引范围内
        if (hashVal < 0)
            hashVal += array.length; // 如果哈希值为负数,则加上数组长度,使其变为非负数

        return hashVal; // 返回哈希值对应的索引
    }

    public boolean insert(AnyType x) {

        if (!isEmpty()) { // 如果哈希表不为空,则返回false
            return false;
        }

        int currentPos = findPos(x); // 查找元素在哈希表中的位置

        if (currentPos == -1) { // 如果找不到合适的位置,则返回false
            return false;
        }

        if (array[currentPos] != null) { // 如果当前位置已经有元素,则将其标记为活跃状态
            x = array[currentPos].element;
            array[currentPos].isActive = true;
        }

        String hope;
        if (array[currentPos] != null) { // 如果当前位置已经有元素,则获取其希望值和元素值
            hope = array[currentPos].hope;
            x = array[currentPos].element;
        } else {
            hope = "10000000"; // 如果当前位置没有元素,则设置希望值为"10000000"
        }

        array[currentPos] = new HashEntry<>(x, hope, true); // 在当前位置插入元素
        theSize++; // 哈希表中元素数量加1

        return true; // 插入成功,返回true
    }

    private int findPos(AnyType x) {
        int offset = 0; // 偏移量
        int currentPos = myhash(x); // 获取元素在哈希表中的初始位置
        int startPosition = currentPos; // 记录初始位置
        int original = startPosition; // 记录初始位置
        boolean flag = false; // 标记是否需要进行跳跃
        boolean f = false; // 标记是否需要进行下一次跳跃
        while (array[currentPos] != null) { // 当前位置已经有元素
            currentPos++; // 继续向后查找

            if (currentPos - startPosition >= 8 // 如果当前位置与初始位置的距离大于等于8
                    || (((currentPos) < startPosition) && (array.length // 或者当前位置小于初始位置且数组长度减去初始位置加上当前位置大于等于8
                    - startPosition + currentPos) >= 8)) {
                f = true; // 设置f为true
            }
            if (f // 如果f为true
                    && ((myhash(array[startPosition].element) - currentPos) >= RANGE // 如果初始位置元素的哈希值与当前位置的差值大于等于范围
                    || (currentPos - myhash(array[startPosition].element)) >= RANGE // 或者当前位置与初始位置元素的哈希值的差值大于等于范围
                    || ((currentPos - myhash(array[startPosition].element)) < 0 && (array.length // 或者当前位置与初始位置元素的哈希值的差值小于0且数组长度减去初始位置元素的哈希值加上当前位置大于等于8
                    - myhash(array[startPosition].element) + currentPos) >= 8))) {
                flag = true; // 设置flag为true
                currentPos = nextJumpPosition(startPosition); // 获取下一次跳跃的位置
                if (currentPos == -2) { // 如果下一次跳跃的位置为-2,则返回-1
                    return -1;
                }
                startPosition = currentPos; // 更新初始位置
                offset = 0; // 偏移量置为0
            }
            if (currentPos >= array.length) { // 如果当前位置超出数组长度,则将其置为0
                currentPos = 0;
            }
        }

        if (flag) { // 如果需要进行跳跃
            array[currentPos] = new HashEntry<>(array[startPosition].element, // 在当前位置插入元素
                    "00000000", true);
            StringBuilder string = new StringBuilder( // 获取初始位置元素的希望值
                    array[myhash(array[startPosition].element)].hope);
            if ((currentPos - myhash(array[startPosition].element)) < 0) { // 如果当前位置与初始位置元素的哈希值的差值小于0
                string.setCharAt(array.length // 将希望值中对应位置的字符置为'1'
                                - myhash(array[startPosition].element) + currentPos,
                        '1');
            } else {
                string.setCharAt(currentPos // 将希望值中对应位置的字符置为'1'
                        - myhash(array[startPosition].element), '1');
            }
            array[myhash(array[startPosition].element)].hope = string // 更新初始位置元素的希望值
                    .toString();
            if (array[myhash(array[startPosition].element)].hope // 如果初始位置元素的希望值中对应位置的字符为'1'
                    .charAt(startPosition
                            - myhash(array[startPosition].element)) == '1') {
                string = new StringBuilder( // 将希望值中对应位置的字符置为'0'
                        array[myhash(array[startPosition].element)].hope);
                string.setCharAt(
                        (startPosition - myhash(array[startPosition].element)),
                        '0');
                array[myhash(array[startPosition].element)].hope = string
                        .toString();
            }
            AnyType x1 = x;
            array[startPosition] = new HashEntry<>(x1, // 在初始位置插入元素
                    array[startPosition].hope, true);
            StringBuilder temp = new StringBuilder(array[myhash(x1)].hope); // 获取元素的希望值
            if (startPosition - myhash(x1) < 0) { // 如果初始位置与元素的哈希值的差值小于0
                temp.setCharAt(array.length - myhash(x1) + startPosition, '1'); // 将希望值中对应位置的字符置为'1'
            } else {
                temp.setCharAt(startPosition - myhash(x1), '1'); // 将希望值中对应位置的字符置为'1'
            }
            array[myhash(x1)].hope = temp.toString(); // 更新元素的希望值
            currentPos = startPosition; // 将当前位置置为初始位置
        } else {
            if (startPosition != currentPos) { // 如果初始位置与当前位置不相等
                array[currentPos] = new HashEntry<>(x, "00000000", true); // 在当前位置插入元素
                StringBuilder temp = new StringBuilder( // 获取初始位置元素的希望值
                        array[startPosition].hope);
                int p;
                if (currentPos - startPosition < 0) { // 如果当前位置与初始位置的差值小于0
                    p = array.length - startPosition + currentPos; // 计算希望值中对应位置的索引
                    temp.setCharAt(p, '1'); // 将希望值中对应位置的字符置为'1'
                } else {
                    temp.setCharAt(currentPos - startPosition, '1'); // 将希望值中对应位置的字符置为'1'
                }

                AnyType x1 = array[startPosition].element;
                array[startPosition] = null; // 将初始位置置为null
                array[startPosition] = new HashEntry<>(x1, temp.toString(), // 在初始位置插入元素
                        true);
                currentPos = startPosition; // 将当前位置置为初始位置
            }
        }

        return currentPos; // 返回当前位置
    }

    private boolean isEmpty() {
        for (HashEntry<AnyType> anyTypeHashEntry : array) { // 遍历哈希表数组
            if (anyTypeHashEntry == null) { // 如果数组中有元素为null,则返回true
                return true;
            }
        }
        return false; // 否则返回false
    }

    private int nextJumpPosition(int startPosition) {
        int position = startPosition + 1; // 下一次跳跃的位置为初始位置加1
        int c = checkHope(position); // 检查希望值
        while (c == -1) { // 如果希望值为-1
            if (position >= array.length) { // 如果位置超出数组长度,则将其置为0
                position = 0;
                c = checkHope(position); // 检查希望值
            }
            if (position == startPosition) { // 如果位置与初始位置相等,则返回-2
                return -2;
            }
            c = checkHope(position++); // 检查希望值
        }
        return c; // 返回下一次跳跃的位置
    }

    private int checkHope(int position) {
        if (array[position] != null // 如果当前位置有元素且希望值不为"00000000"或"00000001"
                && (!array[position].hope.equals("00000000") && !array[position].hope
                .equals("00000001"))) {
            for (int i = 0; i < array[position].hope.length(); i++) { // 遍历希望值
                if (array[position].hope.charAt(i) == '1') { // 如果希望值中有字符为'1',则返回当前位置加上索引
                    return position + i;
                }
            }
        }
        return -1; // 否则返回-1
    }

    private static class HashEntry<AnyType> {
        public AnyType element; // 元素值
        public String hope; // 希望值
        public boolean isActive; // 是否为活跃状态

        public HashEntry(AnyType e) {
            this(e, true); // 调用另一个构造函数
        }

        public HashEntry(AnyType e, boolean i) {
            element = e; // 初始化元素值和活跃状态
            isActive = i;
        }

        public HashEntry(AnyType e, String h, boolean i) {
            element = e; // 初始化元素值、希望值和活跃状态
            hope = h;
            isActive = i;
        }
    }

    @Override
    public String toString() {
        return "HashMap{" +
                "tab=" + JSON.toJSONString(array) + // 将哈希表数组转换为JSON字符串
                '}';
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions