哈希表(散列)

1.问题:

需求:有一个公司,当有新员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址,,),

  • 当输入该员工的id时,要求查到该员工的所有信息。
  • 要求:不使用数据库

2.简略图解

在这里插入图片描述

3.思路:

a.创建一个雇员,此时暂时只考虑id和name

//表示一个雇员
class Emp{
    
    
	public int id;
	public String name;
	public Emp next;//默认为null
	public Emp(int id, String name) {
    
    
		super();
		this.id = id;
		this.name = name;
	}
}

b.创建一条EmpLinkedList链表,链表正常操作,增(新增员工)删(删除原)查(根据id查找员工信息)

//创建EmpLinkedList,表示链表
class EmpLinkedList {
    
    
	//创建头指针head,head指向第一个Emp,就不用一个虚拟头节点 了
	private Emp head;//默认为null
	//添加雇员到链表
	/*
	 * 说明:1.假定当添加雇员时,id是自增长,即id的分 配是从小到大,因此直接将该雇员加到本链表的最后即可
	 * 
	 */
	public void add(Emp emp) {
    
    
		//如果添加第一个雇员
		if(head == null) {
    
    
			head = emp;
			return;
		}
		//如果不是添加第一个雇员,则使用一个辅助指针
		Emp cur = head;
		while(true) {
    
    
			if(cur.next == null) {
    
    //说明到链表的最后了
				break;
			}
			cur = cur.next;
		}
		//退出循环时说明已经遍历到链表最后了
		cur.next = emp;
	}
	//遍历雇员信息
	public void list(int no) {
    
    
		if(head == null) {
    
    //说明链表为空
			System.out.println("第"+(no+1)+"链表为空");
			return;
		}
		System.out.print("第"+(no+1)+"链表的信息为:");
		Emp cur = head;
		while(true) {
    
    
			System.out.print("=>  id=" + cur.id +"  "+ "name=" + cur.name+"  ");
			if(cur.next == null) {
    
    
				break;
			}
		    cur = cur.next;
		}
		System.out.println();
	}
	//根据id 查找雇员
	//如果找到就返回,找不到返回空
	public Emp findEmpById(int id) {
    
    
		if(head == null) {
    
    
			System.out.println("链表为空");
			return null;
		}
		Emp cur = head;
		while(true) {
    
    
			if(cur.id == id) {
    
    
				//找到
				break;
			}
			//退出
			if(cur.next == null) {
    
    
				cur = null;//此时没找到,置空就行
			}
			cur = cur.next;
		}
		return cur;
	}
}

c.创建哈希表,用来管理多条链表,注意在HashTab中也需要编写增删查等方法,然后调用EmpLinkedList里面的具体方法,相当于我们能看见的只有HashTab,但是具体实现的方法却在EmpLinkedList中

class HashTab {
    
    
	private EmpLinkedList[] empLinkedListArr;
	private int size;//表示共有多少条链表
	//构造器

	public HashTab(int size) {
    
    
		this.size = size;
		//初始化empLinkedListArr
		empLinkedListArr = new EmpLinkedList[size];
		//此时不能忘了初始化每一个链表,否则会报空指针异常,因为链表此时为null
		for(int i = 0; i < size; i++) {
    
    
			empLinkedListArr[i] = new EmpLinkedList();
		}
	}
	//添加雇员
	public void add(Emp emp) {
    
    
		//根据雇员的id,得到该员工应当添加到那条链表
		int empLinkedListNo = hashNo(emp.id);
		//将emp添加到对应的链表
		empLinkedListArr[empLinkedListNo].add(emp);
	}
	//遍历HashTable
	public void list() {
    
    
		for(int i = 0; i < size; ++i) {
    
    
			empLinkedListArr[i].list(i);
		}
	}
	//编写散列函数,
	public int hashNo(int id) {
    
    
		return id % size;
	}
	//根据id 查找雇员
	public void findEmpById(int id) {
    
    
		//使用散列函数确定到哪条链表去找
		int empLinkedListNo = hashNo(id);
		Emp emp = empLinkedListArr[empLinkedListNo].findEmpById(id);
	    if(emp != null) {
    
    //找到
	    	System.out.println("在第"+(empLinkedListNo+1)+"条链表中找到雇员,id="+id);
	    } else {
    
    
	    	System.out.println("在哈希表中,没有找到该雇员");
	    }   
	}
}

d.写一个简单的菜单来测试:

public static void main(String[] args) {
    
    
		//创建哈希表
		HashTab hashTab = new HashTab(7);
		//写一个简单的菜单
		String key = "";
		Scanner sc = new Scanner(System.in);
		while(true) {
    
    
			System.out.println("add: 添加雇员");
			System.out.println("list: 显示雇员");
			System.out.println("exit: 退出系统");
			System.out.println("find: 查找雇员");
			key = sc.next();
			switch(key) {
    
    
			case "add":
				System.out.println("输入id");
				int id = sc.nextInt();
				System.out.println("输入姓名");
				String name = sc.next();
				//创建雇员
				Emp emp = new Emp(id,name);
				hashTab.add(emp);
				break;
			case "list":
				hashTab.list();
				break;
			case "find":
				System.out.println("请输入要查找的id");
				id = sc.nextInt();
				hashTab.findEmpById(id);
				break;
			case "exit":
				sc.close();
				System.exit(0);
			}
		}
	}

4.学习心得:具体方法虽然都是链表的操作,但还是有些之前学了就忘了。需要不断练习和学习。菜单写的也很好玩。

猜你喜欢

转载自blog.csdn.net/balder_girl/article/details/113609306