哈希表
哈希表:
哈希表又称散列表,结构为数组加链表,通过计算数据的哈希值能够准确知道这个数据在哪条链表上,加快查找速度(自己写的,可能不太准确)。
例子:
有一个公司,当有新的员工来报道时,要求将该员工的信息(编号,名字)加入,然后可以对这个员工进行增删改查,要求使用哈希表。
代码:
1 import lombok.Data; 2 import lombok.NoArgsConstructor; 3 import java.util.Scanner; 4 5 public class HashTableTest { 6 public static void main(String[] args) { 7 //创建哈希表 8 HashTable hashTab = new HashTable(7); 9 //写一个简单的菜单 10 String key = ""; 11 Scanner scanner = new Scanner(System.in); 12 while(true) { 13 System.out.println("add: 添加雇员"); 14 System.out.println("delete: 删除雇员"); 15 System.out.println("update: 修改雇员"); 16 System.out.println("find: 查找雇员"); 17 System.out.println("list: 显示雇员"); 18 System.out.println("exit: 退出系统"); 19 20 key = scanner.next(); 21 switch (key) { 22 case "add": 23 System.out.println("输入编号"); 24 int no = scanner.nextInt(); 25 System.out.println("输入名字"); 26 String name = scanner.next(); 27 //创建 雇员 28 EmpNode emp = new EmpNode(no, name); 29 boolean addBoo = hashTab.add(emp); 30 if (addBoo) { 31 System.out.println("~~~添加成功~~~"); 32 } else { 33 System.out.println("~~~添加失败~~~"); 34 } 35 break; 36 case "delete": 37 System.out.println("输入编号"); 38 no = scanner.nextInt(); 39 boolean deleteBoo = hashTab.delete(no); 40 if (deleteBoo) { 41 System.out.println("~~~删除成功~~~"); 42 } else { 43 System.out.println("~~~删除失败~~~"); 44 } 45 break; 46 case "update": 47 System.out.println("输入编号"); 48 no = scanner.nextInt(); 49 System.out.println("输入名字"); 50 name = scanner.next(); 51 //创建 雇员 52 emp = new EmpNode(no, name); 53 boolean updateBoo = hashTab.update(emp); 54 if (updateBoo) { 55 System.out.println("~~~更新成功~~~"); 56 } else { 57 System.out.println("~~~更新失败~~~"); 58 } 59 break; 60 case "find": 61 System.out.println("请输入要查找的编号"); 62 no = scanner.nextInt(); 63 EmpNode empNode = hashTab.find(no); 64 if (empNode == null) { 65 System.out.println("~~~没有找到~~~"); 66 } else { 67 System.out.println(empNode); 68 } 69 break; 70 case "list": 71 hashTab.list(); 72 break; 73 case "exit": 74 scanner.close(); 75 System.exit(0); 76 default: 77 break; 78 } 79 } 80 } 81 } 82 83 /** 84 * 员工节点 85 */ 86 @Data 87 @NoArgsConstructor 88 class EmpNode { 89 90 /** 91 * 员工编号 92 */ 93 private int empNo; 94 95 /** 96 * 员工名称 97 */ 98 private String empName; 99 100 private EmpNode next; 101 102 public EmpNode(int empNo, String empName) { 103 this.empNo = empNo; 104 this.empName = empName; 105 } 106 107 @Override 108 public String toString() { 109 return "EmpNode{" + 110 "empNo=" + empNo + 111 ", empName=" + empName + 112 '}'; 113 } 114 } 115 116 /** 117 * 单链表 118 */ 119 @NoArgsConstructor 120 class EmpLinkedList { 121 122 /** 123 * 头节点 124 */ 125 private EmpNode headNode; 126 127 /** 128 * 是否为空 129 * @return 130 */ 131 public boolean isEmpty() { 132 return headNode == null; 133 } 134 135 /** 136 * 添加 137 * @param empNode 138 * @return 139 */ 140 public boolean add(EmpNode empNode) { 141 if (isEmpty()) { 142 //添加第一个元素 143 headNode = empNode; 144 return true; 145 } 146 //按编号顺序添加 147 if (empNode.getEmpNo() < headNode.getEmpNo()) { 148 //新的节点作为头节点 149 empNode.setNext(headNode); 150 headNode = empNode; 151 return true; 152 } else if (empNode.getEmpNo() == headNode.getEmpNo()) { 153 return false; 154 } 155 EmpNode temp = headNode; 156 while (temp.getNext() != null) { 157 if (empNode.getEmpNo() < temp.getNext().getEmpNo()) { 158 empNode.setNext(temp.getNext()); 159 temp.setNext(empNode); 160 return true; 161 } else if (empNode.getEmpNo() == temp.getNext().getEmpNo()) { 162 return false; 163 } 164 temp = temp.getNext(); 165 } 166 temp.setNext(empNode); 167 return true; 168 } 169 170 /** 171 * 删除 172 * @param empNo 173 * @return 174 */ 175 public boolean delete(int empNo) { 176 if (isEmpty()) { 177 return false; 178 } 179 180 if (headNode.getEmpNo() == empNo) { 181 //删除当前的头节点 182 headNode = headNode.getNext(); 183 return true; 184 } else if (headNode.getEmpNo() > empNo) { 185 return false; 186 } 187 EmpNode temp = headNode; 188 while (temp.getNext() != null) { 189 if (temp.getNext().getEmpNo() == empNo) { 190 temp.setNext(temp.getNext().getNext()); 191 return true; 192 } else if (temp.getNext().getEmpNo() > empNo) { 193 return false; 194 } 195 temp = temp.getNext(); 196 } 197 return false; 198 } 199 200 /** 201 * 更新 202 * @param empNode 203 * @return 204 */ 205 public boolean update(EmpNode empNode) { 206 if (isEmpty()) { 207 return false; 208 } 209 EmpNode temp = headNode; 210 while (temp != null) { 211 if (temp.getEmpNo() == empNode.getEmpNo()) { 212 temp.setEmpName(empNode.getEmpName()); 213 return true; 214 } else if (temp.getEmpNo() > empNode.getEmpNo()) { 215 return false; 216 } 217 temp = temp.getNext(); 218 } 219 return false; 220 } 221 222 /** 223 * 查找 224 * @param empNo 225 * @return 226 */ 227 public EmpNode find(int empNo) { 228 if (isEmpty()) { 229 return null; 230 } 231 EmpNode temp = headNode; 232 while (temp != null) { 233 if (temp.getEmpNo() == empNo) { 234 return temp; 235 } else if (temp.getEmpNo() > empNo) { 236 return null; 237 } 238 temp = temp.getNext(); 239 } 240 return null; 241 } 242 243 @Override 244 public String toString() { 245 if (isEmpty()) { 246 return "->链表为空"; 247 } 248 EmpNode temp = headNode; 249 StringBuilder strBu = new StringBuilder(); 250 while (temp != null) { 251 strBu.append("->{no:" + temp.getEmpNo() + ",name:" + temp.getEmpName() + "}"); 252 temp = temp.getNext(); 253 } 254 return strBu.toString(); 255 } 256 } 257 258 class HashTable { 259 /** 260 * 链表数组 261 */ 262 private EmpLinkedList[] empLinkedListArr; 263 264 /** 265 * 链表数组的长度 266 */ 267 private int size; 268 269 public HashTable(int size) { 270 this.size = size; 271 empLinkedListArr = new EmpLinkedList[size]; 272 for (int i = 0; i < empLinkedListArr.length; i++) { 273 empLinkedListArr[i] = new EmpLinkedList(); 274 } 275 } 276 277 /** 278 * 计算哈希值 279 * @param no 280 * @return 281 */ 282 private int hashValue(int no) { 283 return no % size; 284 } 285 286 /** 287 * 添加 288 * @param empNode 289 * @return 290 */ 291 public boolean add(EmpNode empNode) { 292 int hashValue = hashValue(empNode.getEmpNo()); 293 //根据哈希值来判断是落在哪条链表上 294 return empLinkedListArr[hashValue].add(empNode); 295 } 296 297 /** 298 * 删除 299 * @param empNo 300 * @return 301 */ 302 public boolean delete(int empNo) { 303 int hashValue = hashValue(empNo); 304 //根据哈希值判断是在哪条链表上 305 return empLinkedListArr[hashValue].delete(empNo); 306 } 307 308 /** 309 * 更新 310 * @param empNode 311 * @return 312 */ 313 public boolean update(EmpNode empNode) { 314 int hashValue = hashValue(empNode.getEmpNo()); 315 //根据哈希值判断是在哪条链表上 316 return empLinkedListArr[hashValue].update(empNode); 317 } 318 319 /** 320 * 查找 321 * @param empNo 322 * @return 323 */ 324 public EmpNode find(int empNo) { 325 int hashValue = hashValue(empNo); 326 //根据哈希值判断是在哪条链表上 327 return empLinkedListArr[hashValue].find(empNo); 328 } 329 330 /** 331 * 遍历 332 */ 333 public void list() { 334 for (int i = 0; i < empLinkedListArr.length; i++) { 335 System.out.println("arr[" + i + "]: " + empLinkedListArr[i].toString()); 336 } 337 } 338 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现