数据结构——哈希表

news2024/11/15 11:18:21

一、哈希表介绍

1.1 哈希表初了解

哈希表是属于一个数据结构,并不是一个算法

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

需求:当有新员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址....),当输入该员工的id时,要求查找到该员工的所有信息
要求:不使用数据库,尽量节省内存,越快越好

对于这种需求和要求,我们就可以 使用哈希表

每一次都查询数据库的话对数据库的压力很大,我们需要加一个缓存层(当然也可以加多个缓存层),缓存层的实现方式可以看下图。

比如,我们看下图,若我们用哈希表实现的缓存层,我们可以先把数据放在哈希表,当取数据时先在哈希表中取,取不到再到数据库,如果数据库有的话再给用户返回并添加到哈希表中。

1.2 哈希表的内存结构图

百度来的,不是自己做的

数据+链表的形式,形成散列表(也叫哈希表)

先用散列函数进行计算,看看查找的数据下标进行计算,这样就直接精确到某条链表,更快的查找效率

1.3哈希表实现思路图解

二、代码实现

在之前链表的基础上又添加了一个数组而已,并没有那么的难

哈希表在一定程度上就是一个缓存层但是没有redis缓存那么强大

public class HashTabDemo {
    public static void main(String[] args) {

//        创建hash表
        HashTab hashTab = new HashTab(7);
        Emp emp = new Emp(5, "Tom");
        Emp emp2 = new Emp(10, "Tom");
        Emp emp3 = new Emp(11, "Tom");
        Emp emp4 = new Emp(12, "Tom");
        hashTab.add(emp);
        hashTab.add(emp2);
        hashTab.add(emp3);
        hashTab.add(emp4);
        hashTab.list();

        hashTab.findEmpById(6);
    }
}


/**
 * 创建HashTab,管理多条链表
 */
class HashTab {
    //  链表EmpLinked类型的数组
    private EmpLinkedList[] empLinkedListArray;
    // 我们要创建的数组的大小,表示最多有多少条链表
    private int size;

    /**
     * 构造方法
     *
     * @param size 指定empLinkedListArray数组的大小
     */
    public HashTab(int size) {
        this.size = size;
//      初始化empLinkedListArray,记住,这个仅仅是将数组创建出来了,即 empLinkedListArray!=null,但是 empLinkedListArray[i]==null
        empLinkedListArray = new EmpLinkedList[size];

//      有坑,不要忘记这个操作!!!!!!
//      一定给要记好下面的初始化数组下标对应的链表,即让empLinkedListArray[i]!=null
        for (int i = 0; i < size; i++) {
            empLinkedListArray[i] = new EmpLinkedList();
        }

    }

    /**
     * 添加雇员:
     * 根据员工的id,得到该员工应该添加到哪条链表之上
     *
     * @param emp 要添加的雇员
     */
    public void add(Emp emp) {
        //根据员工的确定员工在哪条链之上
        int empLinkedListNo = hashFun(emp.id);
        //EmpLinkedList就是链表,在链表上进行添加
        empLinkedListArray[empLinkedListNo].add(emp);
    }

    /**
     * 遍历hash表(数组+链表共同组成hash表)
     */
    public void list() {
        for (int i = 0; i < size; i++) {
//            数组的每一个元素都是一个列表
            empLinkedListArray[i].list(i);
        }
    }

    /**
     * 根据用户的id,查找雇员
     *
     * @param id
     * @return
     */
    public void findEmpById(int id) {
//       根据id我们先确定好在哪条链
        int empLinkedListNO = hashFun(id);
//       确定好链之后我们再从链中找元素
        Emp emp = empLinkedListArray[empLinkedListNO].findEmpById(id);
        if (emp != null) {
//       找到
            System.out.println("在"+empLinkedListNO+"中找到雇员:"+emp.id+"---->"+emp.name);
        } else {
//       没有找到
            System.out.println("没有在哈希表中找到该雇员  ");
        }
    }


    /**
     * 编写散列函数,使用一个简单取模法
     * 作用:根据员工的id确定在哪条链表之上
     *
     * @param id
     * @return
     */
    public int hashFun(int id) {
        return id % size;
    }


}


/**
 * 表示雇员
 */
class Emp {
    public int id;
    public String name;
    public Emp next;     //指向下一个节点的引用 next默认为空就可以了


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


}

/**
 * 表示链表
 */
class EmpLinkedList {
    //   头指针,链表的head,指向第一个雇员Emp,因此我们这里直接这么写就可以
    private Emp head; //默认为空


