哈希表(散列表)

一、概念

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

哈希表可以用来做缓存,将经常需要用的从数据库中查询出来,并存入hash表。供下一次使用。

二、哈希表练习题

有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址…),当输入该员工的 id 时,要求查找到该员工的所有信息.
要求:

  1. 不使用数据库,速度越快越好=>哈希表(散列)
  2. 添加后,要求各条链表内按照 id 从低到高
  3. 使用链表来实现哈希表, 该链表不带表头[即: 链表的第一个结点就存放雇员信息]

图解:
哈希表(散列表)_第1张图片
代码实现:
Emp类:

public class Emp {
    private int no;
    private String name;
    private Emp next;// 指向下一个emp

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

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

    public Emp getNext() {
        return next;
    }

    public void setNext(Emp next) {
        this.next = next;
    }

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

    @Override
    public String toString() {
        return "Emp{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}

EmpLinkedList类

public class EmpLinkedList {

    private Emp head;

    public Emp getHead() {
        return head;
    }

    public void setHead(Emp head) {
        this.head = head;
    }


    /**
     * @Description: add 添加员工
     * @param: [emp]
     * @return: void
     * @auther: zqq
     * @date: 20/6/18 19:02
     */
    public void add(Emp emp){
        if (this.getHead() == null){ // 该链表还没有数据
            head = emp;
        }else {
            boolean flag = false;//标识是否已经插入
            Emp temp = this.getHead();
            if (emp.getNo() < temp.getNo()){ //如果比第一个emp的id小
                emp.setNext(temp);
                this.setHead(emp);
                flag = true;
            }else {
                while (temp.getNext() != null){
                    if (temp.getNo() == emp.getNo()){
                        System.out.println("编号为 "+emp.getNo()+" 的Emp已经存在,请重新设置");
                        return;
                    }
                    if (emp.getNo() < temp.getNext().getNo()){ //按照id顺序插入
                        emp.setNext(temp.getNext());
                        temp.setNext(emp);
                        flag = true;
                        break;
                    }
                    temp = temp.getNext();
                }
            }
            if (!flag){
                temp.setNext(emp);
            }
        }
    }

    /**
     * @Description: show      显示该链表的所有内容
     * @param: []
     * @return: void
     * @auther: zqq
     * @date: 20/6/18 17:29
     */
    public void show(){
        Emp temp = this.getHead();
        while (temp != null){
            System.out.print(" => "+temp);
            temp = temp.getNext();
        }
        System.out.println();
    }

    /**
     * @Description: findEmpById 根据编号查找内容
     * @param: [no]
     * @return: haseTable.Emp
     * @auther: zqq
     * @date: 20/6/18 17:29
     */
    public Emp findEmpById(int no){
        Emp temp = this.getHead();
        while (temp != null){
            if (temp.getNo() == no){
                return temp;
            }
            temp = temp.getNext();
        }
        return null;//没有找到
    }

    /**
     * @Description: deleteEmp 根据id删除Emp
     * @param: [no]
     * @return: haseTable.Emp
     * @auther: zqq
     * @date: 20/6/18 17:30
     */
    public void deleteEmp(int no){
        Emp temp = this.getHead();
        boolean flag = false; // 标识是否已经删除
        if (temp.getNo() == no){ //如果第一个数就是要删除的数
            head = temp.getNext();
            System.out.println("编号为 "+no+" 删除成功");
            flag = true;
        }else {
            while (temp != null){
                if (temp.getNext().getNo() == no){
                    temp.setNext(temp.getNext().getNext());// 删除
                    System.out.println("编号为 "+no+" 删除成功");
                    flag = true;
                    break;
                }
                temp = temp.getNext();
            }
        }
        if (!flag){
            System.out.println("编号为 "+no+" 的不存在");
        }
    }
}

HashTable类:

public class HashTable {
    private EmpLinkedList[] empLinkedLists;
    private int size;

    public HashTable(int size) {
        this.size = size;
        empLinkedLists = new EmpLinkedList[size];
        for (int i = 0; i < empLinkedLists.length; i++) { // 对hashtable里面的每一个EmpLinkedList初始化,不然会空指针
            empLinkedLists[i] = new EmpLinkedList();
        }
    }


    /**
     * @Description: add 添加
     * @param: [emp]
     * @return: void
     * @auther: zqq
     * @date: 20/6/18 17:45
     */
    public void add(Emp emp){
        int hashNo = hashFun(emp.getNo());
        empLinkedLists[hashNo].add(emp);
    }

    /**
     * @Description: show 显示链表信息
     * @param: []
     * @return: void
     * @auther: zqq
     * @date: 20/6/18 18:26
     */
    public void show(){
        for (int i = 0; i < empLinkedLists.length; i++) {
            if (empLinkedLists[i].getHead() == null){
                System.out.println("第 "+ (i + 1) +" 个链表为空");
            }else {
                System.out.print("第 "+ (i + 1) +" 个链表:");
                empLinkedLists[i].show();
            }
        }
    }

    /**
     * @Description: findEmpById 通过id查找Emp
     * @param: [no]
     * @return: hashTable.Emp
     * @auther: zqq
     * @date: 20/6/18 18:27
     */
    public Emp findEmpById(int no){
        int hashNo = hashFun(no);
        return empLinkedLists[hashNo].findEmpById(no);
    }

    /**
     * @Description: deleteEmp 删除Emp
     * @param: [no]
     * @return: void
     * @auther: zqq
     * @date: 20/6/18 18:30
     */
    public void deleteEmp(int no){
        int hashNo = hashFun(no);
        empLinkedLists[hashNo].deleteEmp(no);
    }

    /**
     * @Description: hashFun 散列函数
     * @param: [no]
     * @return: int
     * @auther: zqq
     * @date: 20/6/18 17:40
     */
    public int hashFun(int no){
        return no % this.size;
    }
}

测试:

public class TestHashTable {

    public static void main(String[] args) {
        HashTable hashTable = new HashTable(5);
        Scanner scanner = new Scanner(System.in);
        while (true){
            System.out.println("show 显示员工");
            System.out.println("add 添加员工");
            System.out.println("delete 删除员工");
            System.out.println("exit 退出系统");
            String input = scanner.next();
            int no;
            switch (input){
                case "show":
                    hashTable.show();
                    break;
                case "add":
                    System.out.println("请输入员工id");
                    no = scanner.nextInt();
                    System.out.println("请输入员工姓名");
                    String name = scanner.next();
                    Emp emp = new Emp(no, name);
                    hashTable.add(emp);
                    break;
                case "delete":
                    System.out.println("请输入要删除员工的id");
                    no = scanner.nextInt();
                    hashTable.deleteEmp(no);
                    break;
                case "exit":
                    scanner.close();
                    System.exit(0);
                    break;
                default:
                    break;
            }
        }
    }

}

你可能感兴趣的:(数据结构与算法)