哈希表实现

哈希和树的区别一个是表结构,一个是树结构

在这里插入图片描述
一般哈希值通过 key % arr.length 获得
可是如果哈希值相同了怎么办呢?
这就叫哈希冲突

解决哈希冲突

有两种方法:

  1. 闭散列:线性探测,二次探测
  2. 开散列:又称为哈希桶,拉链法

在这里插入图片描述
在这里插入图片描述
注意:任何情况下,哈希表都不会存满数据,数据越多,哈希冲突的概率越大,一般当负载因子大于或者等于某一个阈值(0.7)时, 就需要进行扩容

开散列:

哈希桶就是在每个表格中建立一个链表,这样在哈希冲突时就可以进行头插。
数组中存放每一个单链表的头节点,有哈希冲突的数据,会存入单链表中,相同哈希值的数据会在同一个单链表中
在这里插入图片描述

代码

public class HashBucket {
    private static class Node {
        int key;
        int value;
        Node next = null;
        public Node (int key, int value) {
            this.key = key;
            this.value = value;
            next = null;
        }
    }

    private Node[] array;
    private int size;
    //设置负载因子不超过0.7
    private static final double LOAD_FACTORY = 0.7;

    public HashBucket() {
        //设置是两个空位置的表
        array = new Node[2];
        size = 0;
    }

    public double loadFactory() {
        return size * 1.0 / array.length;
    }

    //插入
    public int put(int key, int value) {
        //检查容量
        if (loadFactory() >= LOAD_FACTORY) {
            //增容
            resize();
        }
        //插入
        //1.计算哈希值
        int idx = key % array.length;
        //2.不能插入重复的key,首先要查看key是否已经存在,遍历当前位置的单链表
        Node cur = array[idx];
        while (cur != null) {
            if (cur.key == key) {
                int oldV = cur.value;
                cur.value = value;
                return oldV;
            }
            cur = cur.next;
        }
        //找到位置进行插入
        cur = new Node(key, value);
        cur.next = array[idx];
        array[idx] = cur;
        size++;
        return  -1;
    }

    private void resize() {
        Node[] newArray = new Node[array.length * 2];
        //元素搬移
        //遍历旧表
        for (int i = 0; i < array.length; i++) {
            Node curHead = array[i];
            while (curHead != null) {
                Node next = curHead.next;
                //计算当前元素在新表中的位置
                int idx = curHead.key % newArray.length;
                //头插
                curHead.next = newArray[idx];
                newArray[idx] = curHead;
                curHead = next;
            }
        }
        array = newArray;
    }

    public int get(int key) {
        //只需要搜索表中的一个单链表即可
        int idx = key % array.length;
        Node cur = array[idx];
        while (cur != null) {
            if (cur.key == key){
                return cur.value;
            }
            cur = cur.next;
        }
        return -1;
    }

    public int remove(int key) {
        int idx = key % array.length;
        Node prev = null;
        Node cur = array[idx];
        //删除单链表
        while (cur != null) {
            if (cur.key == key) {
                if (prev == null) {
                    //删除头节点
                    array[idx] = cur.next;
                } else {
                    prev.next = cur.next;
                }
            } else {
                prev = cur;
                cur = cur.next;
            }
        }
        return -1;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值