23-哈希表

1. 概述

1.1 基本介绍

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

1.2 一个使用场景

2. 案例

有一个公司,当有新的员工来报道时,要求将该员工的信息(id, 性别, 年龄, 住址) 加入,当输入该员工的id时,要求查找到该员工的所有信息。要求: ① 不使用数据库,尽量节省内存,速度越快越好;② 添加时,保证按照id从低到高插入

2.1 思路分析

2.2 代码实现

public class HashTabDemo {
    public static void main(String[] args) {
        HashTab hashTab = new HashTab(7);
        for(int i = 0; i < 10; i++) {
            int num = (int) (Math.random()*1101);
            hashTab.add(new Emp(num, "emp_"+num));
        }
        hashTab.list();
        hashTab.add(new Emp(1, "emp_1"));
        hashTab.add(new Emp(1, "emp_1"));
        hashTab.add(new Emp(9999, "emp_9999"));
        hashTab.findEmpById(1);
        hashTab.deleteEmpById(1024);
        hashTab.add(new Emp(9999, "emp_9999"));
        hashTab.list();
    }
}

class HashTab {
    private EmpLinkedList[] empLinkedListArr;
    private int size; // 数组大小(链表条数)
    
    public HashTab(int size) {
        super();
        this.size = size;
        this.empLinkedListArr = new EmpLinkedList[size];
        // 上一行仅仅是创建了数组本身, 或者说这只是创建了size个引用(其值均为null)
        // 要初始化这些引用, 让他们分别指向具体的EmpLinkedList对象才行
        for(int i = 0; i < size; i++)
            empLinkedListArr[i] = new EmpLinkedList();
    }
    
    // 散列函数 (取模法)
    public int hashFunc(int id) {
        return id % size;
    }
    
    // 添加雇员
    public void add(Emp emp) {
        // 1. 根据员工id, 先得到该员工应加入 [哪一条链表 / 数组哪个索引] 下
        int empLinkedListNo = hashFunc(emp.id);
        // 2. 将emp添加到对应的链表中
        empLinkedListArr[empLinkedListNo].add(emp);
    }
    
    // 根据id查找雇员
    public void findEmpById(int id) {
        Emp emp =  empLinkedListArr[hashFunc(id)].findEmpById(id);
        if(emp != null)
            System.out.println(emp);
        else 
            System.out.println("没有找到该雇员");
    }
    
    public void deleteEmpById(int id) {
        Emp delEmp = empLinkedListArr[hashFunc(id)].deleteEmpById(id);
        if(delEmp != null)
            System.out.println(delEmp + "删除成功!");
        else 
            System.out.println("删除失败!");
    }
    
    // 遍历所有的链表
    public void list() {
        for(int i = 0; i<size; i++) {
            System.out.printf("empLinkedListArr[%d]: ", i);
            empLinkedListArr[i].list();
        }
        System.out.println("---------------------------------------------------");
    }
}

class EmpLinkedList {
    // 首结点(注意, 不是头结点!)
    public Emp head;
    
    // 添加雇员
    public void add(Emp emp) {
        if(head == null) { // 是该链表的第1个结点
             head = emp;
        } else { // 不是第1个
            if(emp.id < head.id) {
                emp.next = head;
                head = emp;
            } else if(emp.id == head.id) {
                System.out.println("id已存在, 添加失败!");
                return;
            } else {
                Emp curEmp = head;
                while (curEmp.next != null) {
                    if(curEmp.next.id > emp.id) {
                        break;
                    } else if(curEmp.next.id == emp.id) {
                        System.out.println("id已存在, 添加失败!");
                        return;
                    }
                    curEmp = curEmp.next;
                }
                emp.next = curEmp.next;
                curEmp.next = emp;
            }
        }
    }
    
    // 根据id查找雇员
    public Emp findEmpById(int id) {
        // 判断链表是否为空
        if(head == null) 
            return null;
        
        Emp curEmp = head;
        while(curEmp != null) {
            if(curEmp.id == id)
                return curEmp;
            curEmp = curEmp.next;
        }
        // 到这了的话说明链表里没这id对应的雇员
        return null;
    }
        
    public Emp deleteEmpById(int id) {
        // 判断链表是否为空
        if(head == null) 
            return null;

        Emp delEmp = null;
        // 待删雇员恰为首结点
        if(head.id == id) {
            delEmp = head;
            head = head.next;
            return delEmp; // !null → 找到了
        } else { // 非首结点
            Emp curEmp = head;
            while(curEmp.next != null) {
                if(curEmp.next.id == id) {
                    delEmp = curEmp.next;
                    curEmp.next = delEmp.next;
                    return delEmp; // !null → 找到了
                }
                curEmp = curEmp.next;
            }
            return delEmp; // null → 未找到拥有该id的雇员
        }
    }
    
    // 遍历链表的雇员信息
    public void list() {
        if(head == null) {
            System.out.println("该链表为空");
            return;
        } else {
            Emp curEmp = head;
            while(curEmp != null) {
                System.out.print(curEmp + " → ");
                curEmp = curEmp.next;
            }
            System.out.println();
        }
    }
}

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

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

    @Override
    public String toString() {
        return "[id=" + id + ", name=" + name + "]";
    }
}

一处细节

猜你喜欢

转载自www.cnblogs.com/liujiaqi1101/p/12327846.html
今日推荐