当前位置:   article > 正文

JAVA数据结构之哈希表_java 哈希表

java 哈希表

1、哈希表基本介绍


●散列表(Hash table, 也叫哈希表) ,是根据关键码值(Key value)而直接进行访问的数据结构。
●它通过把关键码值映射到表中一个位置来访问记录, 以加快查找的速度。 这个映射函数叫做散列函数, 存放记录的数组叫做散列表。
●哈希表的核心:private EmpLinkedList[] empLinkedListArray;
●哈希表编程思路:
先根据对象的信息将其散列,得到 hashCode
根据对象的 hashCode 值,找到对应的数组下标,其实就是找到存储对象的链表
在链表中进行相应的增删改查操作



2、代码实现


2.1、Emp 节点

  1. //表示一个雇员
  2. class EmpNode {
  3. public int id;
  4. public String name;
  5. public EmpNode next; // next 默认为 null
  6. public EmpNode(int id, String name) {
  7. super();
  8. this.id = id;
  9. this.name = name;
  10. }
  11. }

2.2、Emp 链表


●head 是首指针(指向真正存放数据的节点),不是头指针

  1. //创建EmpLinkedList ,表示链表
  2. class EmpLinkedList {
  3. // 首指针,指向第一个EmpNode,因此我们这个链表的head 是直接指向第一个EmpNode
  4. private EmpNode head; // 默认null
  5. // 添加雇员到链表
  6. // 说明
  7. // 1. 假定,当添加雇员时,id 是自增长,即id的分配总是从小到大
  8. // 因此我们将该雇员直接加入到本链表的最后即可
  9. public void add(EmpNode empNode) {
  10. // 如果是添加第一个雇员
  11. if (head == null) {
  12. head = empNode;
  13. return;
  14. }
  15. // 如果不是第一个雇员,则使用一个辅助的指针,帮助定位到最后
  16. EmpNode curEmp = head;
  17. while (true) {
  18. if (curEmp.next == null) {// 说明到链表最后
  19. break;
  20. }
  21. curEmp = curEmp.next; // 后移
  22. }
  23. // 退出时直接将emp 加入链表
  24. curEmp.next = empNode;
  25. }
  26. // 遍历链表的雇员信息
  27. public void list(int no) {
  28. if (head == null) { // 说明链表为空
  29. System.out.println("第 " + (no + 1) + " 链表为空");
  30. return;
  31. }
  32. System.out.print("第 " + (no + 1) + " 链表的信息为");
  33. EmpNode curEmp = head; // 辅助指针
  34. while (true) {
  35. System.out.printf(" => id=%d name=%s ", curEmp.id, curEmp.name);
  36. if (curEmp.next == null) {// 说明curEmp已经是最后结点
  37. break;
  38. }
  39. curEmp = curEmp.next; // 后移,遍历
  40. }
  41. System.out.println();
  42. }
  43. // 根据id查找雇员
  44. // 如果查找到,就返回Emp, 如果没有找到,就返回null
  45. public EmpNode findEmpById(int id) {
  46. // 判断链表是否为空
  47. if (head == null) {
  48. System.out.println("链表为空");
  49. return null;
  50. }
  51. // 辅助指针
  52. EmpNode curEmp = head;
  53. while (true) {
  54. if (curEmp.id == id) {// 找到
  55. break;// 这时curEmp就指向要查找的雇员
  56. }
  57. curEmp = curEmp.next;// 后移
  58. // 退出
  59. if (curEmp == null) {// 说明遍历当前链表没有找到该雇员
  60. break;
  61. }
  62. }
  63. return curEmp;
  64. }
  65. }

2.3、Emp 哈希表

  1. //创建HashTab 管理多条链表
  2. class HashTab {
  3. private EmpLinkedList[] empLinkedListArray;
  4. private int size; // 表示有多少条链表
  5. // 构造器
  6. public HashTab(int size) {
  7. this.size = size;
  8. // 初始化empLinkedListArray
  9. empLinkedListArray = new EmpLinkedList[size];
  10. for (int i = 0; i < size; i++) {
  11. empLinkedListArray[i] = new EmpLinkedList();
  12. }
  13. }
  14. // 添加雇员
  15. public void add(EmpNode empNode) {
  16. // 根据员工的id ,得到该员工应当添加到哪条链表
  17. int empLinkedListNO = hashFun(empNode.id);
  18. // 将emp 添加到对应的链表中
  19. empLinkedListArray[empLinkedListNO].add(empNode);
  20. }
  21. // 遍历所有的链表,遍历hashtab
  22. public void list() {
  23. for (int i = 0; i < size; i++) {
  24. empLinkedListArray[i].list(i);
  25. }
  26. }
  27. // 根据输入的id,查找雇员
  28. public void findEmpById(int id) {
  29. // 使用散列函数确定到哪条链表查找
  30. int empLinkedListNO = hashFun(id);
  31. EmpNode empNode = empLinkedListArray[empLinkedListNO].findEmpById(id);
  32. if (empNode != null) {// 找到
  33. System.out.printf("在第%d条链表中找到 雇员 id = %d\n", (empLinkedListNO + 1), id);
  34. } else {
  35. System.out.println("在哈希表中,没有找到该雇员~");
  36. }
  37. }
  38. // 编写散列函数, 使用一个简单取模法
  39. public int hashFun(int id) {
  40. return id % size;
  41. }
  42. }

