哈希表
哈希表基本介绍
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
-
哈希表的应用场景:
-
哈希表的逻辑图:
有关哈希表的一个例题
有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址..),当输入该员工的id 时, 要求查找到该员工的所有信息。
要求:
1) 不使用数据库,,速度越快越好=>哈希表(散列)
2) 添加时,保证按照 id 从低到高插入
[思考题:如果 id 不是从低到高插入,但要求各条链表仍是从低到高,怎么解决?]
3) 使用链表来实现哈希表, 该链表不带表头[即: 链表的第一个结点就存放雇员信息]
4) 思路分析并画出示意图
代码实现
Employee类
1 class Employee { 2 private int id; 3 private String name; 4 private Employee next; //next 默认为 null 5 6 public Employee() { 7 this.id=0; 8 this.name=null; 9 } 10 11 public int getId() { 12 return id; 13 } 14 15 public void setId(int id) { 16 this.id = id; 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 public void setName(String name) { 24 this.name = name; 25 } 26 27 public Employee getNext() { 28 return next; 29 } 30 31 public void setNext(Employee next) { 32 this.next = next; 33 } 34 35 public Employee(int id, String name) { 36 this.id = id; 37 this.name = name; 38 } 39 40 @Override 41 public String toString() { 42 return "employee{" + 43 "id=" + id + 44 ", name='" + name + '\'' + 45 '}'; 46 } 47 }
EmpLinkedList类
1 class EmpLinkedList { 2 //头指针,执行第一个 Emp,因此我们这个链表的 head 是直接指向第一个 Emp 3 private Employee head;//默认 null 4 5 //添加雇员到链表 6 //说明 7 //1. 假定,当添加雇员时,id 是自增长,即 id 的分配总是从小到大 8 // 因此我们将该雇员直接加入到本链表的最后即可 9 public void add(Employee emp) { 10 if (head == null) { 11 head = emp; 12 } else { 13 Employee temp = head; 14 while (temp.getNext() != null) { 15 temp = temp.getNext(); 16 } 17 temp.setNext(emp); 18 } 19 } 20 21 public void list() { 22 if (head == null) { 23 System.out.println("linked list():链表为空。。。。"); 24 return; 25 } 26 Employee temp = head; 27 while (true) { 28 if (temp.getNext() == null) { 29 } else { 30 System.out.print(temp + "==>"); 31 32 } 33 if (temp.getNext() == null) {//说明 curEmp 已经是最后结点 34 break; 35 } 36 temp = temp.getNext(); 37 } 38 System.out.println(); 39 } 40 41 public Employee delete(int id) { 42 if (head == null) { 43 System.out.println("linked findEmp():链表为空。。。。"); 44 return null; 45 } 46 Employee temp = head; 47 while (true) { 48 if (temp.getId() == id) { 49 System.out.println("linked delete():删除成功!"); 50 return temp; 51 } 52 if (temp.getNext() == null) { 53 System.out.println("linked delete():查无此人。。。。。"); 54 return null; 55 } 56 temp = temp.getNext(); 57 } 58 } 59 60 //根据 id 查找雇员 61 public void findEmp(int id) { 62 if (head == null) { 63 System.out.println("linked findEmp():链表为空。。。。"); 64 return; 65 } 66 Employee temp = head; 67 while (true) { 68 if (temp.getId() == id) { 69 System.out.println("linked findEmp():id为 " + id + " 的人员信息为:" + temp); 70 break; 71 } 72 if (temp.getNext() == null) { 73 System.out.println("linked findEmp():查无此人。。。。。"); 74 break; 75 } 76 temp = temp.getNext(); 77 } 78 } 79 }
HashTableDemo类
1 public class HashTableDemo { 2 public static void main(String[] args) { 3 //创建哈希表 4 HashTable hashTab = new HashTable(7); 5 //写一个简单的菜单 String key = ""; 6 Scanner scanner = new Scanner(System.in); 7 while (true) { 8 System.out.println("add: 添加雇员"); 9 System.out.println("list: 显示雇员"); 10 System.out.println("find: 查找雇员"); 11 System.out.println("exit: 退出系统"); 12 13 String key = scanner.next(); 14 switch (key) { 15 case "add": 16 System.out.println("输入 id"); 17 int id = scanner.nextInt(); 18 System.out.println("输入名字"); 19 String name = scanner.next(); 20 //创建 雇员 21 Employee emp = new Employee(id, name); 22 hashTab.add(emp); 23 break; 24 case "list": 25 hashTab.list(); 26 break; 27 case "find": 28 System.out.println("请输入要查找的 id"); 29 id = scanner.nextInt(); 30 hashTab.findEmp(id); 31 break; 32 case "exit": 33 scanner.close(); 34 System.exit(0); 35 default: 36 break; 37 } 38 } 39 } 40 41 } 42 43 //创建 HashTab 管理多条链表 44 class HashTable { 45 private EmpLinkedList[] empLinkedListArray; 46 private int size ;//定义数组长度,表示有多少条链表 47 48 //构造器 49 public HashTable(int size) { 50 this.size = size; 51 empLinkedListArray = new EmpLinkedList[size];//初始化 empLinkedListArray 52 //避坑!! 这时必须要分别初始化每个链表 53 for (int i = 0; i < empLinkedListArray.length; i++) { 54 empLinkedListArray[i] = new EmpLinkedList(); 55 } 56 } 57 58 //添加雇员 59 public void add(Employee emp) { 60 int hashfun = this.hashfun(emp.getId());//根据员工的 id ,得到该员工应当添加到哪条链表 61 empLinkedListArray[hashfun].add(emp);//将 emp 添加到对应的链表中 62 } 63 64 //遍历所有的链表,遍历 hashtab 65 public void list() { 66 for (int i = 0; i < empLinkedListArray.length; i++) { 67 System.out.print("第" + i + "条链表:"); 68 empLinkedListArray[i].list(); 69 } 70 } 71 72 //根据输入的 id,删除雇员 73 public Employee delete(int id) { 74 int hashfun = this.hashfun(id); 75 Employee delete = empLinkedListArray[hashfun].delete(id); 76 return delete; 77 } 78 79 //根据输入的 id,查找雇员 80 public void findEmp(int id) { 81 int hashfun = this.hashfun(id); 82 empLinkedListArray[hashfun].findEmp(id); 83 } 84 85 //编写散列函数, 使用一个简单取模法 86 public int hashfun(int id) { 87 return id % size; 88 } 89 90 @Override 91 public boolean equals(Object o) { 92 if (this == o) return true; 93 if (o == null || getClass() != o.getClass()) return false; 94 HashTable hashtable = (HashTable) o; 95 return size == hashtable.size && 96 Arrays.equals(empLinkedListArray, hashtable.empLinkedListArray); 97 } 98 99 @Override 100 public int hashCode() { 101 int result = Objects.hash(size); 102 result = 31 * result + Arrays.hashCode(empLinkedListArray); 103 return result; 104 } 105 }