大一学生分享哈希表

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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Linux从文件中提取特定内容的实用技巧分享

《Linux从文件中提取特定内容的实用技巧分享》在日常数据处理和配置文件管理中,我们经常需要从大型文件中提取特定内容,本文介绍的提取特定行技术正是这些高级操作的基础,以提取含有1的简单需求为例,我们可... 目录引言1、方法一:使用 grep 命令1.1 grep 命令基础1.2 命令详解1.3 高级用法2

使用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. 私有接口方法:接口