雲原生愛好者週刊:長得最像蘋果的 Linux 桌面
阿新 • • 發佈:2021-07-13
雜湊表的基本介紹
散列表(Hash table,也叫雜湊表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通
過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列
叫做散列表
google 公司的一個上機題:
有一個公司,當有新的員工來報道時,要求將該員工的資訊加入(id,性別,年齡,名字,住址..),當輸入該員工的 id 時,
要求查詢到該員工的 所有資訊.
要求:
1) 不使用資料庫,,速度越快越好=>雜湊表(雜湊)
2) 新增時,保證按照 id 從低到高插入 [課後思考:如果 id 不是從低到高插入,但要求各條連結串列仍是從低到
高,怎麼解決?]
3) 使用連結串列來實現雜湊表, 該連結串列不帶表頭[即: 連結串列的第一個結點就存放僱員資訊]
4) 思路分析並畫出示意圖
程式碼實現
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; } }