先介绍下什么是哈希表
哈希表, 也叫散列表, 是根据关键码值而直接进行访问的数据结构。
也就是说, 它通过关键码值映射到表中一个位置来访问记录, 以加快查找的速度, 这个映射函数叫散列函数, 存放记录的数组叫散列表。
Google面试问题描述
有一个公司, 当有新员工报道的时候, 要求将该员工的信息保存(id, 姓名, 年龄, 住址等), 当输入该员工的的id时, 要求查找该员工的所有信息。
注: 不要使用数据库, 尽量节省内存, 速度越快越好
思路分析
-
不让使用数据库, 越快越好, 我们选择哈希表
-
使用链表来实现哈希表, 该链表不带表头, 即链表的第一个结点就存放雇员信息
代码实现
/**
* 定义雇员
*/
class Emp{
public int id;
public String name;
public Emp next; // 默认是null
public Emp(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
/**
* 定义链表
*/
class EmpLinkedList{
// 头指针, 执行第一个Emp,
private Emp head; //默认null
/**
* 添加雇员到链表
* @param emp 要添加的雇员
*/
public void add(Emp emp){
// 添加第一个雇员
if(head == null){
head = emp;
return;
}
// 如果不是第一个雇员, 使用辅助指针, 帮助定位到最后
Emp curEmp = head;
while (true){
if(curEmp.next == null){
break;
}
curEmp = curEmp.next;
}
// 加入链表
curEmp.next = emp;
}
/**
* 遍历链表的雇员信息
* @param num 第几条链表
*/
public void list(int num){
if(head == null){
System.out.println("第"+(num+1)+"条链表为空");
return;
}
System.out.println("开始遍历第"+(num+1)+"条链表信息");
Emp curEmp = head; // 辅助指针
while (true){
System.out.printf("id = %d, name = %s\t", curEmp.id, curEmp.name);
if(curEmp.next == null){
break;
}
curEmp = curEmp.next;
}
System.out.println();
}
/**
* 根据id查找雇员
* @param id 雇员id
* @return 雇员 or null
*/
public Emp findEmpById(int id){
if(head == null){
System.out.println("链表为空");
return null;
}
// 辅助指针
Emp curEmp = head;
while (true){
// 找到了
if(curEmp.id == id){
break;
}
if(curEmp.next == null){//遍历结束, 没有找到
curEmp = null;
break;
}
curEmp = curEmp.next; // 后移
}
return curEmp;
}
}
/**
* 创建HashTab管理多条链表
*/
class HashTab{
private EmpLinkedList[] empLinkedListArray;
private int size;
public HashTab(int size) {
this.size = size;
this.empLinkedListArray = new EmpLinkedList[size];
// 初始化每个链表
for(int i=0; i<size; i++){
empLinkedListArray[i] = new EmpLinkedList();
}
}
/**
* 通过取模的方法获取id应该放到哪个链表
* @param id
* @return
*/
public int getSizeByHash(int id){
return id/size;
}
/**
* 添加雇员
* @param emp
*/
public void add(Emp emp){
int empLinkedListNum = getSizeByHash(emp.id);
empLinkedListArray[empLinkedListNum].add(emp);
}
/**
* 遍历所有链表
*/
public void list(){
for(int i=0; i<size; i++){
empLinkedListArray[i].list(i);
}
}
/**
* 根据id查找雇员信息
* @param id
* @return
*/
public Emp findEmpById(int id){
int empLinkedListNum = getSizeByHash(id);
Emp emp = empLinkedListArray[empLinkedListNum].findEmpById(id);
if(emp != null){
return emp;
}
return null;
}
}
/**
* 测试
*/
public class Hash {
public static void main(String[] args) {
//1. 创建一个哈希表
HashTab hashTab = new HashTab(5);
//2. 添加雇员信息
for(int i=0; i<13; i++){
Emp emp = new Emp(i, "test"+i);
hashTab.add(emp);
}
//3.遍历雇员信息
hashTab.list();
//5.根据id查找雇员信息
Emp emp = hashTab.findEmpById(4);
System.out.printf(emp.toString());
}
}
输出:
开始遍历第1条链表信息
id = 0, name = test0 id = 1, name = test1 id = 2, name = test2 id = 3, name = test3 id = 4, name = test4
开始遍历第2条链表信息
id = 5, name = test5 id = 6, name = test6 id = 7, name = test7 id = 8, name = test8 id = 9, name = test9
开始遍历第3条链表信息
id = 10, name = test10 id = 11, name = test11 id = 12, name = test12
第4条链表为空
第5条链表为空
Emp{id=4, name='test4'}