Estructura y algoritmo de datos: tabla hash

Prefacio

Este artículo explica principalmente la tabla hash (hash)


Estructura de datos y lista de artículos sobre algoritmos

Estructura de datos y lista de artículos sobre algoritmos: haga clic aquí para saltar a la vista


Tabla de contenido

Inserte la descripción de la imagen aquí


(1) Introducción básica de la tabla hash

La tabla hash (también llamada tabla hash) es una estructura de datos a la que se accede directamente en función del valor de la clave. En otras palabras, accede al registro asignando el valor del código clave a una ubicación en la tabla para acelerar la búsqueda. Esta función de mapeo se llama función hash, y la matriz que almacena registros se llama tabla hash.
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí


(2) Caso de aplicación de tabla hash (hash)

Hay una empresa, cuando un nuevo empleado viene a reportar, se requiere agregar la información del empleado (id, género, edad, nombre, dirección ...), y cuando se ingresa el id del empleado, se requiere encontrar todos la información del empleado.
Reclamo:

  1. No use una base de datos, cuanto más rápido mejor => tabla hash (hash)
  2. Al agregar, asegúrese de insertar de menor a mayor de acuerdo con la identificación
  3. Use una lista vinculada para implementar una tabla hash, la lista vinculada no tiene un encabezado [es decir, el primer nodo de la lista vinculada almacena información de los empleados]
  4. Analizar ideas y dibujar un diagrama esquemático.
    Inserte la descripción de la imagen aquí

Código:

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;
     }

}

resultado:

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

Supongo que te gusta

Origin blog.csdn.net/a13027629517/article/details/115015015
Recomendado
Clasificación