[JAVA]模擬Hash Table使用散列函數(Hash Function)實現新刪查員工

圖片來源:https://blog.csdn.net/weixin_44441009/article/details/115333213

package utitled;

import java.util.Scanner;

public class EmpHashTableDemo {

  public static void main(String[] args) {
    // 包含7條串列的HashTable
    EmpHashTable empHashTable = new EmpHashTable(7);
    System.out.println("請輸入add, loop, find, delete, exit: ");
    Scanner scanner = new Scanner(System.in);
    while (scanner.hasNext()) {      
      switch (scanner.next()) {
        case "add":
          System.out.println("請輸入id:");
          int id = scanner.nextInt();
          System.out.println("請輸入姓名:");
          String name = scanner.next();
          Emp emp = new Emp(id, name);
          empHashTable.addEmp(emp);
          System.out.println("新增成功~~");
          break;
        case "loop":
          empHashTable.loopEmpLinkedList();
          break;
        case "find":
          System.out.println("請輸入id:");
          id = scanner.nextInt();
          emp = empHashTable.findEmpById(id);
          if (emp == null) {
            System.out.printf("找不到id=%d的員工資料\n", id);
          } else {
            System.out.printf("員工資料:id{%d}/ name{%s}\n", emp.getId(), emp.getName());
          }
          break;
        case "delete" :
          System.out.println("請輸入id:");
          id = scanner.nextInt();
          empHashTable.deleteEmpById(id);
          break;
        case "exit":
          scanner.close();
          System.exit(0);
          break;
        default:
          break;
      }
      System.out.println("請輸入add, loop, find, delete, exit: ");
    }
  }

}


class Emp {
  private int id;
  private String name;
  /* 預設指向下一個員工為null */
  private Emp next;

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

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

  public Emp getNext() {
    return next;
  }

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


class EmpLinkedList {

  /* 預設頭節點為第一位員工 */
  private Emp head;

  /**
   * 新增員工到串列
   *
   * @param emp
   */
  void addEmp(Emp emp) {
    if (head == null) {
      head = emp;
      return;
    }
    Emp empById = findEmpById(emp.getId());
    if (empById == null) {
      // 先用id找看看是否已存在,不存在再新增

      // 找到一條串列的最後一位員工再新增
      Emp curEmp = head;
      while (curEmp.getNext() != null) {
        // 若還有下一位員工就繼續loop
        curEmp = curEmp.getNext();
      }
      curEmp.setNext(emp);
    }
  }

  /**
   * 遍歷員工串列 輸出員工資料
   */
  void loopEmpLinkedList() {
    if (head == null) {
      System.out.print("串列為空~~\n");
      return;
    }
    Emp curEmp = head;
    while (true) {
      System.out.printf("員工資料:id{%d}/ name{%s}\t", curEmp.getId(), curEmp.getName());
      // 若還有下一位員工就繼續loop
      if (curEmp.getNext() == null) {
        break;
      }
      curEmp = curEmp.getNext();
    }
  }

  /**
   * 依據id查詢員工 回傳員工物件
   * @param id
   * @return
   */
  Emp findEmpById(int id) {
    if (head == null) {
      System.out.println("串列為空~~");
    }
    Emp curEmp = head;
    while(curEmp != null) {
      if (id == curEmp.getId()) {
        // 找到該員工
        break;
      }
      curEmp = curEmp.getNext();
    }
    return curEmp;
  }

  /**
   * 依據id刪除員工
   * @param id
   */
  void deleteEmpById(int id) {
    if (head == null) {
      System.out.printf("串列為空,找不到id=%d的員工~~\n", id);
      return;
    }
    Emp curEmp = head;
    Emp preEmp = null;
    while (curEmp != null) {
      if (id == curEmp.getId()) {
        // 找到待刪除的員工
        if (curEmp.getNext() != null) {
          preEmp.setNext(curEmp.getNext());
          curEmp.setNext(null);
        } else if (preEmp != null) {
          // 若待刪除的員工在串列的最後
          preEmp.setNext(null);
        } else {
          // 該串列只有head一個員工
          head = null;
        }
        System.out.println("刪除成功~~");
        return;
      }
      preEmp = curEmp;
      curEmp = curEmp.getNext();
    }
    System.out.printf("找不到id=%d的員工,無法刪除!\n", id);
  }

}


class EmpHashTable {
  private EmpLinkedList[] empLinkedListArr;
  private int size;

  /**
   * 初始化EmpHashTable, EmpLinkedList
   * @param size
   */
  public EmpHashTable(int size) {
    this.empLinkedListArr = new EmpLinkedList[size];
    for (int i = 0; i < size; i++) {
      empLinkedListArr[i] = new EmpLinkedList();
    }
    this.size = size;
  }

  /**
   * 以取餘數方式取得員工id對應哪條串列
   * @param empId
   * @return
   */
  int getEmpIdBelongs(int empId) {
    return empId % size;
  }

  /**
   * 透過散列函數以hashTable管理
   * 新增員工
   * @param emp
   */
  void addEmp(Emp emp) {
    // 1. 先找出哪一條串列
    // 2. 再呼叫EmpLinkedList的addEmp()
    empLinkedListArr[getEmpIdBelongs(emp.getId())].addEmp(emp);
  }

  /**
   * 遍歷所有串列的員工資料
   * 並輸出
   */
  void loopEmpLinkedList() {
    for (int i = 0; i < size; i++) {
      System.out.print("\n第"+(i+1)+"條串列 : ");
      empLinkedListArr[i].loopEmpLinkedList();
    }
  }

  /**
   * 透過散列函數以hashTable管理
   * 查詢員工
   * @param id
   * @return
   */
  Emp findEmpById(int id) {
    // 1. 先找出哪一條串列
    // 2. 在呼叫EmpLinkedList的findEmpById
    System.out.print("第"+(getEmpIdBelongs(id)+1)+"條串列:");
    return empLinkedListArr[getEmpIdBelongs(id)].findEmpById(id);
  }

  /**
   * 透過散列函數以hashTable管理
   * 刪除員工
   * @param id
   */
  void deleteEmpById(int id) {
    // 1. 先找出哪一條串列
    // 2. 在呼叫EmpLinkedList的deleteEmpById
    System.out.print("第"+(getEmpIdBelongs(id)+1)+"條串列:");
    empLinkedListArr[getEmpIdBelongs(id)].deleteEmpById(id);
  }
}

如有敘述錯誤,還請不吝嗇留言指教,thanks!