数据结构学习笔记(六):哈希表
哈希表是根据关键码值而直接进行访问的数据结构。也就是说它通过关键码值映射到表中的一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
哈希表的具体框架如下图所示:
哈希表的组成通常为数组+链表或者数组+二叉树,本文以链表为例。接下来将结合一个具体的题目来实现哈希表的代码。题目如下:
有一个公司,当有新员工来报道时,要求将该员工的信息加入(编号,姓名),当输入该员工的编号时,要求查找到该员工的所有信息。
要求不使用数据库,速度越快越好。
分析题目过后,总结如下信息:
- 使用链表来实现哈希表,该链表不带表头;
- 实现增删览查功能。
实现代码如下:
1 .定义员工类,重写toString方法
public class Emp {
private String name;
private int num;
private Emp next;
public Emp(String name, int num) {
this.name = name;
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Emp getNext() {
return next;
}
public void setNext(Emp next) {
this.next = next;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", num=" + num +
'}';
}
}
2 .创建链表,实现增删览查功能
public class EmpLinkedList {
Emp head;
//向链表中添加结点
public void add(Emp emp){
//如果链表为空,则将添加的结点放到头节点
if (head == null){
head = emp;
return;
}
//如果链表不为空,则将结点添加到链表的最后
//为此,需要定义一个临时结点帮忙遍历链表
Emp tempEmp = head;
while (true){
if (tempEmp.getNext() == null){
tempEmp.setNext(emp);break;
}else {
tempEmp = tempEmp.getNext();
}
}
}
//遍历链表中的结点
public void list(){
if (head == null){
System.out.println("链表为空");
return;
}
Emp tempEmp = head;
while (true){
System.out.print(tempEmp);
System.out.println();
if (tempEmp.getNext() == null){
break;
}
tempEmp = tempEmp.getNext();
}
}
//查找方法
public Emp find(int num){
if (head == null){
System.out.println("链表为空");
return null;
}
Emp tempEmp = head;
while (true){
if (tempEmp.getNum() == num){
return tempEmp;
}else if(tempEmp.getNext() == null){
return null;
} else {
tempEmp = tempEmp.getNext();
}
}
}
//删除结点
public int del(int num){
int res;
if (head == null){
System.out.println("结点为空");
return 0;
}
Emp tempEmp = head;
if (head.getNum() == num){
head = tempEmp.getNext();
return 1;
}
while (true){
if (tempEmp.getNext().getNum() == num){
tempEmp.setNext(tempEmp.getNext().getNext());
return 1;
}else if (tempEmp.getNext() == null){
return 2;
}else {
tempEmp = tempEmp.getNext();
}
}
}
}
- 创建一个哈希表,管理多条链表
public class HashTab {
EmpLinkedList[] empLinkedLists;
int size;
public HashTab(int size) {
this.size = size;
empLinkedLists = new EmpLinkedList[size];
//动态初始化创建对象数组时,运算符new只是为数组本身分配空间,并没有对数组元素进行初始化,即所有元素都为空
//此时如果进行编译会报错。因此要对每个对象数组进行如下初始化:
for (int i = 0; i < size; i++) {
empLinkedLists[i] = new EmpLinkedList();
}
}
//添加方法
public void add(Emp emp){
int arraynum = emp.getNum()%size;
empLinkedLists[arraynum].add(emp);
}
//遍历方法
public void list(){
for (int i = 0; i < size; i++) {
empLinkedLists[i].list();
System.out.println();
}
}
//查找方法
public void find(int num){
int arraynum = num % size;
Emp resEmp = empLinkedLists[arraynum].find(num);
if (resEmp == null){
System.out.println("未找到该雇员");
return;
}
System.out.println(resEmp);
}
//删除方法
public void del(int num){
int res;
int arraynum = num % size;
res = empLinkedLists[arraynum].del(num);
if (res == 0){
System.out.println("链表为空");return;
}else if (res == 1){
return;
}else {
System.out.println("未找到该雇员");return;
}
}
}
最后主函数调用哈希表中的方法就可以进行相关的操作了:
public class Test {
public static void main(String[] args) {
HashTab hashTab = new HashTab(7);
hashTab.add(new Emp("李磊",1));
hashTab.add(new Emp("李雷",2));
hashTab.add(new Emp("韩梅梅",3));
hashTab.add(new Emp("韩美美",8));
hashTab.add(new Emp("韩美",15));
hashTab.del(1);
hashTab.list();
}
}