2.4、代码测试

测试代码

  1. public class HashTabDemo {
  2. public static void main(String[] args) {
  3. // 创建哈希表
  4. HashTab hashTab = new HashTab(7);
  5. // 写一个简单的菜单
  6. String key = "";
  7. Scanner scanner = new Scanner(System.in);
  8. while (true) {
  9. System.out.println("add: 添加雇员");
  10. System.out.println("list: 显示雇员");
  11. System.out.println("find: 查找雇员");
  12. System.out.println("exit: 退出系统");
  13. System.out.println();
  14. key = scanner.next();
  15. switch (key) {
  16. case "add":
  17. System.out.println("输入id");
  18. int id = scanner.nextInt();
  19. System.out.println("输入名字");
  20. String name = scanner.next();
  21. // 创建 雇员
  22. EmpNode empNode = new EmpNode(id, name);
  23. hashTab.add(empNode);
  24. break;
  25. case "list":
  26. hashTab.list();
  27. break;
  28. case "find":
  29. System.out.println("请输入要查找的id");
  30. id = scanner.nextInt();
  31. hashTab.findEmpById(id);
  32. break;
  33. case "exit":
  34. scanner.close();
  35. System.exit(0);
  36. default:
  37. break;
  38. }
  39. }
  40. }
  41. }

程序运行结果

  1. add: 添加雇员
  2. find: 查找雇员
  3. exit: 退出系统
  4. add
  5. 输入id
  6. 2
  7. 输入名字
  8. Oneby
  9. add: 添加雇员
  10. list: 显示雇员
  11. find: 查找雇员
  12. exit: 退出系统
  13. add
  14. 输入id
  15. 8
  16. 输入名字
  17. NiuNiu
  18. add: 添加雇员
  19. list: 显示雇员
  20. find: 查找雇员
  21. exit: 退出系统
  22. list
  23. 1 链表为空
  24. 2 链表的信息为 => id=1 name=Heygo => id=8 name=NiuNiu
  25. 3 链表的信息为 => id=2 name=Oneby
  26. 4 链表为空
  27. 5 链表为空
  28. 6 链表为空
  29. 7 链表为空
  30. add: 添加雇员
  31. list: 显示雇员
  32. find: 查找雇员
  33. exit: 退出系统
  34. find
  35. 请输入要查找的id
  36. 1
  37. 在第2条链表中找到 雇员 id = 1
  38. add: 添加雇员
  39. list: 显示雇员
  40. find: 查找雇员
  41. exit: 退出系统
  42. find
  43. 请输入要查找的id
  44. 8
  45. 在第2条链表中找到 雇员 id = 8
  46. add: 添加雇员
  47. list: 显示雇员
  48. find: 查找雇员
  49. exit: 退出系统
  50. find
  51. 请输入要查找的id
  52. 9
  53. 在哈希表中,没有找到该雇员~
  54. add: 添加雇员
  55. list: 显示雇员
  56. find: 查找雇员
  57. exit: 退出系统

3.5、课后练习
实现员工的删除

