Data structure and algorithm: hash table

Preface

This article mainly explains the hash table (hash)


Data structure and algorithm article list

Data structure and algorithm article list: click here to jump to view


table of Contents

Insert picture description here


(1) Basic introduction of hash table

Hash table (also called hash table) is a data structure that is directly accessed based on the key value. In other words, it accesses the record by mapping the key code value to a location in the table to speed up the search. This mapping function is called a hash function, and the array storing records is called a hash table.
Insert picture description here
Insert picture description here


(2) Hash table (hash) application case

There is a company, when a new employee reports, it requires the employee's information to be added (id, gender, age, name, address...), when the employee's id is entered, all the information of the employee is required to be found.
Claim:

  1. Do not use a database, the faster the better => hash table (hash)
  2. When adding, ensure to insert from low to high according to id
  3. Use a linked list to implement a hash table, the linked list does not have a header [ie: the first node of the linked list stores employee information]
  4. Analyze ideas and draw a schematic diagram
    Insert picture description here

Code:

import java.util.Scanner;
public class HashTabDemo {
    
    
     public static void main(String[] args) {
    
    
          // 创建哈希表
          HashTab hashTab = new HashTab(7);
          // 写一个简单的菜单
          String key = "";
          Scanner scanner = new Scanner(System.in);
          while (true) {
    
    
              System.out.println("add:  添加雇员");
              System.out.println("list: 显示雇员");
              System.out.println("find: 查找雇员");
              System.out.println("exit: 退出系统");
              key = scanner.next();
              switch (key) {
    
    
              case "add":
                   System.out.println("输入id");
                   int id = scanner.nextInt();
                   System.out.println("输入名字");
                   String name = scanner.next();
                   // 创建 雇员
                   Emp emp = new Emp(id, name);
                   hashTab.add(emp);
                   break;
              case "list":
                   hashTab.list();
                   break;
              case "find":
                   System.out.println("请输入要查找的id");
                   id = scanner.nextInt();
                   hashTab.findEmpById(id);
                   break;
              case "exit":
                   scanner.close();
                   System.exit(0);
              default:
                   break;
              }
          }
     }
}

// 创建HashTab管理多条链表
class HashTab {
    
    
     private EmpLinkedList[] empLinkedListArray;
     private int size; // 表示有多少条链表
     // 构造器
     public HashTab(int size) {
    
    
          this.size = size;
          // 初始化empLinkedListArray
          empLinkedListArray = new EmpLinkedList[size];
          // ?留一个坑, 这时不要分别初始化每个链表
          for (int i = 0; i < size; i++) {
    
    
              empLinkedListArray[i] = new  EmpLinkedList();
          }
     }

     // 添加雇员
     public void add(Emp emp) {
    
    
          // 根据员工的id ,得到该员工应当添加到哪条链表
          int empLinkedListNO = hashFun(emp.id);
          // 将emp添加到对应的链表中
          empLinkedListArray[empLinkedListNO].add(emp);
     }

     // 遍历所有的链表,遍历hashtab
     public void list() {
    
    
          for (int i = 0; i < size; i++) {
    
    
              empLinkedListArray[i].list(i);
          }
     }

     // 根据输入的id,查找雇员
     public void findEmpById(int id) {
    
    
          // 使用散列函数确定到哪条链表查找
          int empLinkedListNO = hashFun(id);
          Emp emp =  empLinkedListArray[empLinkedListNO].findEmpById(id);
          if (emp != null) {
    
    // 找到
              System.out.printf("在第%d条链表中找到 雇员  id = %d\n", (empLinkedListNO + 1), id);
          } else {
    
    
              System.out.println("在哈希表中,没有找到该雇员~");
          }
     }

     // 编写散列函数, 使用一个简单取模法
     public int hashFun(int id) {
    
    
          return id % size;
     }
}

// 表示一个雇员
class Emp {
    
    
     public int id;
     public String name;
     public Emp next; // next 默认为 null
     public Emp(int id, String name) {
    
    
          super();
          this.id = id;
          this.name = name;
     }
}

// 创建EmpLinkedList ,表示链表
class EmpLinkedList {
    
    
     // 头指针,执行第一个Emp,因此我们这个链表的head 是直接指向第一个Emp
     private Emp head; // 默认null
     // 添加雇员到链表
     // 说明
     // 1. 假定,当添加雇员时,id 是自增长,即id的分配总是从小到大
     // 因此我们将该雇员直接加入到本链表的最后即可
     public void add(Emp emp) {
    
    
          // 如果是添加第一个雇员
          if (head == null) {
    
    
              head = emp;
              return;
          }
          // 如果不是第一个雇员,则使用一个辅助的指针,帮助定位到最后
          Emp curEmp = head;
          while (true) {
    
    
              if (curEmp.next == null) {
    
    // 说明到链表最后
                   break;
              }
              curEmp = curEmp.next; // 后移
          }
          // 退出时直接将emp 加入链表
          curEmp.next = emp;
     }

     // 遍历链表的雇员信息
     public void list(int no) {
    
    
          if (head == null) {
    
     // 说明链表为空
              System.out.println("第 " + (no + 1) + " 链表为空");
              return;
          }
          System.out.print("第 " + (no + 1) + " 链表的信息为");
          Emp curEmp = head; // 辅助指针
          while (true) {
    
    
              System.out.printf(" => id=%d name=%s\t",  curEmp.id, curEmp.name);
              if (curEmp.next == null) {
    
    // 说明curEmp已经是最后结点
                   break;
              }
              curEmp = curEmp.next; // 后移,遍历
          }
          System.out.println();
     }

     // 根据id查找雇员
     // 如果查找到,就返回Emp, 如果没有找到,就返回null
     public Emp findEmpById(int id) {
    
    
          // 判断链表是否为空
          if (head == null) {
    
    
              System.out.println("链表为空");
              return null;
          }
          // 辅助指针
          Emp curEmp = head;
          while (true) {
    
    
              if (curEmp.id == id) {
    
    // 找到
                   break;// 这时curEmp就指向要查找的雇员
              }
              // 退出
              if (curEmp.next == null) {
    
    // 说明遍历当前链表没有找到该雇员
                   curEmp = null;
                   break;
              }
              curEmp = curEmp.next;// 以后
          }
          return curEmp;
     }

}

result:

add:  添加雇员
list: 显示雇员
find: 查找雇员
exit: 退出系统
add
输入id
1
输入名字
tom
add:  添加雇员
list: 显示雇员
find: 查找雇员
exit: 退出系统
add
输入id
4
输入名字
777
add:  添加雇员
list: 显示雇员
find: 查找雇员
exit: 退出系统
list1 链表为空2 链表的信息为 => id=1 name=tom3 链表为空4 链表为空5 链表的信息为 => id=4 name=7776 链表为空7 链表为空
add:  添加雇员
list: 显示雇员
find: 查找雇员
exit: 退出系统

Guess you like

Origin blog.csdn.net/a13027629517/article/details/115015015