    /**
     * 添加雇员到列表
     * 说明:
     * 假定,添加雇员时,id是自增长的,即id的分配总是从小到达,因此我们将该雇员加入到本链表的最后即可
     *
     * @param emp
     */
    public void add(Emp emp) {
        if (head == null) {
//          head为空说明是第一个雇员,直接将雇员emp赋值给head
            head = emp;
//          添加成功直接返回
            return;
        }

//      运行到这里说明不是第一个雇员,接下来我们就要遍历链表找到对应的地方添加进去
        Emp curEmp = head;
        while (curEmp.next != null) {
//         移动指针
            curEmp = curEmp.next;
        }
//       运行到这里curEmp的next是null,我们加在这里就好了
        curEmp.next = emp;
    }

    /**
     * 遍历链表的雇员信息
     */
    public void list(int number) {
        if (head == null) {
//          链表为空
            System.out.println("第" + number + "条链表为空");
            return;
        }
        System.out.println("第" + number + "条链表的信息为:");

//      辅助指针遍历链表
        Emp curEmp = head;
        while (curEmp != null) {
            System.out.println("====>id=" + curEmp.id + "-----name=" + curEmp.name);
//          指针后移动
            curEmp = curEmp.next;
        }
//      单纯的想输出一个换行
        System.out.println();
    }

    /**
     * 如果查找到,就返回Emp,没找到返回空
     *
     * @param id
     * @return
     */
    public Emp findEmpById(int id) {
        if (head == null) {
            System.out.println("链表为空");
//           就不用再往下找了
            return null;
        }
//         辅助指针
        Emp curEmp = head;
//        遍历所在的链
        while (curEmp != null) {
            if (curEmp.id == id) {
                break;
            }
//          后移
            curEmp = curEmp.next;
        }
//      这个情况可能是找到了返回结果,也有可能是这个链上直接没有返回的null
        return curEmp;
    }
}

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

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

相关文章

解析永春堂1300模式为何风靡新零售市场

最近&#xff0c;永春堂1300模式风靡新零售市场&#xff0c;它凭借兼顾大、小、新、老会员&#xff0c;没有沉淀和泡沫等特点&#xff0c;引起市场的热切关注。而永春堂1300模式如此受欢迎的原因&#xff0c;最重要的&#xff0c;还是它丰厚的奖项报酬。永春堂1300直销模式主要…

Spring Boot 实现接口幂等性的 4 种方案

一、什么是幂等性 幂等是一个数学与计算机学概念&#xff0c;在数学中某一元运算为幂等时&#xff0c;其作用在任一元素两次后会和其作用一次的结果相同。 在计算机中编程中&#xff0c;一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数或幂…

多态与虚(函数)表

前言续接上回&#xff08;继承&#xff09;&#xff0c;我们了解了继承是如何通过虚基表&#xff0c;来解决派生类和父类有相同的成员变量的情况&#xff0c;但是类和对象中可不只有成员变量&#xff0c;如果成员函数也有同名&#xff0c;更或者如果我们想在访问不同情况&#…

Zeppelin【部署 01】Zeppelin最新版本zeppelin-0.10.1下载安装配置启动及问题处理(一篇学会部署Zeppelin)

1.简单介绍 来自百度百科&#xff1a; Apache Zeppelin 是一个让交互式数据分析变得可行的基于网页的开源框架。提供了数据分析、数据可视化等功能。是一个提供交互数据分析且基于Web的笔记本。方便你做出可数据驱动的、可交互且可协作的精美文档&#xff0c;并且支持多种语言…

JavaScript 简单计算

parseFloat和Number parseFloat()并不能进行数据类型转换&#xff0c; 所以对字符串进行parseFloat()是不起作用的&#xff0c; 需要使用Number()进行强制类型转换&#xff1b; 但是&#xff0c;如果真正涉及到精度计算&#xff0c;建议用decimal.js 毕竟&#xff0c;js的…

深入理解Linux进程

进程参数和环境变量的意义一般情况下&#xff0c;子进程的创建是为了解决某个问题。那么解决问题什么问题呢&#xff1f;这个就需要进程参数和环境变量来进行决定的。子进程解决问题需要父进程的“数据输入”(进程参数 & 环境变量)设计原则&#xff1a;3.1 子进程启动的时候…

项目实战典型案例6——没有复用思想

这里写目录标题一&#xff1a;背景介绍反例思路&方案反例一的优化思路和方案反例一优化的模拟代码测试优化之前的缺点与优化之后的优点反例二的优化思路和方案反例二优化的模拟代码测试优化之前的缺点与优化之后的优点四&#xff1a;总结一&#xff1a;背景介绍 本篇博客是…

Spring Boot统一功能处理

目录 一、统一用户登录权限验证 1.1 自定义拦截器 1.2 将自定义拦截器加入到系统配置 1.3 统一访问前缀 二、统一异常处理 三、统一数据格式返回 一、统一用户登录权限验证 1.1 自定义拦截器 拦截器是一个普通的类&#xff0c;需要实现HandlerInterceptor接口并重写pre…

