java---哈希表插入和查询---数组模拟(每日一道算法2022.8.18)

两种方法,一种拉链法一种开放寻址法
拉链法涉及到单链表的运用,可以看我之前单链表的那篇文章:
java-单链表-数组模拟实现

题目
维护一个集合,支持如下几种操作:
I x,插入一个数 x;
Q x,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果

输入:
5
I 1
I 2
I 3
Q 2
Q 5
输出:
Yes
No

拉链法

public class 哈希表_模拟散列表 {
    //初始化,这里的哈希表用的是拉链法,每个hash槽位中镶嵌一个链表储存相同hash值的数据
    //注意,N最好取用比数据量大的最小质数,这样可以尽量避免hash值重复,具体可以自己去查,涉及一些数学知识,就不深讲了
    public static int N = 100003, index = 0;
    public static int[] hash = new int[N], e = new int[N], ne = new int[N];

    public static void main(String[] args) {
        //初始化,记得将hash数组全部设置为-1,这样才能符合链表的规则
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        Arrays.fill(hash, -1);

        //操作部分,插入和查找,比较简单就不多说了
        while (n-- > 0) {
            String[] data_arr = in.nextLine().split(" ");
            String model = data_arr[0];
            int x = Integer.parseInt(data_arr[1]);
            if (model.equals("I")) {
                insert(x);
            }
            else if (model.equals("Q")) {
                if (search(x)) {System.out.println("Yes");}
                else {System.out.println("No");}
            }
        }
    }

    //插入操作,和单链表很像,区别在于head我们使用的是hash[k]的值,而不是自己定义的head
    public static void insert(int x) {
    	//注意,在java和c中,负数进行%,结果会是负数,所以我们这里的操作就是让%的结果变为正数,类似绝对值
        int k = (x % N + N) % N;
        e[index] = x;
        ne[index] = hash[k];
        hash[k] = index++;
    }

    //查找操作,和单链表一致,head被替换为hash[k]
    public static boolean search(int x) {
        int k = (x % N + N) % N;
        for (int i = hash[k]; i!=-1; i = ne[i]) {
            if (e[i] == x) {
                return true;
            }
        }
        return false;
    }
}

开放寻址法

public class 哈希表_开放寻址法 {
    //初始化,这里记得一点,使用开放寻址法的话,N要开到数据量的2-3倍左右才行
    public static int N = 200003;
    public static int[] hash = new int[N];

    public static void main(String[] args) {
        //初始化,hash数组初始全部为-1
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        Arrays.fill(hash, -1);

        while(n-- > 0) {
            //初始化
            String[] data_arr = in.nextLine().split(" ");
            String model = data_arr[0];
            int x = Integer.parseInt(data_arr[1]);

            //因为插入和查找都需要拿到x在hash数组中的位置,就先定义出来
            int hash_index = get_hash_index(x);
            if (model.equals("I")) {hash[hash_index] = x;}
            else if (model.equals("Q")) {
                if (hash[hash_index] == x) {System.out.println("Yes");}
                else {System.out.println("No");}
            }
        }
    }

    //hash index拿到的是x在hash数组中的位置
    public static int get_hash_index(int x) {
        //这里还是一样,拿到x的正hash值
        int k = (x % N + N) % N;
        //如果当前k存在值且不等于x,k就继续往后找
        while (hash[k]!=-1 && hash[k]!=x) {
            k++;
            //这里设置限制,如果k等于N了,那么hash值就应该从头开始用
            if (k==N) {k=0;}
        }
        return k;
    }
}

声明:算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值