哈希表项目


注意:哈希表在一定程度上可以看作一个缓存产品,但肯定没有redis…等产品那么强大

面试题

写一个实现:加入员工信息(id,姓名,年龄…),当输入员工id时,查到员工相关信息。要求不使用数据库,尽量节省内存并提高速度。

实现思路:

1. 将员工封装为类作为链表的Node

为每个员工写一个类,其中成员变量即为员工的个人信息,每个员工还应该与下一个员工形成链接关系,将每个员工理解为链表的每一个节点Node。

class Emp {
	public int id;
	public String name;
	public Emp next; //next 默认为 null
	public Emp(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
}

2. 进行链表的实现

当链表的节点Node(即Emp)写好了后,开始写链表的类,目的是实现每个Node的add()、list()、find()、del()方法。

//创建EmpLinkedList ,表示链表
class EmpLinkedList {
	//头指针,执行第一个Emp,因此我们这个链表的head 是直接指向第一个Emp
	private Emp head; //默认null
	
	//添加雇员到链表
	//说明
	//1. 假定,当添加雇员时,id 是自增长,即id的分配总是从小到大
	//   因此我们将该雇员直接加入到本链表的最后即可
	public void add(Emp emp) {
		//如果是添加第一个雇员
		if(head == null) {
			head = emp;
			return;
		}
		//如果不是第一个雇员,则使用一个辅助的指针,帮助定位到最后
		Emp curEmp = head;
		while(true) {
			if(curEmp.next == null) {//说明到链表最后
				break;
			}
			curEmp = curEmp.next; //后移
		}
		//退出时直接将emp 加入链表
		curEmp.next = emp;
	}
	
	//遍历链表的雇员信息
	public void list(int no) {
		if(head == null) { //说明链表为空
			System.out.println("第 "+(no+1)+" 链表为空");
			return;
		}
		System.out.print("第 "+(no+1)+" 链表的信息为");
		Emp curEmp = head; //辅助指针
		while(true) {
			System.out.printf(" => id=%d name=%s\t", curEmp.id, curEmp.name);
			if(curEmp.next == null) {//说明curEmp已经是最后结点
				break;
			}
			curEmp = curEmp.next; //后移,遍历
		}
		System.out.println();
	}
	
	//根据id查找雇员
	//如果查找到,就返回Emp, 如果没有找到,就返回null
	public Emp findEmpById(int id) {
		//判断链表是否为空
		if(head == null) {
			System.out.println("链表为空");
			return null;
		}
		//辅助指针
		Emp curEmp = head;
		while(true) {
			if(curEmp.id == id) {//找到
				break;//这时curEmp就指向要查找的雇员
			}
			//退出
			if(curEmp.next == null) {//说明遍历当前链表没有找到该雇员
				curEmp = null;
				break;
			}
			curEmp = curEmp.next;//以后
		}
		
		return curEmp;
	}
	
}

3.对链表进行封装,对哈希表进行实现

  1. 当链表类写好后,应该开始写一个哈希表的类,目的是管理这些链表。其成员变量应该有 上述链表类型的数组(数组中每个元素存一条链表的引用,这就实现了哈希表的结构)。成员变量还可以定义一个size,在构造方法中就可以初始化链表的条数(上述数组的大小)。
  2. 这个哈希表也应该有add()、list()…等等方法,作为对外的总体封装。
    以add()为例子,哈希表中的add()方法也调用了其中每个数组元素(类型为链表)的add()方法,哈希表多做的事情就是多定义一个数组的维度。
  3. 编写散列函数的作用是把所有员工散列地分配到每一条链表上。思路是除余。
//添加雇员
	public void add(Emp emp) {
		//根据员工的id ,得到该员工应当添加到哪条链表
		int empLinkedListNO = hashFun(emp.id);
		//将emp 添加到对应的链表中
		empLinkedListArray[empLinkedListNO].add(emp);
		
	}

总体实现代码如下:

class HashTab {
	private EmpLinkedList[] empLinkedListArray;
	private int size; //表示有多少条链表
	
	//构造器
	public HashTab(int size) {
		this.size = size;
		//初始化empLinkedListArray
		empLinkedListArray = new EmpLinkedList[size];
		//?留一个坑, 这时不要分别初始化每个链表
		for(int i = 0; i < size; i++) {
			empLinkedListArray[i] = new EmpLinkedList();
		}
	}
	
	//添加雇员
	public void add(Emp emp) {
		//根据员工的id ,得到该员工应当添加到哪条链表
		int empLinkedListNO = hashFun(emp.id);
		//将emp 添加到对应的链表中
		empLinkedListArray[empLinkedListNO].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].findEmpById(id);
		if(emp != null) {//找到
			System.out.printf("在第%d条链表中找到 雇员 id = %d\n", (empLinkedListNO + 1), id);
		}else{
			System.out.println("在哈希表中,没有找到该雇员~");
		}
	}
	
	 /**
     * 散列函数
     *      1、散列函数的作用是把所有员工散列地分配到每一条链表上。
     *      2、id=100则可以代表第100个员工。举例数组大小=10(10条链表)。如何把这第100个员工分到链表中?
     *          100%10=0; 99%10=9; 98%10=8; ... 
     *          这样下来100个数每个都被均匀地分配到10条链路中(只要输入id,除余后就知道改分配到哪一条链路) 
     *          
     *      3、使用一个简单取模法的思路。(取余数)
     *
     * @param id id代表员工的编号,
     * @return
     */
	public int hashFun(int id) {
		return id % size;
	}
	
	
}

4.将以上模块进行整合

将以上模块进行整合后,对外部直接就表现为哈希表,直接进行测试就行了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值