Emp
/*** 表示一个雇员*/class Emp{public int id;public String name;public Emp next;//next 默认为空public Emp(int id, String name) {this.id = id;this.name = name;}}
HashTab
///创建hashTab 管理多条链表class HashTab{// 数组里面放的是链表private EmpLinkedList[] empLinkedListArray;//private Integer size = 7;// 构造器public HashTab(int size) {// 初始化empLinkedListArrayempLinkedListArray = new EmpLinkedList[size];// ? 留一个坑// 这里能直接用么/** add:添加雇员list:显示雇员exit:退出雇员add输入idtomException in thread "main" java.util.InputMismatchExceptionat java.util.Scanner.throwFor(Scanner.java:864)at java.util.Scanner.next(Scanner.java:1485)at java.util.Scanner.nextInt(Scanner.java:2117)at java.util.Scanner.nextInt(Scanner.java:2076)at com.atguigu.hashtab.HashTabDemo.main(HashTabDemo.java:30)Process finished with exit code 1* */// 这个时候不要忘了, 分别初始化 每个链表for (int i = 0; i < size; i++) {// 数组中的每一个元素都需要创建一把empLinkedListArray[i] = new EmpLinkedList();}}// 添加雇员public void add(Emp emp) {// 根据员工的id,得到该员工应当加入到,哪条链表int empLinkedListNO = hashFun(emp.id);// 将emp 添加到对应的链表中empLinkedListArray[empLinkedListNO].add(emp);}// 不管你是什么操作,总是要找链表// 遍历所有的链表public void list() {// 遍历Hash表for (int i = 0; i < size; i++) {empLinkedListArray[i].list(i);}}// 编写一个散列函数// 散列函数有很多种写法// 这里使用简单的方法-取模法public int hashFun(int id) {return id % size;}/*** 更根据输入的id,查找雇员* @param id*/public void findEmpById(int id) {// 使用散列函数确定到哪条链表查找int empLinkedListNO = hashFun(id);Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);if (emp != null) {// 说明找到了System.out.println("找到了该雇员");System.out.printf("在第%d条链表中找到了该雇员,id = %d",id,empLinkedListNO+1);} else {System.out.println("在哈希表中,没有找到该雇员~");}}}
EmpLinkedList
class EmpLinkedList{// 头指针, 执行第一个Emp,因此我们这个链表的head,是直接 指向第一个Empprivate Emp head;//添加雇员到链表// 说明.// 1. 假定,当添加雇员的时候,id是自增长的,即id 的分配总是从小到大public void add(Emp emp) {// 如果是添加第一个雇员if (head == null) {head = emp;return;}// 如果不是添加第一个雇员,则使用一个辅助的指针,帮助定位到最后Emp currEmp = head;while (true) {if (currEmp.next == null) {// 说明到链表最后break;}// 后移currEmp = currEmp.next;}// 退出时,直接将emp 加入链表currEmp.next = emp;}// 遍历链表的雇员信息public void list(int no) {// 判断是否为空if (head == null) {// 说明链表为空System.out.println("当前链"+no+"表为空!");return;}// 没有空// 打印信息System.out.println("当前链"+no+"表的信息为");// 辅助指针Emp currEmp = head;while (true) {System.out.printf("=> id =%d name = %s\t",currEmp.id,currEmp.name);if (currEmp.next == null) {// 说明,currEmp 已经是最后节点break;}// 后移 遍历currEmp = currEmp.next;}System.out.println();}/*** // 根据id 查找雇员* // 如果查找到 ,就返回Emp,如果没有找打到,就返回null* @param id* @return*/public Emp findEmpById(int id) {// 判断链表是否为空if (head == null) {System.out.println("链表为空");return null;}//辅助指针Emp curEmp = head;while (true) {//if (curEmp.id == id) {// 找到break;// 这个时候,currEmp就指向了要查找的雇员}// 退出if (curEmp.next == null) {// 说明遍历当前链表没有找到该雇员curEmp = null;}// 后移curEmp = curEmp.next;}return curEmp;}}
主函数
public static void main(String[] args) {// 创建哈希表HashTab hashTab = new HashTab(7);// 写一个简单的菜单来测试String key = "";Scanner scanner = new Scanner(System.in);while (true) {System.out.println("add:添加雇员");System.out.println("list:显示雇员");System.out.println("find:查找雇员");System.out.println("exit:退出雇员");key = scanner.next();switch (key) {case "add":System.out.println("输入id");int id = scanner.nextInt();System.out.println("输入名字");String name = scanner.next();// 创建雇员Emp emp = new Emp(id, name);hashTab.add(emp);break;case "list":hashTab.list();break;case "find":System.out.println("输入id");int findId = scanner.nextInt();hashTab.findEmpById(findId);break;case "exit":scanner.close();System.exit(0);default:break;}}}
add:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id1输入名字tomadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id2输入名字jackadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id3输入名字pinadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id6输入名字nancadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员list当前链0表为空!当前链1表的信息为=> id =1 name = tom当前链2表的信息为=> id =2 name = jack当前链3表的信息为=> id =3 name = pin当前链4表为空!当前链5表为空!当前链6表的信息为=> id =6 name = nancadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id123输入名字smeadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员list当前链0表为空!当前链1表的信息为=> id =1 name = tom当前链2表的信息为=> id =2 name = jack当前链3表的信息为=> id =3 name = pin当前链4表的信息为=> id =123 name = sme当前链5表为空!当前链6表的信息为=> id =6 name = nancadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id678输入名字vicradd:添加雇员list:显示雇员find:查找雇员exit:退出雇员list当前链0表为空!当前链1表的信息为=> id =1 name = tom当前链2表的信息为=> id =2 name = jack当前链3表的信息为=> id =3 name = pin当前链4表的信息为=> id =123 name = sme当前链5表为空!当前链6表的信息为=> id =6 name = nanc => id =678 name = vicradd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id389输入名字wefadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id9输入名字zhoadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员list当前链0表为空!当前链1表的信息为=> id =1 name = tom当前链2表的信息为=> id =2 name = jack => id =9 name = zho当前链3表的信息为=> id =3 name = pin当前链4表的信息为=> id =123 name = sme => id =389 name = wef当前链5表为空!当前链6表的信息为=> id =6 name = nanc => id =678 name = vicradd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id34输入名字machadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员list当前链0表为空!当前链1表的信息为=> id =1 name = tom当前链2表的信息为=> id =2 name = jack => id =9 name = zho当前链3表的信息为=> id =3 name = pin当前链4表的信息为=> id =123 name = sme => id =389 name = wef当前链5表为空!当前链6表的信息为=> id =6 name = nanc => id =678 name = vicr => id =34 name = machadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员find输入id8Exception in thread "main" java.lang.NullPointerExceptionat com.atguigu.hashtab.EmpLinkedList.findEmpById(HashTabDemo.java:237)at com.atguigu.hashtab.HashTab.findEmpById(HashTabDemo.java:128)at com.atguigu.hashtab.HashTabDemo.main(HashTabDemo.java:44)Process finished with exit code 1
最后这里置空要 加上break
if (curEmp.next == null) {// 说明遍历当前链表没有找到该雇员curEmp = null;break;}
这下就可以了
add:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id1输入名字tomadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id2输入名字nancyadd:添加雇员list:显示雇员find:查找雇员exit:退出雇员add4add:添加雇员list:显示雇员find:查找雇员exit:退出雇员add输入id4输入名字victoradd:添加雇员list:显示雇员find:查找雇员exit:退出雇员list当前链0表为空!当前链1表的信息为=> id =1 name = tom当前链2表的信息为=> id =2 name = nancy当前链3表为空!当前链4表的信息为=> id =4 name = victor当前链5表为空!当前链6表为空!add:添加雇员list:显示雇员find:查找雇员exit:退出雇员find输入id6链表为空在哈希表中,没有找到该雇员~add:添加雇员list:显示雇员find:查找雇员exit:退出雇员find输入id4找到了该雇员在第4条链表中找到了该雇员,id = 5add:添加雇员list:显示雇员find:查找雇员exit:退出雇员
完整代码
package com.atguigu.hashtab;import java.util.Scanner;/*** ClassName: <br/>* Description: <br/>* Date: 2021-02-24 13:10 <br/>* <br/>* @project data_algorithm* @package com.atguigu.hashtab*/public class HashTabDemo {public static void main(String[] args) {// 创建哈希表HashTab hashTab = new HashTab(7);// 写一个简单的菜单来测试String key = "";Scanner scanner = new Scanner(System.in);while (true) {System.out.println("add:添加雇员");System.out.println("list:显示雇员");System.out.println("find:查找雇员");System.out.println("exit:退出雇员");key = scanner.next();switch (key) {case "add":System.out.println("输入id");int id = scanner.nextInt();System.out.println("输入名字");String name = scanner.next();// 创建雇员Emp emp = new Emp(id, name);hashTab.add(emp);break;case "list":hashTab.list();break;case "find":System.out.println("输入id");int findId = scanner.nextInt();hashTab.findEmpById(findId);break;case "exit":scanner.close();System.exit(0);default:break;}}}}///创建hashTab 管理多条链表class HashTab{// 数组里面放的是链表private EmpLinkedList[] empLinkedListArray;//private Integer size = 7;// 构造器public HashTab(int size) {// 初始化empLinkedListArrayempLinkedListArray = new EmpLinkedList[size];// ? 留一个坑// 这里能直接用么/** add:添加雇员list:显示雇员exit:退出雇员add输入idtomException in thread "main" java.util.InputMismatchExceptionat java.util.Scanner.throwFor(Scanner.java:864)at java.util.Scanner.next(Scanner.java:1485)at java.util.Scanner.nextInt(Scanner.java:2117)at java.util.Scanner.nextInt(Scanner.java:2076)at com.atguigu.hashtab.HashTabDemo.main(HashTabDemo.java:30)Process finished with exit code 1* */// 这个时候不要忘了, 分别初始化 每个链表for (int i = 0; i < size; i++) {// 数组中的每一个元素都需要创建一把empLinkedListArray[i] = new EmpLinkedList();}}// 添加雇员public void add(Emp emp) {// 根据员工的id,得到该员工应当加入到,哪条链表int empLinkedListNO = hashFun(emp.id);// 将emp 添加到对应的链表中empLinkedListArray[empLinkedListNO].add(emp);}// 不管你是什么操作,总是要找链表// 遍历所有的链表public void list() {// 遍历Hash表for (int i = 0; i < size; i++) {empLinkedListArray[i].list(i);}}// 编写一个散列函数// 散列函数有很多种写法// 这里使用简单的方法-取模法public int hashFun(int id) {return id % size;}/*** 更根据输入的id,查找雇员* @param id*/public void findEmpById(int id) {// 使用散列函数确定到哪条链表查找int empLinkedListNO = hashFun(id);Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);if (emp != null) {// 说明找到了System.out.println("找到了该雇员");System.out.printf("在第%d条链表中找到了该雇员,id = %d",id,empLinkedListNO+1);} else {System.out.println("在哈希表中,没有找到该雇员~");}}}/*** 表示一个雇员*/class Emp{public int id;public String name;public Emp next;//next 默认为空public Emp(int id, String name) {this.id = id;this.name = name;}}class EmpLinkedList{// 头指针, 执行第一个Emp,因此我们这个链表的head,是直接 指向第一个Empprivate Emp head;//添加雇员到链表// 说明.// 1. 假定,当添加雇员的时候,id是自增长的,即id 的分配总是从小到大public void add(Emp emp) {// 如果是添加第一个雇员if (head == null) {head = emp;return;}// 如果不是添加第一个雇员,则使用一个辅助的指针,帮助定位到最后Emp currEmp = head;while (true) {if (currEmp.next == null) {// 说明到链表最后break;}// 后移currEmp = currEmp.next;}// 退出时,直接将emp 加入链表currEmp.next = emp;}// 遍历链表的雇员信息public void list(int no) {// 判断是否为空if (head == null) {// 说明链表为空System.out.println("当前链"+no+"表为空!");return;}// 没有空// 打印信息System.out.println("当前链"+no+"表的信息为");// 辅助指针Emp currEmp = head;while (true) {System.out.printf("=> id =%d name = %s\t",currEmp.id,currEmp.name);if (currEmp.next == null) {// 说明,currEmp 已经是最后节点break;}// 后移 遍历currEmp = currEmp.next;}System.out.println();}/*** // 根据id 查找雇员* // 如果查找到 ,就返回Emp,如果没有找打到,就返回null* @param id* @return*/public Emp findEmpById(int id) {// 判断链表是否为空if (head == null) {System.out.println("链表为空");return null;}//辅助指针Emp curEmp = head;while (true) {//if (curEmp.id == id) {// 找到break;// 这个时候,currEmp就指向了要查找的雇员}// 退出if (curEmp.next == null) {// 说明遍历当前链表没有找到该雇员curEmp = null;break;}// 后移curEmp = curEmp.next;}return curEmp;}}
扩展
删除功能???
