【数算-18】哈希表

1、基本结构与底层原理

在这里插入图片描述
底层原理:用链表的数组来存放元素
在这里插入图片描述

2、应用实例

在这里插入图片描述

3、代码实现

1、单个节点的结构
/**
 * @author zhihua.li
 * @date 2021/2/10 - 8:28
 **/
public class Employee {
    private Integer id;
    private String name;

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", next=" + next +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Employee getNext() {
        return next;
    }

    public void setNext(Employee next) {
        this.next = next;
    }

    private Employee next;

    public Employee(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
}

2、多个节点组成的链表结构
/**
 * @author zhihua.li
 * @date 2021/2/10 - 8:30
 **/
public class EmpLinkedList {

    //    头指针,指向第一个Emloyee,不需要额外的头结点
    private Employee head;

    /*
     * 将雇员添加到链表
     * 假定当添加雇员时,直接添加到链表尾部
     * */
    public void add(Employee employee) {
        //判断当前首节点是否为空,若为空则直接将结点添加到链表尾
        if (head == null) {
            head = employee;
            return;
        }
//        首节点非空
        Employee curEmp = head;
        while (true) {
            if (curEmp.getNext() == null) {
                break;
            }
//            找到当前链表的最后一个节点
            curEmp = curEmp.getNext();
        }
        curEmp.setNext(employee);
    }

    /*
     *   遍历列表
     */
    public void list(int no) {
        if (head == null) {
            System.out.println("第" + (no + 1) + "条链表为空");
            return;
        }
//        链表非空
        System.out.print("第" + (no + 1) + "条链表信息为");
        Employee cur = head;
        while (true) {
            System.out.print(" -> id = " + cur.getId() + ",name = " + cur.getName() + "\t");
            if (cur.getNext() == null) {
                break;
            }
            cur = cur.getNext();
        }
        System.out.println();
    }

    /*
     * 根据指定id查找链表中元素
     * */
    public Employee getEmpById(Integer id) {
        if (head == null) {
            System.out.println("链表为空");
            return null;
        }
        //辅助指针
        Employee cur = head;
        while(true){
            if(cur.getId()==id){    //找到
                break;
            }
            if(cur.getNext()==null){    //没找到
                cur = null;
            }
            cur = cur.getNext();
        }
        return cur;
    }
}
3、多个链表组成的Hash表结构

/**
 * @author zhihua.li
 * @date 2021/2/10 - 8:43
 *
 **/
public class EmpHashTable {

//    定义一个链表数组
    private EmpLinkedList[] empLinkedLists;
//    定义链表数组的大小
    private Integer size;

    //    初始化HashTable
    public EmpHashTable(Integer size) {
        this.size = size;
        empLinkedLists = new EmpLinkedList[size];
//         初始化HashTable中的每个链表
        for (int i = 0; i < size; i++) {
            empLinkedLists[i] = new EmpLinkedList();
        }
    }


    //    通过取模运算来求得新添加的emp应该放在哪个链表中
    public int getPosition(Integer id) {
        return id % size;
    }

    //    根据哈希表分配算法得到链表序号插入employee
    public void add(Employee employee) {
        int position = getPosition(employee.getId());
        empLinkedLists[position].add(employee);
    }

    //    遍历哈希表中所有链表
    public void list() {
        System.out.println("当前链表信息为:");
        for (int i = 0; i < size; i++) {
//            遍历到单个链表时,调用该链表的list方法来遍历该链表中的节点元素
            empLinkedLists[i].list(i);
        }
    }

    //    通过id获取元素位置
    public void getEmpById(Integer id){
//        获取该id对应元素在哪个链表上
        int position = getPosition(id);
//        通过上一步获取到该元素对应的链表上是否存在id为指定值的元素节点
        Employee emp = empLinkedLists[position].getEmpById(id);
        if(emp != null){
            System.out.println("在第"+(position+1)+"条链表中找到该雇员,其id为:"+id);
        }else{
            System.out.println("在哈希表中未找到该雇员");
        }
    }
}

4、测试

测试代码:

import org.junit.Test;

import java.util.Scanner;

/**
 * @author zhihua.li
 * @date 2021/2/10 - 8:58
 **/
public class EmpHashTableTest {
    //    初始化一个长度为7的链表数组为Hash表
    private EmpHashTable empHashTable = new EmpHashTable(7);


    @Test
    public void test() {
//        通过一个简单的菜单来测试HashTable的功能
        String key = "";
        Scanner scanner = new Scanner(System.in);
        boolean loop = false;
        while (!loop) {
            System.out.println("===========================================================");
            System.out.println("add:添加雇员");
            System.out.println("list:显示雇员");
            System.out.println("search:查找雇员");
            System.out.println("exit:退出程序");
            key = scanner.next();
            switch (key) {
                case "add":
                    System.out.print("请输入id:");
                    int id = scanner.nextInt();
                    System.out.print("请输入名字:");
                    String name = scanner.next();
                    Employee employee = new Employee(id, name);
                    empHashTable.add(employee);
                    break;
                case "list":
                    System.out.println("所有雇员信息如下:");
                    empHashTable.list();
                    break;
                case "search":
                    System.out.print("请输入要查找的id:");
                    id = scanner.nextInt();
                    empHashTable.getEmpById(id);

                    break;
                case "exit":
                    scanner.close();
                    loop = true;
                    break;
                default:
                    System.out.println("您的输入有误,请重试!");
                    break;
            }
        }
        System.out.println("程序退出!");

    }
}

测试结果:


===========================================================
add:添加雇员
list:显示雇员
search:查找雇员
exit:退出程序
请输入id:请输入名字:===========================================================
add:添加雇员
list:显示雇员
search:查找雇员
exit:退出程序
请输入id:请输入名字:===========================================================
add:添加雇员
list:显示雇员
search:查找雇员
exit:退出程序
请输入id:请输入名字:===========================================================
add:添加雇员
list:显示雇员
search:查找雇员
exit:退出程序
所有雇员信息如下:
当前链表信息为:
第1条链表为空
第2条链表为空
第3条链表信息为 -> id = 2,name = zhangsan	
第4条链表信息为 -> id = 10,name = lisi	 -> id = 234,name = wangwu	
第5条链表为空
第6条链表为空
第7条链表为空
===========================================================
add:添加雇员
list:显示雇员
search:查找雇员
exit:退出程序
请输入要查找的id:在第3条链表中找到该雇员,其id为:2
===========================================================
add:添加雇员
list:显示雇员
search:查找雇员
exit:退出程序
程序退出!

Process finished with exit code 0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pascalzhli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值