哈希表的结构与代码实现
哈希表的结构
哈希表(hash table)又叫做散列表,是根据key值而直接进行访问的数据结构,它通过把key值映射到表中的一个位置来访问记录,来加快查找的速度。这个映射的函数叫做散列函数,存放记录的数组,叫做散列表
代码实现
从哈希表中可以看出需要三个结构来共同管理哈希表
- 节点,用来记录节点信息
- 链表,用来管理节点的信息
- 数组,用来管理链表的信息
节点(存储信息)
//管理每一个员工的信息
class Emp {
public int no;
public String name;
public String nickname;
public Emp next;
public Emp(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "员工{" +
"编号为=" + no +
", 姓名为='" + name + '\'' +
",昵称='" + nickname + '\'' +
'}';
}
}
单向链表(用来管理节点信息)
分别设置增删改查的方法,来管理节点
//创建链表来管理员工的信息
class SingleList{
//要有节点的属性信息
public Emp head;
//增加节点
public void add(Emp newEmp){
if(head==null){
head=newEmp;
System.out.println("新员工"+newEmp.name+"添加成功!");
return;
}
Emp temp=head;
while(true){
if(temp.next==null){
temp.next=newEmp;
System.out.println("新员工"+newEmp.name+"添加成功!");
break;
}else {
temp=temp.next;
}
}
}
//按照大小顺序添加节点
public void addByOrder(Emp newEmp){
if(head==null){
head=newEmp;
System.out.print("新员工"+newEmp.name+"添加成功!");
return;
}else if (head.next==null){
if(head.no>newEmp.no){
Emp No0=head;
head=newEmp;
newEmp.next=No0;
return;
}
}else {
//还是要引入辅助变量
Emp temp = head;
//此标记用来判断所添加的元素是否已经存在
boolean flag = false;
//遍历整个链表
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no > newEmp.no) {
break;
} else if (temp.next.no == newEmp.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
System.out.println("准备插入的人编号【" + temp.no + "】已存在");
} else {
//若可以插入,则将新的节点插入
newEmp.next = temp.next;
temp.next = newEmp;
System.out.print("新员工"+newEmp.name+"添加成功!");
}
}
}
//删除节点,假设节点一定存在
public void delete(int no){
if(head.no==no&&head.next!=null){
head=head.next;
return;
}
if (head.no==no&&head.next==null){
head=null;
return;
}
Emp temp=head;
boolean flag=false;
while (true){
//说明是一个空的链表
if(temp==null){
break;
}
if(temp.next.no==no){
//说明找到了
flag=true;
break;
}
temp=temp.next;
}
if(flag){
temp.next=temp.next.next;
System.out.println("编号为【"+no+"】的员工删除成功!");
}else {
System.out.println("编号为【"+no+"】的员工不存在!");
}
}
//显示节点
public void displayAll(){
if(head==null){
System.out.println("该链表为空");
return;
}
Emp temp=head;
while(true){
if (temp!=null){
System.out.print(temp+"----->");
temp=temp.next;
}else {
break;
}
}
System.out.println("");
}
//改节点信息
public void update(Emp newEmp){
Emp temp=head;
while(true){
if(temp.no!=newEmp.no){
temp=temp.next;
}else {
temp.name=newEmp.name;
temp.nickname=newEmp.nickname;
System.out.println("修改成功!");
break;
}
}
}
}
数组(用来管理链表的信息)
//创建数组来管理链表
class ArrList{
public int size;
//这里注意是建立数组来存储每个链表
public SingleList[] lists;
//初始化数组的个数的构造方法
public ArrList(int size) {
this.size = size;
//对数组进行初始化
lists=new SingleList[size];
for(int i=0;i<size;i++){
lists[i]=new SingleList();
}
}
//哈希值,来判断插入的节点应该到哪一个链表上
public int hashCode(int no){
return no%size;
}
//增加员工
public void add(Emp newEmp){
int ListNo=hashCode(newEmp.no);
lists[ListNo].add(newEmp);
}
//按照编号的大小添加员工
public void addByOrder(Emp newEmp){
int listNo=hashCode(newEmp.no);
lists[listNo].addByOrder(newEmp);
}
//删除员工信息
public void delete(int no){
int listNo=hashCode(no);
lists[listNo].delete(no);
}
//改员工的信息
public void update(Emp node){
int listNum=hashCode(node.no);
//通过hash值来判断要加入链表的位置。
lists[listNum].update(node);
}
//遍历所有节点
public void displayAll(){
for (int i=0;i<size;i++){
lists[i].displayAll();
}
}
}
测试代码
public class HashTab2 {
public static void main(String[] args) {
ArrList hashTable=new ArrList(8);
String key="";
Scanner scanner=new Scanner(System.in);
while (true){
System.out.println("add:添加");
System.out.println("list:显示");
System.out.println("exit:退出");
System.out.println("addByOrder:按照顺序添加");
System.out.println("update:更改员工信息");
System.out.println("delete:删除员工信息");
System.out.println(" ");
key=scanner.next();
switch (key){
case "add":
System.out.println("请输入雇员id:");
int id=scanner.nextInt();
System.out.println("请输入雇员姓名");
String name=scanner.next();
System.out.println("请输入雇员昵称");
String nickname=scanner.next();
Emp newEmp=new Emp(id,name,nickname);
hashTable.add(newEmp);
break;
case "addByOrder":
System.out.println("请输入雇员id:");
id=scanner.nextInt();
System.out.println("请输入雇员姓名");
name=scanner.next();
System.out.println("请输入雇员昵称");
nickname=scanner.next();
newEmp=new Emp(id,name,nickname);
hashTable.addByOrder(newEmp);
break;
case "delete":
System.out.println("请输入雇员id:");
id=scanner.nextInt();
hashTable.delete(id);
break;
case "update":
System.out.println("请输入要修改的雇员id:");
id=scanner.nextInt();
System.out.println("请输入想要修改的雇员姓名");
name=scanner.next();
System.out.println("请输入想要修改的雇员昵称");
nickname=scanner.next();
newEmp=new Emp(id,name,nickname);
hashTable.update(newEmp);
break;
case "list":
hashTable.displayAll();
break;
case "exit":
scanner.close();
System.exit(0);
default:
break;
}
}
}
}
测试结果:
可以看出,可以实现很好的哈希表的数据结构。