简介
涉及的方法
add :普通添加节点的方法
sadd:顺序添加的方法
List: 显示全部节点信息
remove:根据id删除某个节点
find:查找某个节点 exit:退出程序
散列函数
HashFind:因为hash表使用数组和链表来实现的,数组里面维护了几个链表,而我们添加节点的时候如何来确定添加都能链表上呢 这就用到了散列函数 ,这个散列函数就是用取模的方式实现的用id号模数组的大小(size)这样就可以分散在某个链表上了
源码
package 哈希表;
import java.util.Scanner;
/**
* @author 一介草莽子
* version 1.0
*/
@SuppressWarnings({
"all"})
public class HashTabDemo {
public static void main(String[] args) {
//创建hashTab
HashTab hashTab = new HashTab(6);
Scanner scanner = new Scanner(System.in);
String key = "";//选择
boolean loop = true;
int id = 0;
String name = "";
while (loop) {
System.out.println("==========add:添加节点emp =========");
System.out.println("==========sadd:顺序添加节点emp =========");
System.out.println("==========List:显示所有数据=========");
System.out.println("==========find:查找某个数据=========");
System.out.println("==========remove:删除节点 =========");
System.out.println("==========exit:退出 =========");
System.out.println("请输入你的选择:");
key = scanner.next();
switch (key) {
case "add":
System.out.println("请输入id,姓名:");
id = scanner.nextInt();
name = scanner.next();
hashTab.add(new Emp(id, name));
break;
case "sadd":
System.out.println("请输入id,姓名:");
id = scanner.nextInt();
name = scanner.next();
hashTab.SortAdd(new Emp(id, name));
break;
case "List"://显示所有数据
hashTab.List();
break;
case "find"://显示所有数据
System.out.println("请输入要查找的id: ");
id = scanner.nextInt();
hashTab.findEmpById(id);
break;
case "remove":
System.out.println("请输入要删除的id:");
id = scanner.nextInt();
hashTab.remove(id);
break;
case "exit":
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出。。。");
}
}
//管理链表
class HashTab {
//设置一个管理链表的数组
private EmpLinkedList empLinkedList[];
private int size;//数组大小 可以有几个链表
public HashTab(int size) {
this.size = size;
empLinkedList = new EmpLinkedList[size];
//为每个链表赋值,初始化链表
for (int i = 0; i < size; i++) {
empLinkedList[i] = new EmpLinkedList();
}
}
//hashtab里面维护里一个数组,数组里面有一个链表 链表有一个个的emp对象
//链表完成本质上的节点添加 而暴露在外面的是hashtab 因此hashtab里面也有一个add
//add方法
public void add(Emp emp) {
//选择要添加到那个节点上
int no = HashFind(emp.getId());
empLinkedList[no].add(emp);//添加到某个数组链表上
}
//显示List() 遍历所有链表
public void List() {
for (int i = 0; i < size; i++) {
empLinkedList[i].List(i);
}
}
//查找某个节点,通过id号
public void findEmpById(int id) {
//通过散列函数来判断这个id是哪条链表上的
int no = HashFind(id);
//得到了这个no代表的是哪条链表的起始节点,在通过这个no来找这条链表里面的节点
Emp empById = empLinkedList[no].findEmpById(id);
if (empById == null) {
System.out.println("没有找到...");
} else {
System.out.println("找到了:id=" + empById.getId() + " name=" + empById.getName());
}
}
//散列函数 用来把要添加的节点分散到某个链表上 用一个取模的方法
public int HashFind(int no) {
return no % size;
}
public void remove(int id) {
//通过散列函数找到某条链表
int no = HashFind(id);
//no来找的那一条链表
empLinkedList[no].remove(id);
}
public void SortAdd(Emp emp) {
//选择要添加到那个节点上
int no = HashFind(emp.getId());
empLinkedList[no].SortAdd(emp);
}
}
//存放雇员的链表
class EmpLinkedList {
//头指针用来指向第一个元素 头指针就是第一个元素
private Emp head;
//默认添加到最后面
public void add(Emp emp) {
//判断是不是空链表是就添加到头结点里面
if (head == null) {
head = emp;
return;
}//否则就用辅助指针来遍历
Emp curEmp = head;
while (true) {
if (curEmp.next == null) {
break;
}
//遍历
curEmp = curEmp.next;
}
//找到了最后一个的next来指向新的
curEmp.next = emp;
System.out.println("添加成功..............................");
}
//显示链表信息 no 代表的是那一条链表
public void List(int no) {
if (head == null) {
System.out.println("第" + (no + 1) + "条链表为空...");
return;
}
System.out.println("第" + (no + 1) + "条链表内容为: ");
//否则就遍历打印
Emp curEmp = head;
while (true) {
if (curEmp == null) {
break;
}
System.out.printf("编号是%d,名字是%s ", curEmp.getId(), curEmp.getName());
curEmp = curEmp.next;//遍历
}
//换行
System.out.println();
}
//查找函数
public Emp findEmpById(int id) {
//head 不能动用临时指针来遍历寻找
Emp curEmp = head;
boolean flag = true;
while (true) {
if (curEmp == null) {
flag = false;
break;
}
if (curEmp.getId() == id) {
break;
}
curEmp = curEmp.next;//遍历
}
if (flag) {
return curEmp;
} else {
return null;
}
}
public void remove(int id) {
//head不能动 设置一个临时变量 curEmp
//找到被删除对象的前一个对象
//判断是不是空链表
if (head == null) {
System.out.println("空链表...");
return;
}
//判断链表的第一个节点是不是删除的对象
if (head.getId() == id) {
head = null;
System.out.println("删除成功...");
return;
} else {
//否则第一个节点就不是
Emp curEmp = head;
boolean flag = true;
while (true) {
if (curEmp.next == null) {
flag = false;//没找的的情况
break;
}
if (curEmp.next.getId() == id) {
//找到的情况
break;
}
}
if (flag) {
curEmp.next = curEmp.next.next;
System.out.println("删除成功...");
} else {
System.out.println("删除失败没找的该元素....");
}
}
}
public void SortAdd(Emp emp) {
//顺序添加链表 1 2 3 5 6 插入4
//这是没有头结点的 所以要判断头结点的内容是空还是这个链表就有一个元素
if (head == null) {
head = emp;//空链表直接插入
} else if (head.getId() >= emp.getId()) {
//待插入元素小于head里的id的情况 要是插入的节点id小于头结点id就插入到头几点前面
//让emp.next指向head 在让head指向新的 emp
emp.next = head;
head = emp;
System.out.println("顺序添加 成功...");
} else if (head.getId() < emp.getId() && head.next == null) {
//找到一个的情况 待插入元素小大于head里的id的情况
//直接插入在head后面
head.next = emp;
System.out.println("顺序添加 成功...");
} else {
//一个以上的情况
Emp curEmp = head;
while (true) {
if (curEmp.next == null) {
//插入的数比所有的都大的情况
curEmp.next = emp;
break;
}
//找到首次大于待插入节点的id 的那个节点
if (curEmp.next.getId() >= emp.getId()) {
emp.next = curEmp.next;//新emp指向首次大于的节点
curEmp.next = emp;//让前一个的curEmp.next存emp地址
System.out.println("顺序添加 成功...");
break;
}
curEmp = curEmp.next;
}
}
}
}
//雇员的类
class Emp {
private int id;
private String name;
public Emp next;//指向下一个
public Emp(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}