centos安装docker,docker-cpmpose教程及疑难解决

1、安装dockeryum -y install docker出现完毕&#xff08;complete&#xff09;则表示安装完成2、启动docker服务systemctl start docker报错如下&#xff0c;让通过 systemctl status docker.service 和 journalctl -xe 命令查看详情输入systemctl status docker.service&…

在ROS2中,通过MoveIt2控制Gazebo中的自定义机械手

目前的空余时间主要都在研究ROS2&#xff0c;最终目的是控制自己用舵机组装的机械手。 由于种种原因&#xff0c;先控制Gazebo的自定义机械手。 先看看目前的成果 左侧是rviz2中的moveit组件的机械手&#xff0c;右侧是gazebo中的机械手。在moveit中进行路径规划并执行后&#…

RolePred: Open-Vocabulary Argument Role Prediction for Event Extraction 论文解读

Open-Vocabulary Argument Role Prediction for Event Extraction 论文&#xff1a;2211.01577.pdf (53yu.com) 代码&#xff1a;yzjiao/RolePred: Source code for EMNLP findings paper “Open-Vocabulary Argument Role Prediction for Event Extraction” (github.com) 期…

优思学院|我们的企业面对哪些危机?六西格玛如何处理这些危机?

如果你在某公司买到的产品经常出现问题&#xff0c;你还会再去买他们的产品吗&#xff1f;如果某公司为你提供的服务经常不如你所预期&#xff0c;你还会再次使用他们的服务吗&#xff1f; 六西格玛管理是以客户为中心&#xff0c;透过六西格玛的工具和方法&#xff0c;针对问…

【黑马】Java基础从入门到起飞目录合集

视频链接&#xff1a; Java入门到起飞&#xff08;上部&#xff09;&#xff1a;BV17F411T7AoJava入门到起飞&#xff08;下部&#xff09;&#xff1a;BV1yW4y1Y7Ms 学习时间&#xff1a; 2023/02/01 —— 2023/03/09断断续续的学习&#xff0c;历时大概37天&#xff0c;完结撒…

php+bootstrap+jquery+mysql实现购物车项目案例

获取源码 一键三连后&#xff0c;评论区留下邮箱安排发送&#xff1a;&#xff09; 介绍 使用php,bootstrap,jquery,mysql实现的简易购物车案例。 通过本案例&#xff0c;你将学习到以下知识点&#xff1a; php 操作 mysql 实现增删改查掌握 php 常用数组函数掌握 php $…

HBase 2.x核心技术

HBase 2.x主要包含以下核心功能&#xff1a; 1、基于Procedure v2重新设计了HBase的Assignment Manager和核心管理流程。通过Procedure v2&#xff0c;HBase能保证各核心步骤的原子性&#xff0c;从设计上解决了分布式场景下多状态不一致的问题。 2、实现了In Memory Compactio…

Chapter2.2:线性表的顺序表示

该系列属于计算机基础系列中的《数据结构基础》子系列&#xff0c;参考书《数据结构考研复习指导》(王道论坛 组编)&#xff0c;完整内容请阅读原书。 2.线性表的顺序表示 2.1 顺序表的定义 线性表的顺序存储亦称为顺序表&#xff0c;是用一组地址连续的存储单元依次存储线性表…

脑机接口科普0017——飞米

本文禁止转载&#xff01;&#xff01;&#xff01;&#xff01; 在我们的九年制义务教育体系中&#xff0c;我们知道纳米是个很小的单位&#xff0c;一般进行单位制的转换的时候&#xff0c;最小就只能到达纳米级别了。 1nm 10^-9 m 这会给学生造成一种误解。认为纳米就是…

搭建兰空图床(Lsky Pro)-docker

兰空图床(Lsky Pro) 官方网站&#xff1a;https://www.lsky.pro/ GitHub&#xff1a;https://github.com/lsky-org/lsky-pro 一, 安装docker-compose 下载-授权 #下载 国内地址 curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-una…

dl----算法常识100例

1.depthwise卷积&&Pointwise卷积 depthwise与pointwise卷积又被称为Depthwise Separable Convolution&#xff0c;与常规卷积不同的是此卷积极大地减少了参数数量&#xff0c;同时保持了模型地精度&#xff0c;depthwise操作是先进行二维平面上地操作&#xff0c;然后利…

nginx的学习

1. 我们今天的目标是学习 了解认识nginx的基本结构和语法学习经典案例 2. Nginx是什么 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;Nginx是由俄罗斯的人开发的&#xff0c;因它的稳定性、丰富的功能集…