大一学生分享哈希表

2024-06-12 19:44
文章标签 学生 哈希 分享 大一

本文主要是介绍大一学生分享哈希表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据结构与算法,众妙之门,魅力无穷                                

                                                    ---同行者联盟

哈希表

哈希表使用场景与详细介绍

需求:

“三分钟内,我要那个女生的全部资料”,这是我们在霸道总裁爱上我的电视剧中常听到的话,

维护一份学生人员资料信息,当输入人员学号时,要快速查到该学生的基本信息,越快越好,且不使用数据库,要节省内存

什么是哈希表:

“散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表/哈希表。

哈希表的本质及其实现方法

哈希表本质就是数组,实现方法有两种

1、数组+链表

2、数组+红黑树

哈希表示意图:

数组+链表以及数组+红黑树两种实现形式的示意图

图片

 

为什么不直接使用数组而是要使用哈希表

hash表为了实现:通过某一个关键值(一个具体业务值)可以直接取到数据,达到和数组一样的随机访问效果。但是数组的关键值只能是下标,不具有任何业务意义,所以直接使用数组是不满足我们的需求的。那我们中间加一个函数去实现:关键值 --> 下标 --> 数据,这个就是hash函数。

哈希冲突是什么以及如何解决

哈希冲突:不同的输入数据在经过哈希函数计算后,产生了相同的哈希值。即k1 != k2,但H(k1) = H(k2),这种现象就是哈希冲突。

举个例子,比如哈希函数是:  哈希值 = 关键字 mod 10,那13和23就会产生哈希冲突,因为会映射到同一个地址上,就会产生哈希冲突

怎样解决:

F1: 开放址法

基本思想:当哈希冲突发生时,采用一定的规则在哈希表中寻找下一个可用的槽,直到找到一个空槽或者达到某个阈值为止;

对阈值的解释:

数组的长度为16,加载因子设为0.75,阈值就是总长度*加载因子的值,当已经插入的元素个数超过阈值时,需要对哈希表进行扩容操作。因为此时发生哈希冲突的概率会增大

如:

数据关键字:15 2 38 28 4 12

数组大小:13

哈希函数为 下标=关键字 mod 13

如下图,元素 15 已经占据了下标为 2 的位置,元素 2 本身也应该占据下标为 2 的位置,这时遇到哈希冲突,它就往下一个地址寻找空位。

如果遇到冲突,就往下一个地址寻找空位。新地址 = 原始位置+i(i是查找次数)

F2: 链接法 

(又叫拉链法, HashMap底层就是这样处理的)

基本思想: 将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

如:数据关键字:19,14,23,01,68,20,84,27,55,11,10,79

哈希表长度:13

哈希函数为:哈希值 = key % 13

解决需求:来实现哈希表的创建及其使用

1、哈希表的创建

创建学生类

/** 创建学生类**/
class Student {public int id;public String name;public int age;public String addr;public Student next;public Student(int id, String name, int age, String addr) {this.id = id;this.name = name;this.age = age;this.addr = addr;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", addr='" + addr + '\'' +'}';}
}

创建学生链表

/**创建学生链表**/
class StudentList {public Student head;public void addStudent(Student student) {if (head == null) {head = student;return;}Student cur = head;while (true) {if (cur.next == null) {break;}cur = cur.next;}cur.next = student;}
}

创建学生哈希表,用于管理链表

