公告

👇 微信 👇

图片

欢迎私信交流

Skip to content

11-散列表 ​

算法思想 ​

散列表 ​

  • 散列表是可以根据键直接访问存储位置的数据结构

哈希函数 ​

  • 除留余数法: h(k) = k mod m
  • m 的选取原则:m 选取一个素数,且远离 2 的幂,以避免模式化冲突

算法模板 ​

拉链法 ​

java
import java.util.*;
public class Main {
    // 临近100000的最大素数
    static int N = 100003;
    // e[i]存储第 i 个节点的数值
    static int[] e = new int[N],
    // ne[i]存储第 i 个节点的下一个节点的索引
        ne = new int[N],
    // h[i] 存储第 i 个拉链的头结点的下一个节点的索引
    // 头结点是个虚拟节点(并不存在),空节点的索引为 -1
        h = new int[N];
    static int idx;


    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Arrays.fill(h, -1);
        
        while(n -- > 0)
        {
            String s = sc.next();
            int x = sc.nextInt();
            if(s.equals("I")) insert(x);
            else
            {
                String res = (find(x)) ? "Yes" : "No";
                System.out.println(res);
            }
        }
    }
    
    public static void insert(int x)
    {
        // k = x % N
        // 在数学运算中,k 一定为正数
        // 在Java运算中,k 可能为负数
        // 为确保 k 为正数,执行 + N % N 操作
        int k = (x % N + N) % N;
        e[idx] = x;
        ne[idx] = h[k];
        h[k] = idx ++;
    }
    
    public static boolean find(int x)
    {
        int k = (x % N + N) % N;
        for(int i = h[k]; i != -1; i = ne[i])
        {
            if(e[i] == x) return true;
        }
        return false;
    }
}

开放寻址法 ​

java
import java.util.*;

public class Main {
    // 极端情况下,所有数值都映射到数组 h 的最后一个位置
    // N > 2 * maxN,确保不会出问题
    static int N = 200003;
    static int[] h = new int[N];
    // 节点值为 NULL 表示节点为空节点
    // NULL > 1e9 
    static int NULL = 0x3f3f3f3f;

    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Arrays.fill(h, NULL);
        
        while(n -- > 0)
        {
            String op = in.next();
            int x = in.nextInt();
            
            if(op.equals("I")) h[find(x)] = x;
            else
            {
                var res = (h[find(x)] != NULL) ? "Yes" : "No";
                System.out.println(res);
            }
        }
    }
    // 若找不到,则返回可以存放 x 的正确位置    
    static int find(int x)
    {
        int k = (x % N + N) % N;
        while(h[k] != NULL && h[k] != x)
        {
            k ++;
            // 后面没找到空的位置,从头开始寻找
            if(k == N) k = 0;
        }
        return k;
    }
}