【数据结构】哈希表(散列表)

news2024/11/13 9:46:39
介绍

哈希表(也叫散列表),是根据关键码值( Key value )而直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中的一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

哈希表的实际应用

Java 程序操作数据最普通的方式是直接操作数据库,经过一番操作后数据库将结果返回给程序,但是这种结构对数据库的操作非常频繁,造成了不必要的开销。

为了解决这个问题,我们可以在程序与数据库之间添加一个缓存层,把常用的数据加载到缓存层,这样就可以在缓存层中取数据,避免了对数据库的操作。

在缓存层,我们可以使用一些常见的缓存产品,如 Redis 、Memcache 等,但是这些缓存产品太重量级了,我们也可以使用哈希表来自己写一个缓存层,即先把数据存入哈希表,使用时从哈希表中取出数据。

 我们可以使用 数组+链表 来实现一个哈希表,结构如下

使用哈希表管理雇员信息

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

//表示一个雇员
class Emp {
    public int id;
    public String name;
    public Emp next;  // next 默认为空

    public Emp(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
}

//创建 EmpLinkedList ,表示链表
class EmpLinkedList {
    //头指针,指向第一个 Emp ,因此我们这个链表的 head 是直接指向第一个 Emp
    private Emp head;  //默认为空

    //添加雇员到链表
    /*
    说明
    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) {
        int tempNo = no + 1;
        if (head == null) {  //说明链表为空
            System.out.println("第" + tempNo + "条链表为空");
            return;
        }
        System.out.print("第" + tempNo + "条链表的信息为:");
        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 查找雇员
    //如果查找到,就返回 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;
    }
}

//创建 HashTab 管理多条链表
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 int hashFun(int id) {
        return id % size;
    }

    //添加雇员
    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", (empLinkedListNO + 1), id);
        } else {
            System.out.println("在哈希表中没有找到该雇员");
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1970618.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“您的连接不是私密连接”怎么解决?

遇到“您的连接不是私密连接”的警告时&#xff0c;这通常意味着浏览器无法与网站建立安全的加密连接&#xff0c;可能是因为网站的SSL证书存在问题或网络连接存在安全风险。 1、清除浏览器缓存和Cookies&#xff1a;清除浏览器缓存和Cookies有时可以解决这个问题&#xff0c;因…

在Qt中获取Windows中进程的PID

主要是用到了系统自带的工具【tasklist.exe】 利用 QProcess调用这个tasklist有一点坑&#xff0c;已经在代码中指出了。 指定为csv格式输出的话&#xff0c;在后处理时比较方便。 QList<quint64> listProcessIdentifier(QString processName) {QProcess process;QStrin…

华为OD应聘最全流程!!!

第一步&#xff1a;投递简历 提供姓名、邮箱、手机号、身份证号&#xff0c;务必慎重考虑&#xff0c;因为此后会被锁定在特定项目组。&#x1f4dd;&#x1f512; 这一步在招聘站点搜索一下即可&#xff0c;主要选择目标城市和岗位&#xff0c;一般投递之后就会有 HR 联系&…

springboot系列教程(三十):springboot整合Zookeeper组件,管理架构中服务协调

一、Zookeeper基础简介 1、概念简介 Zookeeper是一个Apache开源的分布式的应用&#xff0c;为系统架构提供协调服务。从设计模式角度来审视&#xff1a;该组件是一个基于观察者模式设计的框架&#xff0c;负责存储和管理数据&#xff0c;接受观察者的注册&#xff0c;一旦数据…

Tamato

1.导入靶机&#xff0c;扫端口目录 访问tomato/antibot_image/ 访问/antibot_image/antibots/info.php&#xff0c;右击查看源代码&#xff0c;发现文件包含漏洞 2.漏洞利用&#xff0c;在url后输入?image/etc/passwd,有显示&#xff0c;存在文件包含漏洞 发现端口没有全部扫描…

公网IP与内网IP的核心区别及辨别方法

今天我们来聊聊公网IP和内网IP的区别&#xff0c;以及如何区分这两者。在互联网时代&#xff0c;了解这些基础知识有助于我们更好地管理网络和设备。 公网IP与内网IP的区别 1. 定义和用途 公网IP&#xff1a;也称为外网IP&#xff0c;是由互联网服务提供商&#xff08;ISP&a…

现在还有一年期SSL证书吗?具体该怎么申请?

SSL证书&#xff0c;全称为Secure Sockets Layer Certificate&#xff08;安全套接层证书&#xff09;&#xff0c;是一种用于在互联网上验证网站身份和加密通信的数字证书。它类似于现实生活中的驾驶证、护照或营业执照的电子副本&#xff0c;但专门用于网络环境。SSL证书由受…

如何构建自己的交易机器人开发环境

作者&#xff1a;老余捞鱼 原创不易&#xff0c;转载请标明出处及原作者。 写在前面的话&#xff1a; 本文主要讲解如何构建一个交易机器人开发环境。描述具体的步骤和工具&#xff0c;包括使用 GitHub Codespaces、Visual Studio Code&#xff08;VS Code&#xff09;…

线上教育在线课堂知识付费小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 线上教育在线课堂知识付费小程序源码系统&#xff0c;是一款专为教育机构、个人讲师及知识创作者设计的综合性在线教育平台解决方案。该系统基于微信小程序框架开发&#xff0c;充分利用了微信庞大的用户基础和高粘性的社交属性&#xff0c;为教育内容的传播与变现提…

Publisher - hackmyvm

简介 靶机名称&#xff1a;Publisher 难度&#xff1a;简单 靶场地址&#xff1a;https://hackmyvm.eu/machines/machine.php?vmPublisher 本地环境 虚拟机&#xff1a;vitual box 靶场IP&#xff08;Publisher&#xff09;&#xff1a;192.168.56.123 跳板机IP(window…

用Python实现AI人脸识别

实现AI人脸识别通常涉及到使用深度学习库&#xff0c;如TensorFlow或PyTorch&#xff0c;配合预训练的人脸识别模型。以下是一个使用Python和TensorFlow框架中的tensorflow_hub模块来加载和使用一个预训练的人脸识别模型的简单示例。 步骤 1: 安装必要的库 首先&#xff0c;你…

【已解决】在Docker的Alpine容器中使用Docke

在Docker中使用Docker有很多种方法。 这里介绍一种在Alpine中安装使用Docker的方法&#xff0c;这种方法使用的不是宿主机的Docker&#xff0c;而是容器自身的&#xff0c;所以封装起来比较方便。 运行Alpine 用以下命令运行一个Alpine&#xff0c;记得开启--privileged参数&…

一个纯前端实现的头像生成网站

大家好&#xff0c;我是 Java陈序员。 今天&#xff0c;给大家介绍一个纯前端实现的头像生成网站。 关注微信公众号&#xff1a;【Java陈序员】&#xff0c;获取开源项目分享、AI副业分享、超200本经典计算机电子书籍等。 项目介绍 vue-color-avatar —— 一款基于 Vite Vue…

SpringBoot 依赖之Validation

Validation Validation 依赖名称: Validation功能描述: Bean Validation with Hibernate validator.使用 Hibernate 验证器进行 Bean 验证。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation&…

适用于 Mac 和 Windows 电脑的九大数据恢复软件

你们中的一些人肯定经历过由于计算机意外删除、系统崩溃、格式化、病毒攻击等而导致的严重数据丢失。 感觉不一样&#xff1f; 不用担心&#xff0c;使用数据恢复软件可以找回已删除或丢失的文件。 适用于 Mac 和 Windows 电脑的九大数据恢复软件 这里我们收集了大多数用户对…

好家伙,路由器也会中暑,你信吗?

前言 盛夏已经来很久了&#xff0c;这几天广州的天气就像女朋友&#xff0c;说变脸就变脸…… 一会儿下雨&#xff0c;一会儿又是热情满满的大晴天&#xff01; 伴随着这一切来的就是热、很热、闷热&#xff01; 感觉在阳光底下晒个2秒&#xff0c;整个人就会融化消失。 就…

RabbitMQ知识总结(工作模式)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 工作模式 简单模式 一个生产者对应一个消费者&#xff0c;通过队…

预测未来 | MATLAB实现RF随机森林多变量时间序列预测未来-预测新数据

预测未来 | MATLAB实现RF随机森林多变量时间序列预测未来-预测新数据 预测效果 基本介绍 随机森林属于 集成学习 中的 Bagging(Bootstrap AGgregation 的简称) 方法。如果用图来表示他们之间的关系如下: 随机森林是由很多决策树构成的,不同决策树之间没有关联。当我们进行…

基于raid10的Fastdfs HA搭建

1. Fastdfs HA原理 - Fastdfs引入Tracker以支持文件操作的负载均衡调度 - Fastdfs引入基于group分组的storage以支持类似raid10模式的高可靠高性能的存储 - Fastdfs引入fastdfs-nginx-module 可以重定向文件连接到文件上传时的源服务器取文件,避免客户端由于复制延迟导致的文…