4、Emp 哈希表全部代码

  1. public class HashTabDemo {
  2. public static void main(String[] args) {
  3. // 创建哈希表
  4. HashTab hashTab = new HashTab(7);
  5. // 写一个简单的菜单
  6. String key = "";
  7. Scanner scanner = new Scanner(System.in);
  8. while (true) {
  9. System.out.println("add: 添加雇员");
  10. System.out.println("list: 显示雇员");
  11. System.out.println("find: 查找雇员");
  12. System.out.println("exit: 退出系统");
  13. System.out.println();
  14. key = scanner.next();
  15. switch (key) {
  16. case "add":
  17. System.out.println("输入id");
  18. int id = scanner.nextInt();
  19. System.out.println("输入名字");
  20. String name = scanner.next();
  21. // 创建 雇员
  22. EmpNode empNode = new EmpNode(id, name);
  23. hashTab.add(empNode);
  24. break;
  25. case "list":
  26. hashTab.list();
  27. break;
  28. case "find":
  29. System.out.println("请输入要查找的id");
  30. id = scanner.nextInt();
  31. hashTab.findEmpById(id);
  32. break;
  33. case "exit":
  34. scanner.close();
  35. System.exit(0);
  36. default:
  37. break;
  38. }
  39. }
  40. }
  41. }
  42. //创建HashTab 管理多条链表
  43. class HashTab {
  44. private EmpLinkedList[] empLinkedListArray;
  45. private int size; // 表示有多少条链表
  46. // 构造器
  47. public HashTab(int size) {
  48. this.size = size;
  49. // 初始化empLinkedListArray
  50. empLinkedListArray = new EmpLinkedList[size];
  51. for (int i = 0; i < size; i++) {
  52. empLinkedListArray[i] = new EmpLinkedList();
  53. }
  54. }
  55. // 添加雇员
  56. public void add(EmpNode empNode) {
  57. // 根据员工的id ,得到该员工应当添加到哪条链表
  58. int empLinkedListNO = hashFun(empNode.id);
  59. // 将emp 添加到对应的链表中
  60. empLinkedListArray[empLinkedListNO].add(empNode);
  61. }
  62. // 遍历所有的链表,遍历hashtab
  63. public void list() {
  64. for (int i = 0; i < size; i++) {
  65. empLinkedListArray[i].list(i);
  66. }
  67. }
  68. // 根据输入的id,查找雇员
  69. public void findEmpById(int id) {
  70. // 使用散列函数确定到哪条链表查找
  71. int empLinkedListNO = hashFun(id);
  72. EmpNode empNode = empLinkedListArray[empLinkedListNO].findEmpById(id);
  73. if (empNode != null) {// 找到
  74. System.out.printf("在第%d条链表中找到 雇员 id = %d\n", (empLinkedListNO + 1), id);
  75. } else {
  76. System.out.println("在哈希表中,没有找到该雇员~");
  77. }
  78. }
  79. // 编写散列函数, 使用一个简单取模法
  80. public int hashFun(int id) {
  81. return id % size;
  82. }
  83. }
  84. //表示一个雇员
  85. class EmpNode {
  86. public int id;
  87. public String name;
  88. public EmpNode next; // next 默认为 null
  89. public EmpNode(int id, String name) {
  90. super();
  91. this.id = id;
  92. this.name = name;
  93. }
  94. }
  95. //创建EmpLinkedList ,表示链表
  96. class EmpLinkedList {
  97. // 首指针,指向第一个EmpNode,因此我们这个链表的head 是直接指向第一个EmpNode
  98. private EmpNode head; // 默认null
  99. // 添加雇员到链表
  100. // 说明
  101. // 1. 假定,当添加雇员时,id 是自增长,即id的分配总是从小到大
  102. // 因此我们将该雇员直接加入到本链表的最后即可
  103. public void add(EmpNode empNode) {
  104. // 如果是添加第一个雇员
  105. if (head == null) {
  106. head = empNode;
  107. return;
  108. }
  109. // 如果不是第一个雇员,则使用一个辅助的指针,帮助定位到最后
  110. EmpNode curEmp = head;
  111. while (true) {
  112. if (curEmp.next == null) {// 说明到链表最后
  113. break;
  114. }
  115. curEmp = curEmp.next; // 后移
  116. }
  117. // 退出时直接将emp 加入链表
  118. curEmp.next = empNode;
  119. }
  120. // 遍历链表的雇员信息
  121. public void list(int no) {
  122. if (head == null) { // 说明链表为空
  123. System.out.println("第 " + (no + 1) + " 链表为空");
  124. return;
  125. }
  126. System.out.print("第 " + (no + 1) + " 链表的信息为");
  127. EmpNode curEmp = head; // 辅助指针
  128. while (true) {
  129. System.out.printf(" => id=%d name=%s ", curEmp.id, curEmp.name);
  130. if (curEmp.next == null) {// 说明curEmp已经是最后结点
  131. break;
  132. }
  133. curEmp = curEmp.next; // 后移,遍历
  134. }
  135. System.out.println();
  136. }
  137. // 根据id查找雇员
  138. // 如果查找到,就返回Emp, 如果没有找到,就返回null
  139. public EmpNode findEmpById(int id) {
  140. // 判断链表是否为空
  141. if (head == null) {
  142. System.out.println("链表为空");
  143. return null;
  144. }
  145. // 辅助指针
  146. EmpNode curEmp = head;
  147. while (true) {
  148. if (curEmp.id == id) {// 找到
  149. break;// 这时curEmp就指向要查找的雇员
  150. }
  151. curEmp = curEmp.next;// 后移
  152. // 退出
  153. if (curEmp == null) {// 说明遍历当前链表没有找到该雇员
  154. break;
  155. }
  156. }
  157. return curEmp;
  158. }
  159. }




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/775690
推荐阅读
相关标签
  

闽ICP备14008679号