哈希表
一----导读:
首先要明确一个概念:哈希表不是 算法,而是一种数据结构 。
我们都知道,java代码可以操作数据库,并且从从数据库再返回数据。但是如果频繁的对数据库进行操作,效率较低且存在安全隐患,这时就诞生出了缓存产品,也就是现在常用的redis或者Memcache ,但是以前的 老程序员们没有这些产品怎么办?这时哈希表就出场了。一级缓存不够的话加二级缓存。
哈希表常用的结构:
1)数组+链表
2)数组+二叉树
二---代码实现哈希表
看一个实际的面试题:
有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,姓名),
当输入该员工的id时,要求查找到该员工的所有信息。
要求,不使用数据库,速度越快越好
思路分析 :
测试代码:
1 public class HashTable { 2 public static void main(String[] args) { 3 // 创建一个hashtab 4 HashTab hashTab = new HashTab(7); 5 6 // 写一个简单菜单 7 String key = ""; 8 Scanner scanner = new Scanner(System.in); 9 while (true) { 10 System.out.println("1)添加雇员"); 11 System.out.println("2)显示雇员"); 12 System.out.println("3)退出系统"); 13 key = scanner.next(); 14 switch (key) { 15 case "1": 16 System.out.println("输入id"); 17 int id = scanner.nextInt(); 18 System.out.println("输入名字"); 19 String name = scanner.next(); 20 // 创建雇员 21 Emp emp = new Emp(id,name); 22 hashTab.add(emp); 23 break; 24 case "2": 25 hashTab.list(); 26 break; 27 case "3": 28 scanner.close(); 29 System.exit(0); 30 31 default: 32 break; 33 34 } 35 } 36 37 38 39 40 } 41 } 42 43 // 创建HashTab 管理多条链表 44 class HashTab { 45 private EmpLinkedList[] empLinkedListArray; // 数组里面放的是链表 46 private int size; // 表示共有多少条链表 47 //构造器 48 public HashTab(int size) { // size表示指定有多少条链表 49 this.size = size; 50 // 初始化empLinkedListArray 51 empLinkedListArray = new EmpLinkedList[size]; // 开辟空间 52 // 留一个坑 此时的链表数组能不能用? 53 // 这时不要忘了分别初始化每个链表 54 for (int i = 0; i < size ; i++) { 55 empLinkedListArray[i] = new EmpLinkedList(); 56 } 57 } 58 59 // 添加雇员 60 public void add(Emp emp) { // 添加的时候给出一个雇员 61 // 根据员工的id,得到该员工应当添加到哪条链表 62 int empLinkedListNo = hashFun(emp.id); 63 // 将emp添加到对应链表 64 empLinkedListArray[empLinkedListNo].add(emp); 65 } 66 67 // 遍历所有的链表(哈希表) 68 public void list() { 69 for (int i = 0; i < size ; i++) { 70 empLinkedListArray[i].list(i); 71 } 72 73 } 74 75 // 编写一个散列函数,使用简单的取模法 76 public int hashFun(int id) { 77 return id % size; 78 } 79 80 } 81 82 // 表示雇员 83 class Emp { 84 public int id; 85 public String name; 86 public Emp next; // next 默认为空指向下一个雇员信息的指针 87 88 public Emp(int id, String name) { // 带参构造 89 super(); 90 this.id = id; 91 this.name = name; 92 } 93 } 94 95 // 创建EmpLinkedList ,表示链表 96 class EmpLinkedList { 97 // 头指针,执行第一个Emp,因此我们这个链表的head是有效的,直接指向第一个Emp 98 private Emp head; // 默认null 99 100 // 添加雇员到链表 101 // 说明 102 // 1)假定当添加雇员时,id自增长,即id的分配总是从小到大 103 // 因此我们将该雇员直接加入到本链表的最后即可 104 public void add(Emp emp) { 105 // 如果是添加第一个雇员 106 if (head == null) { 107 head = emp; 108 return; 109 } 110 // 如果不是添加第一个雇员,则使用一个辅助指针帮助定位到最后 111 Emp curEmp = head; 112 while(true) { 113 if (curEmp.next == null) { // 说明到链表最后 114 break; 115 } 116 curEmp = curEmp.next; // 后移 117 } 118 // 退出时直接将emp加入链表 119 curEmp.next = emp; 120 } 121 122 // 遍历链表的雇员信息 123 public void list(int no) { 124 if(head == null) { // 说明链表为空 125 System.out.println("第" + (no + 1) + "链表为空"); 126 return; 127 } 128 System.out.print("第" + (no + 1) + "链表的信息为"); 129 Emp curEmp = head; // 辅助指针 130 while(true) { 131 System.out.printf(" =>id= %d name = %s\t", curEmp.id, curEmp.name); 132 if(curEmp.next == null) { //说明curEmp是最后结点 133 break; 134 } 135 curEmp = curEmp.next; // 如果不是最后一个就后移 136 } 137 System.out.println(); 138 } 139 140 }
posted on 2021-04-22 22:08 Love&Share 阅读(80) 评论(0) 编辑 收藏 举报