大一学生分享哈希表

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

相关文章

MySQL8.2.0安装教程分享

《MySQL8.2.0安装教程分享》这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤... 目录mysql的安装图文1.python访问网址2javascript.点击3.进入Downloads向下滑动4.选择Community Server5.

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

10个Python自动化办公的脚本分享

《10个Python自动化办公的脚本分享》在日常办公中,我们常常会被繁琐、重复的任务占据大量时间,本文为大家分享了10个实用的Python自动化办公案例及源码,希望对大家有所帮助... 目录1. 批量处理 Excel 文件2. 自动发送邮件3. 批量重命名文件4. 数据清洗5. 生成 PPT6. 自动化测试

10个Python Excel自动化脚本分享

《10个PythonExcel自动化脚本分享》在数据处理和分析的过程中,Excel文件是我们日常工作中常见的格式,本文将分享10个实用的Excel自动化脚本,希望可以帮助大家更轻松地掌握这些技能... 目录1. Excel单元格批量填充2. 设置行高与列宽3. 根据条件删除行4. 创建新的Excel工作表5

Redis多种内存淘汰策略及配置技巧分享

《Redis多种内存淘汰策略及配置技巧分享》本文介绍了Redis内存满时的淘汰机制,包括内存淘汰机制的概念,Redis提供的8种淘汰策略(如noeviction、volatile-lru等)及其适用场... 目录前言一、什么是 Redis 的内存淘汰机制?二、Redis 内存淘汰策略1. pythonnoe

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

C#读取本地网络配置信息全攻略分享

《C#读取本地网络配置信息全攻略分享》在当今数字化时代,网络已深度融入我们生活与工作的方方面面,对于软件开发而言,掌握本地计算机的网络配置信息显得尤为关键,而在C#编程的世界里,我们又该如何巧妙地读取... 目录一、引言二、C# 读取本地网络配置信息的基础准备2.1 引入关键命名空间2.2 理解核心类与方法

Golang使用etcd构建分布式锁的示例分享

《Golang使用etcd构建分布式锁的示例分享》在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统,分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要,它有助于维护一致性,防止竞... 目录引言环境准备新建Go项目实现加锁和解锁功能测试分布式锁重构实现失败重试总结引言我们将使用Go作

Python中列表的高级索引技巧分享

《Python中列表的高级索引技巧分享》列表是Python中最常用的数据结构之一,它允许你存储多个元素,并且可以通过索引来访问这些元素,本文将带你深入了解Python列表的高级索引技巧,希望对... 目录1.基本索引2.切片3.负数索引切片4.步长5.多维列表6.列表解析7.切片赋值8.删除元素9.反转列表