哈希表

本文最后更新于:2022年12月13日 晚上

哈希表

应用背景

Google上机题

看一个实际需求,Google公司的一个上机题:

有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址…),当输入该员工的id时,要求查找到该员工的所有信息.
要求:不使用数据库,尽量节省内存,速度越快越好

这时候就暗示要使用哈希表(散列)

减少数据库查询次数

可用于数据库和业务层(Java程序)之间的缓存层,从而减少数据库查询次数。

基本介绍

散列表 (Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

HashTable

实现思路

创建一个数组,数组每个元素存放一条链表,使用一种散列函数(如除余),使每个结点分散存放到指定链表。

代码实现

hashTable类,包括测试

public class HashTable {

    // 测试
    public static void main(String[] args) {
        HashTable hashTable = new HashTable(8);
        Emp emp1 = new Emp(1, "Yorick");
        Emp emp2 = new Emp(2, "Jerry");
        Emp emp3 = new Emp(3, "Lily");
        Emp emp4 = new Emp(4, "Tom");
        Emp emp5 = new Emp(4, "Sia");
        Emp emp10 = new Emp(10, "Jim");
        Emp emp11 = new Emp(11, "Merry");
        Emp emp12 = new Emp(12, "Jack");
        Emp emp13 = new Emp(13, "Mike");
        Emp emp23 = new Emp(23, "Smith");
        hashTable.add(emp1);
        hashTable.add(emp2);
        hashTable.add(emp3);
        hashTable.add(emp4);
        hashTable.add(emp5);
        hashTable.add(emp10);
        hashTable.add(emp11);
        hashTable.add(emp12);
        hashTable.add(emp13);
        hashTable.add(emp23);
        hashTable.list();
        hashTable.find(11);
        hashTable.del(3);
        hashTable.list();
    }

    private final int size;
    private final EmpLinkedList[] empLinkedLists;

    public HashTable(int tableLength) {
        this.size = tableLength;
        empLinkedLists = new EmpLinkedList[tableLength];
        for (int i = 0; i < size; i++) {
            empLinkedLists[i] = new EmpLinkedList();
        }
    }

    // 增加
    public void add(Emp emp) {
        getListNo(emp.getId());
        empLinkedLists[emp.getId() % size].add(emp);
    }

    // 遍历
    public void list() {
        for (int i = 0; i < size; i++) {
            System.out.print("第 " + (i + 1) + " 条 ");
            empLinkedLists[i].list();
        }
    }

    // 查找
    public void find(int id) {
        EmpLinkedList empLinkedList = getListNo(id);
        Emp emp = empLinkedList.find(id);
        if (emp == null) {
            System.out.println("未找到ID为 " + id + " 的结点");
        } else {
            System.out.println("此ID对应姓名为:" + emp.getName());
        }
    }

    // 删除
    public void del(int id) {
        empLinkedLists[id % size].del(id);
    }

    // 获取id所在链表
    public EmpLinkedList getListNo(int id) {
        return empLinkedLists[id % size];
    }
}

单链表EmpLinkedList

public class EmpLinkedList {

    public Emp head = null;

    // 增加结点
    public void add(Emp emp) {
        // 如果链表为空,将第一个插入值作为头结点
        if (isEmpty()) {
            head = emp;
            return;
        }
        // 辅助指针
        Emp helper = head;
        while (helper.next != null && emp.getId() > helper.next.getId()) {
            helper = helper.next;
        }
        Emp temp = helper.next;
        helper.next = emp;
        emp.next = temp;
    }

    // 遍历链表
    public void list() {
        if (isEmpty()) {
            System.out.println("NULL");
            return;
        }
        Emp helper = head;
        while (helper != null) {
            System.out.printf("ID:%d NAME:%s\t", helper.getId(), helper.getName());
            helper = helper.next;
        }
        System.out.println();
    }

    public Emp find(int id) {
        if (isEmpty()) {
            System.out.println("链表为空");
            return null;
        }
        Emp helper = head;
        while (helper != null) {
            if (helper.getId() == id) {
                return helper;
            }
            helper = helper.next;
        }
        return null;
    }

    public void del(int id) {
        if (isEmpty()) {
            System.out.println("链表为空");
            return;
        }
        if (head.getId() == id) {
            head = head.next;
            return;
        }
        Emp helper = head;
        while (helper.next != null) {
            if (helper.next.getId() == id) {
                helper.next = helper.next.next;
                break;
            }
            helper = helper.next;
        }
        System.out.println("未找到ID为 " + id + " 的结点");
    }

    // 判断非空
    public boolean isEmpty() {
        return head == null;
    }
}

节点类Emp

public class Emp {
    private int id;
    private String name;
    public Emp next;

    public Emp(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

哈希表
http://yorick.love/2022/07/20/数据结构/数据结构_哈希表/
作者
Yorick
发布于
2022年7月20日
许可协议