哈希表详解
哈希表说明
- 哈希表,又称为散列表,通过关键码值来存储数据,具有很高的查询效率
- 哈希表的核心思想是数组里边存储链表
- 哈希表一般用作数据的缓冲层,因为它的快速高效及结构特性
通过向员工系统中添加员工模拟哈希表思路分析
- 先创建一个员工类,实例化对象为一个实际存在的员工,类似于链表的节点
- 然后创建链表类,每个链表中可以有多个员工信息,当然每条链表都包含自身的增删查改方法
- 再创建哈希表类,表示一张哈希表,哈希表由链表数组组成,及每个哈希表中可以有多条链表,而每条链表中又有多个员工的信息
- 哈希类通过调用链表类的增删查改方法,完成对哈希表的各种操作
- 创建功能菜单进行测试
- 源码详解见下
源码及分析
员工类
//员工类
class Emp{
public int id;
public String name;
public Emp next;
public Emp(int id, String name) {
this.id = id;
this.name = name;
}
}
链表类
//包含多条员工信息的链表
class EmpLinkedList{
//头指针,保存链表的第一个元素,不为空
private Emp head;
//向链表中添加元素,假设不按照员工的序列,直接添加到链表的最后
public void add(Emp emp){
//如果头节点为空,则直接添加到头节点
if (head == null){
head = emp;
return;
}
//否则添加到最后
//定义辅助指针指向头节点,因为头节点不能动
Emp cur = head;
while (true){
if (cur.next == null){
break;
}
cur = cur.next;
}
cur.next = emp;
}
//根据哈希表中链表编号遍历链表信息
public void list(int no){
if (head == null){
System.out.println("第 " + (no + 1) + " 条链表为空");
return;
}
System.out.println("第 " + (no + 1) + " 条链表信息为: ");
//定义辅助变量用于遍历。因为头节点不能动
Emp cur = head;
while (true){
System.out.printf("-->id = %d name = %s",cur.id,cur.name);
if (cur.next == null){
break;
}
cur = cur.next;
}
System.out.println();
}
//根据id查找员工
public Emp findById(int id){
if (head == null){
System.out.println("链表为空~~");
return null;
}
//定义辅助指针用于查找
Emp cur = head;
while (true){
if (cur.id == id){
break;
}
if (cur.next == null){
cur = null;
break;
}
cur = cur.next;
}
return cur;
}
}
哈希表类
//创建HashTab管理多条链表
class HashTab{
//使用EmpLinkedList数组模拟哈希
private EmpLinkedList[] empLinkedListArray;
//哈希中有多少条链表
private int size;
public HashTab(int size){
this.size = size;
empLinkedListArray = new EmpLinkedList[size];
//分别初始化每条链表
for (int i = 0; i < size; i++) {
empLinkedListArray[i] = new EmpLinkedList();
}
}
//添加员工,根据员工的id判断该员工应该添加到那条链表
public void add(Emp emp){
int empLinkedListId = hashFun(emp.id);
empLinkedListArray[empLinkedListId].add(emp);
}
//遍历所有的链表,即遍历hashTab
public void list(){
for (int i = 0; i < size; i++) {
empLinkedListArray[i].list(i);
}
}
//根据输入的id查找雇员
public void findEmpById(int id){
//根据散列函数确定到那条链表查找
int empLinkedListNo = hashFun(id);
Emp emp = empLinkedListArray[empLinkedListNo].findById(id);
if (emp != null){
System.out.printf("在%d链表中找到雇员编号为%d的员工",(empLinkedListNo + 1),id);
System.out.println();
}else {
System.out.println("在哈希表中没有找到该雇员~~");
}
}
//编写散列函数,使用简单的取模法
public int hashFun(int id){
return id % size;
}
}
测试类
public static void main(String[] args) {
//测试哈希表
HashTab hashTab = new HashTab(7);
Scanner scanner = new Scanner(System.in);
String key = "";
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");
id = scanner.nextInt();
hashTab.findEmpById(id);
break;
case "exit":
scanner.close();
System.exit(0);
default:
break;
}
}
}