class StudentHashTable {StudentList[] studentLists;int maxSize;public StudentHashTable(int maxSize) {studentLists = new StudentList[maxSize];this.maxSize = maxSize;//初始化链表数组for (int i = 0; i < maxSize; i++) {studentLists[i] = new StudentList();}}
}

2、哈希表实现学生信息的插入操作(不考虑学生重复插入)

// 实现添加学生的方法
public void addStudent(Student student) {// 根据哈希函数,获取学生应该对应的下标int stuId = student.id % maxSize;// 将学生插入到该条链表中studentLists[stuId].addStudent(student);}

3、哈希表实现学生信息的遍历输出

学生链表类中实现遍历学生的方法

public void showStudent(int index) {if (head == null) {System.out.println("下标"+index+"下,链表为空,没有学生信息可以输出");return;}System.out.println("下标"+index+"下的学生信息分别是:");Student cur = head;System.out.println(cur.toString());while (true) {if (cur.next == null) {break;}cur = cur.next;System.out.println(cur.toString());}
}
 

哈希表中实现遍历每一个索引​​​​​​

/***   遍历学生**/
public void showStudent() {for (int i = 0; i < studentLists.length; i++) {studentLists[i].showStudent(i);}
}

4、哈希表实现根据对应学号快速找到对应学生信

学生链表类中实现通过学号获取学生信息的方法​​​​​​​

public void getStudentById(int id) {if (head == null) {System.out.println("不存在学号为" + id+ "的学生");return;}// 辅助节点初始化为头节点,即数组下标位置所代表的学生Student cur = head;// 遍历链表while (true) {if(cur.id == id){System.out.println("学号为"+id+"的同学信息为"+cur.toString());break;}if (cur.next == null) {System.out.println("不存在学号为" + id+ "的学生");break;}cur = cur.next;}
}

哈希表中实现的通过学号获取学生信息的方法

public void getStudentById(int id) {// 根据学号找到对应的数组下标int index = id % maxSize;studentLists[index].getStudentById(id);
}

测试实例​​​​​​​​​​​​​​

public static void main(String[] args) {StudentHashTable studentHashTable = new StudnetHashTable(3);for (int i = 1; i <= 6; i++) {Student stu = new Student(i, "zs" + i, 20 + i, "aaa" + i);studentHashTable.addStudent(stu);}studentHashTable.showStudent();studentHashTable.getStudentById(5);
}

这篇关于大一学生分享哈希表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1055157

相关文章

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

OpenCV在Java中的完整集成指南分享

《OpenCV在Java中的完整集成指南分享》本文详解了在Java中集成OpenCV的方法,涵盖jar包导入、dll配置、JNI路径设置及跨平台兼容性处理,提供了图像处理、特征检测、实时视频分析等应用... 目录1. OpenCV简介与应用领域1.1 OpenCV的诞生与发展1.2 OpenCV的应用领域2

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

Python虚拟环境与Conda使用指南分享

《Python虚拟环境与Conda使用指南分享》:本文主要介绍Python虚拟环境与Conda使用指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、python 虚拟环境概述1.1 什么是虚拟环境1.2 为什么需要虚拟环境二、Python 内置的虚拟环境工具

Python处理大量Excel文件的十个技巧分享

《Python处理大量Excel文件的十个技巧分享》每天被大量Excel文件折磨的你看过来!这是一份Python程序员整理的实用技巧,不说废话,直接上干货,文章通过代码示例讲解的非常详细,需要的朋友可... 目录一、批量读取多个Excel文件二、选择性读取工作表和列三、自动调整格式和样式四、智能数据清洗五、

JDK9到JDK21中值得掌握的29个实用特性分享

《JDK9到JDK21中值得掌握的29个实用特性分享》Java的演进节奏从JDK9开始显著加快,每半年一个新版本的发布节奏为Java带来了大量的新特性,本文整理了29个JDK9到JDK21中值得掌握的... 目录JDK 9 模块化与API增强1. 集合工厂方法:一行代码创建不可变集合2. 私有接口方法:接口

电脑系统Hosts文件原理和应用分享

《电脑系统Hosts文件原理和应用分享》Hosts是一个没有扩展名的系统文件,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应... Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应

Java如何将文件内容转换为MD5哈希值

《Java如何将文件内容转换为MD5哈希值》:本文主要介绍Java如何将文件内容转换为MD5哈希值的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java文件内容转换为MD5哈希值一个完整的Java示例代码代码解释注意事项总结Java文件内容转换为MD5

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置