实现了crud功能,其中delete功能是自己独立写的

    1. package com.atguigu.hashtable;
    2. import java.util.Scanner;
    3. /**
    4. * 哈希表
    5. * 谷歌面试题
    6. *
    7. * @author Dxkstart
    8. * @create 2021-10-15-19:27
    9. */
    10. public class HashTableDemo {
    11. public static void main(String[] args) {
    12. //创建哈希表
    13. HashTable hashTable = new HashTable(7);
    14. //写一个简单的菜单
    15. Scanner scanner = new Scanner(System.in);
    16. String key;
    17. L:
    18. while (true) {
    19. System.out.println("~~~欢迎使用HashTable~~~");
    20. System.out.println("1.添加员工信息");
    21. System.out.println("2.删除员工信息");
    22. System.out.println("3.显示所有员工信息");
    23. System.out.println("4.根据id号查找员工信息");
    24. System.out.println("5.退出程序");
    25. key = scanner.next();
    26. switch (key) {
    27. case "1":
    28. System.out.println("请输员工信息");
    29. System.out.println("id:");
    30. int id = scanner.nextInt();
    31. System.out.println("名字:");
    32. String name = scanner.next();
    33. hashTable.add(new Emp(id, name));
    34. break;
    35. case "2":
    36. System.out.println("请输要删除的员工的id");
    37. id = scanner.nextInt();
    38. hashTable.delete(id);
    39. break;
    40. case "3":
    41. hashTable.list();
    42. break;
    43. case "4":
    44. System.out.println("请输要查找的员工的id");
    45. id = scanner.nextInt();
    46. hashTable.findEmpById(id);
    47. break;
    48. case "5":
    49. scanner.close();
    50. break L;
    51. }
    52. }
    53. }
    54. }
    55. //创建HashTable 管理多条链表
    56. class HashTable {
    57. private EmpLinkedList[] empLinkedListsArray;
    58. private int size;//表示有多少条链表
    59. //构造器
    60. public HashTable(int size) {
    61. this.size = size;
    62. //初始化empLinkedListsArray
    63. empLinkedListsArray = new EmpLinkedList[size];
    64. //?小心这里有坑,这是不要忘了分别初始化每一条链表!!!
    65. for (int i = 0; i < size; i++) {
    66. empLinkedListsArray[i] = new EmpLinkedList();
    67. }
    68. }
    69. //添加员工
    70. public void add(Emp emp) {
    71. //根据员工的id,得到该员工应当添加到哪条链表
    72. int empLinkedListNo = hashFun(emp.id);
    73. //将emp添加到对应的链表中
    74. empLinkedListsArray[empLinkedListNo].add(emp);
    75. }
    76. //遍历员工(遍历所有的链表,即哈希表)
    77. public void list() {
    78. for (int i = 0; i < size; i++) {
    79. empLinkedListsArray[i].list(i);
    80. }
    81. }
    82. //根据输入的id,查找员工信息
    83. public void findEmpById(int id) {
    84. //根据员工的id,得到该员工应当添加到哪条链表
    85. int empLinkedListNo = hashFun(id);
    86. Emp emp = empLinkedListsArray[empLinkedListNo].findEmpById(id);
    87. if (emp != null) {
    88. System.out.printf("在第%d条链表中找到员工 id = %d , 名字:%s \n", (empLinkedListNo + 1), id, emp.name);
    89. } else {
    90. System.out.println("没有找到该员工信息");
    91. }
    92. }
    93. //删除员工
    94. public void delete(int id) {
    95. //根据员工的id,得到该员工在哪条链表
    96. int empLinkedListNo = hashFun(id);
    97. //删除对应的员工
    98. empLinkedListsArray[empLinkedListNo].delete(id);
    99. }
    100. //编写一个散列函数,使用一个简单的取模法
    101. //说明:
    102. //这个HashTable中是一个数组,每个数组有一条链表,
    103. //加入员工时,要确定这个员工加入到哪条链表中去
    104. //即:要确定的是数组的角标
    105. public int hashFun(int id) {
    106. return id % size;
    107. }
    108. }
    109. //表示一个雇员
    110. class Emp {
    111. public int id;
    112. public String name;
    113. public Emp next;//next 默认为null
    114. public Emp(int id, String name) {
    115. this.id = id;
    116. this.name = name;
    117. }
    118. }
    119. //创建EmpLinkedList,表示链表
    120. class EmpLinkedList {
    121. //头指针,指向第一个Emp,因此我们这个链表的head 是直接指向第一个Emp
    122. private Emp head;//默认null
    123. //添加员工到链表
    124. //说明:
    125. //1.假定,当添加雇员时,id 是自增长的,即id的分配总是从小到大
    126. // 因此我们将该雇员直接加入到本链表的最后即可
    127. public void add(Emp emp) {
    128. //如果是添加第一个员工
    129. if (head == null) {
    130. head = emp;
    131. return;
    132. }
    133. //如果不是第一个员工,则使用一个辅助的指针,帮助定位到最后
    134. Emp curEmp = head;
    135. while (true) {
    136. if (curEmp.next == null) {//说明到链表的最后
    137. break;
    138. }
    139. curEmp = curEmp.next;//往后移
    140. }
    141. //退出循环时,即指针指向了链表的最后
    142. //将emp(员工信息),连接到链表尾部
    143. curEmp.next = emp;
    144. }
    145. //遍历链表信息
    146. public void list(int no) {
    147. if (head == null) {//说明链表为空
    148. System.out.println("第" + (no + 1) + "条链表为空!");
    149. return;
    150. }
    151. System.out.println("第" + (no + 1) + "条链表的信息为:");
    152. Emp curEmp = head;//辅助指针
    153. while (true) {
    154. System.out.printf(" => id = %d, name = %s \n", curEmp.id, curEmp.name);
    155. if (curEmp.next == null) {//说明到链表的最后
    156. break;
    157. }
    158. curEmp = curEmp.next;//后移遍历
    159. }
    160. }
    161. //根据id,查找员工信息
    162. //如果找到,就返回Emp,如果没有找到,就返回null
    163. public Emp findEmpById(int id) {
    164. //判断链表是否为空
    165. if (head == null) {
    166. System.out.println("链表为空");
    167. return null;
    168. }
    169. //辅助指针
    170. Emp curEmp = head;
    171. while (true) {
    172. if (curEmp.id == id) {
    173. break;//这是curEmp就指向要查找的员工
    174. }
    175. //退出循环的条件
    176. if (curEmp.next == null) {//说明当前链表没有找到该雇员
    177. curEmp = null;
    178. break;
    179. }
    180. curEmp = curEmp.next;//后移指针
    181. }
    182. return curEmp;
    183. }
    184. //删除链表信息(自己写的)
    185. public void delete(int id) {
    186. if (head == null) {//说明链表为空
    187. System.out.println("当前链表为空");
    188. return;
    189. }
    190. Emp curEmp = head;//辅助指针
    191. if (curEmp.next == null && curEmp.id == id) {//只有一个员工
    192. head = null;
    193. System.out.println("删除成功1");
    194. return;
    195. }
    196. while (true) {//将辅助指针指向要删除的节点的上一个节点
    197. if (curEmp.next == null) {//说明到链表的最后
    198. System.out.println("没有此员工信息");
    199. return;
    200. }
    201. if (curEmp.next.id == id) {
    202. break;
    203. }
    204. curEmp = curEmp.next;//后移遍历
    205. }
    206. if (curEmp.next.next == null) {//如果此节点是链表上的最后一个节点
    207. curEmp.next = null;
    208. System.out.println("删除成功end");
    209. return;
    210. }
    211. curEmp.next = curEmp.next.next;
    212. System.out.println("删除成功");
    213. }
    214. }