数据结构程序设计——哈希表的应用(2)->哈希表解决冲突的方法
目录
实验须知
代码实现
实验报告
一:问题分析
二、数据结构
1.逻辑结构
2.物理结构
三、算法
(一)主要算法描述
1.用除留余数法构造哈希函数
2.线性探测再散列法
(一)主要算法实现代码
四、上机调试
实验须知
实验目的: 深入理解哈希表解决冲突的办法。实验内容: 针对自己所在班级中学生姓名设计一个哈希表,使得平均查找长度不超过 R ,并完成相应的建表和查表程序。实验要求:( 1 )创建名为 kcsj19.cpp 的文件,在其中编写哈希查找学生姓名的程序;( 2 )假设学生姓名为中国人姓名的汉语拼音形式。待填入哈希表的学生姓名共有 30 个,取平均查找 长度的上限为 2 。哈希函数用除留余数法构造,用线性探测再散列法或链地址法处理冲突;( 3 )测试数据:取读者周围较熟悉的 30 个学生姓名。
代码实现
import java.util.Arrays;
import java.util.Scanner;public class Kcsj19 {private static final int TABLE_SIZE = 61; // 哈希表的大小,选择质数可以减少冲突private String[] table;public Kcsj19() {table = new String[TABLE_SIZE];Arrays.fill(table, "");}// 哈希函数:除留余数法private int hashFunction(String key) {int hashValue = 0;for (char ch : key.toCharArray()) {hashValue = (hashValue * 31 + ch) % TABLE_SIZE;}return hashValue;}// 线性探测再散列法private int linearProbe(int index, int attempt) {return (index + attempt) % TABLE_SIZE;}// 插入元素private void insert(String name) {int index = hashFunction(name);int attempt = 0;while (!table[index].isEmpty()) {attempt++;index = linearProbe(index, attempt);}table[index] = name;}// 查找元素private boolean search(String name) {int index = hashFunction(name);int attempt = 0;while (!table[index].isEmpty()) {if (table[index].equals(name)) {System.out.println("学生姓名 " + name + " 在哈希表中。");return true;}attempt++;index = linearProbe(index, attempt);}System.out.println("学生姓名 " + name + " 不在哈希表中。");return false;}// 打印哈希表private void displayTable() {for (int i = 0; i < TABLE_SIZE; i++) {if (!table[i].isEmpty()) {System.out.println("哈希表[" + i + "]: " + table[i]);}}}public static void main(String[] args) {Kcsj19 hashTable = new Kcsj19();// 待填入哈希表的学生姓名String[] students = {"蔡开俊", "陈恒", "陈慧强", "董彪", "冯迪", "冯伟宇", "谷婉如","韩欣言", "何继翔","李宝才", "李琳琳", "李现珍", "李向阳", "李毅琛", "路亚博","路政睿" ,"孙志坤","王龙杰","王蕊", "王艺涵", "薛获宇", "元亚捷", "岳婧婧", "詹思航", "张浩","张恒", "张佳熙", "张锦彩", "张梦娇", "张轩硕"};// 插入学生姓名到哈希表for (String student : students) {hashTable.insert(student);}// 打印哈希表hashTable.displayTable();// 测试查找学生姓名Scanner scanner = new Scanner(System.in);// 判断学生姓名是否存在于哈希表中while(true) {System.out.print("请输入学生姓名(输入exit退出):");String inputName = scanner.nextLine();if (inputName.equalsIgnoreCase("exit")) {System.out.println("程序已退出。");break;}hashTable.search(inputName);}}
}
实验报告
一:问题分析

描述问题该实验可归结为哈希表的建表和查表功能的实现。用除留余数法构建哈希表,把学生姓名以汉语拼音的形式储存在哈希表中,当发生冲突时,会使用线性探测再散列法在哈希表中的下一个位置继续搜索直到找到空槽。解决该问题的方法和思路:使用除留余数法构造哈希表,然后向表中添加学生姓名,如果在插入和查找的过程中发生冲突用线性探测散列法解决冲突。
二、数据结构
1.逻辑结构
哈希表的应用实习项目的逻辑结构是一个大小为TABLE_SIZE的数组,每个数组元素都可以存储一个学生姓名。哈希函数将学生姓名转化成一个数组索引,然后在该索引位置上插入或查找学生姓名。当插入学生姓名时,如果对应的数组索引位置已经被占用,则使用线性探测再散列法来寻找下一个可用的位置。当查找学生姓名时,根据哈希函数得到学生姓名对应的数组索引,然后根据线性探测再散列法依次检查该索引位置及其后续位置,直到找到匹配的学生姓名或者遇到空位置为止。
2.物理结构
物理结构采用的是顺序存储结构。
三、算法
(一)主要算法描述
1.用除留余数法构造哈希函数
(1)哈希函数的输入是一个字符串key,它使用了一个for循环遍历 字符串key的每个字符,并结合当前的哈希值hashValue进行计算。具体的计算公式是:hashValue=(hashValue * 31+ch)%TABLE_SIZE。
(2)其中,ch表示当前字符的ASCII值。乘以31是为了增加哈希函数的散列性能,使得不同的字符组合能够得到不同的哈希值。最后取余数TABLE_SIZE 是将哈希值限定在哈希表的大小范围内,以确保插入和查询的正确性。
(3)然后,根据这个哈希值,确定存储学生姓名的位置(索引)在哈希表中的哪个位置。最终,将学生姓名保存在哈希表的相应位置上。
2.线性探测再散列法
(1)代码中使用了线性探测再散列法来处理哈希冲突。在插入元素和查找元素的方法中,通过不断尝试下一个位置来解决冲突。如果当前位置已经被占用,就尝试下一个位置,直到找到一个空闲的位置或者遍历完整个哈希表。
(2)linearProbe方法接受两个参数:index表示原始的哈希值对应的索引,attempt表示当前的探测次数。通过将原始索引index和探测次数attempt相加,并对TABLE_SIZE取模,得到一个新的索引值。这个新的索引值即为通过线性探测法计算得到的下一个位置。
(3)在插入元素的方法中,先把通过学生姓名计算出的哈希值赋值给index,此时设置探测次数attempt为0,如果哈希表在index位置不为空那么attempt加一,再用linearProbe方法来计算下一个位置,即(index+attempt) % TABLE_SIZE。如果哈希表在index位置为空的话,就把学生姓名添加到哈希表中。
(4)在查找元素的方法中,首先通过调用hashFunction 哈希函数来计算给定学生姓名的哈希值,并将其赋值给index变量。然后,设置初始的探测次数attempt 为0。接下来,使用一个循环来判断哈希表在index位置是否为空。如果不为空,则进入循环体。在循环体中,首先判断哈希表在index位置的值与目标姓名是否相等。如果相等,说明找到了目标姓名,将相关信息打印出来,并返回true表示找到了目标。如果不相等,则增加attempt的值,并使用linearProbe方法计算下一个探测位置。linearProbe方法使用线性探测再散列法的思想,通过(index + attempt)%TABLE_SIZE的计算来获取下一个探测位置。当哈希表在index位置为空时,说明未找到目标姓名,将相关信息打印出来,并返回false表示未找到目标。
(一)主要算法实现代码
1.用除留余数法构建哈希表
private int hashFunction(String key) {int hashValue = 0;for (char ch : key.toCharArray()) {hashValue = (hashValue * 31 + ch) % TABLE_SIZE;}return hashValue;}
2.线性探测再散列法解决冲突
private int linearProbe(int index, int attempt) {return (index + attempt) % TABLE_SIZE;
}
3.向哈希表中插入元素
private void insert(String name) {int index = hashFunction(name);int attempt = 0;while (!table[index].isEmpty()) {attempt++;index = linearProbe(index, attempt);}table[index] = name;
}
4.在哈希表中查找元素
private boolean search(String name) {int index = hashFunction(name);int attempt = 0;while (!table[index].isEmpty()) {if (table[index].equals(name)) {System.out.println("学生姓名 " + name + " 在哈希表中。");return true;}attempt++;index = linearProbe(index, attempt);}System.out.println("学生姓名 " + name + " 不在哈希表中。");return false;}
四、上机调试
问题1: 输入exit并不会退出程序,而是输出“学生姓名exit不在哈希表中”。

图2 无法退出程序
解决办法:出现这种情况的原因是使用“==”来判断两个字符串是否相等,要比较两个字符串的内容是否相等,可以使用equals方法,或者equalsIgnoreCase方法(可以忽略大小写)。

图3 使用equalsIgnoreCase方法比较字符串是否相同
问题2:哈希表的存储与哈希值有关, 如何获取字符串的哈希值, 进行存储。
解决办法:对于输入的字符串key,遍历其中的每个字符ch,将hashValue乘以31后加上ch的ASCII码值,并取模TABLE_SIZE,得到新的哈希值。
问题3: 出现空指针异常。

图4出现空指针异常
解决办法:出现异常的原因是没有对数组进行初始化。使用Arrays.fill()方法将数组中所有元素赋值为空字符串,避免在插入或查找元素时出现值null, 因为如果数组元素为null,那么在调用字符串方法时,就会抛出空指针异常。

图5对数组进行初始化
相关文章:
数据结构程序设计——哈希表的应用(2)->哈希表解决冲突的方法
目录 实验须知 代码实现 实验报告 一:问题分析 二、数据结构 1.逻辑结构 2.物理结构 三、算法 (一)主要算法描述 1.用除留余数法构造哈希函数 2.线性探测再散列法 (一)主要算法实现代码 四、上机调试 实…...
微信小程序开发系列-07组件
微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》《微信小程序开发系列-02注册小程序》《微信小程序开发系列-03全局配置中的“window”和“tabBar”》《微信小程序开发系列-04获取用户图像和昵称》《微信小程序开发系列-05登录小程序》《微信小程序…...
JavaScript 中 Set 和 Map 的区别
JavaScript 中的 Set 和 Map 都是用来存储数据的数据结构,它们之间的区别如下: Set 是一组唯一值的集合,而 Map 是一组键值对的集合。Set 中的值是唯一的,不允许重复;Map 中的键是唯一的,值可以重复。Set …...
web前端之JavaScript
MENU JavaScript之设计模式、单例、代理、装饰者、中介者、观察者、发布订阅、策略JavaScript之数组静态方法的实现、reduce、forEach、map、push、every JavaScript之设计模式、单例、代理、装饰者、中介者、观察者、发布订阅、策略 单例模式 概念 保证一个类仅有一个实例&am…...
C# 图标标注小工具-查看重复文件
目录 效果 项目 代码 下载 效果 项目 代码 using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Windows.Forms;namespace ImageDuplicate {public partial clas…...
浅谈冯诺依曼体系和操作系统
🌎冯诺依曼体系结构 文章目录 冯诺依曼体系结构 认识冯诺依曼体系结构 硬件分类 各个硬件的简单认识 输入输出设备 中央处理器 存储器 关于内存 对冯诺依曼体系的理解 操作系统 操作系统…...
Good Bye 2023
Good Bye 2023 Good Bye 2023 A. 2023 题意:序列a中所有数的乘积应为2023,现在给出序列中的n个数,找到剩下的k个数并输出,报告不可能。 思路:把所有已知的数字乘起来,判断是否整除2023,不够…...
多开工具对手机应用响应速度的优化与改进
多开工具对手机应用响应速度的优化与改进 摘要: 如今,手机应用的多样化和个性化需求不断增长,用户对应用的响应速度要求也越来越高。为了满足用户的需求,开发者们使用了多种技术手段进行应用的优化和改进。其中,多开工…...
文件批量整理,文件归类整理,文件批量归类
我们每天都要面对无数的文件,从工作报告、个人照片到电影和音乐。如何有效地管理和归类这些文件,成为了我们日常生活和工作中所要处理的。今天,小编就给大家介绍一款简单易用的工具——文件批量改名高手,助你轻松实现文件批量归类…...
Python+Django+Mysql+SimpleUI搭建后端用户管理系统(非常详细,每一步都清晰,列举了里面所有使用的方法属性)
一、在Anaconda环境下创建虚拟环境 (1)打开Anaconda Prompt(install),创建虚拟环境,如下图所示: 方法一:默认情况下虚拟环境创建在Anaconda安装目录下的envs文件夹中 conda create --name usermanage …...
【Qt-QWidget-QLabel-QFrame-QSlider-View-Bar】
Qt编程指南 ■ Label■ QLabel■ QMovie 显示动画■ Widget■ QWidget■ QTabWidget■ QTableWidget■ QListWidget■ QStackedWidget■ QCalendarWidget■ QFrame■ QFrame■ View■ QT...
11|代理(上):ReAct框架,推理与行动的协同
11|代理(上):ReAct框架,推理与行动的协同 在之前介绍的思维链(CoT)中,我向你展示了 LLMs 执行推理轨迹的能力。在给出答案之前,大模型通过中间推理步骤(尤其…...
毫秒格式化
## 计算当前毫秒数: const [start,setStart] useState(new Date().getTime())useEffect(()>{setInterval(()>{setCurrMill(new Date().getTime()-start)},1)},[]) ## 格式化毫秒 function formatMilliseconds(milliseconds) {const totalSeconds Math.flo…...
pytorch与cuda版本对应关系汇总
pytorch与cuda版本关系 cuda版本支持pytorch版本cuda10.21.5 ~ 1.12cuda11.01.7 ~ 1.7.1cuda11.11.8 ~ 1.10.1cuda11.31.8.1 ~ 1.12.1cuda11.61.12.0 ~ 1.13.1cuda11.71.13.0 ~ 2.0.1cuda11.82.0.0 ~ 2.1.1cuda12.12.1.0 ~ 2.1.1 cuda 与 cudnn关系 cuda版本支持cudnn版本cu…...
Linux系统下隧道代理HTTP
在Linux系统下配置隧道代理HTTP是一个涉及网络技术的话题,主要目的是在客户端和服务器之间建立一个安全的通信通道。下面将详细解释如何进行配置。 一、了解基本概念 在开始之前,需要了解几个关键概念:代理服务器、隧道代理和HTTP协议。代理…...
unity学习笔记----游戏练习03
一、修复植物种植的问题 1.当手上存在植物时,再次点击卡片上的植物就会在手上添加新的植物,需要修改成只有手上没有植物时才能再次获取到植物。需要修改AddPlant方法。 public bool AddPlant(PlantType plantType) { //防止手上出现多个植…...
VistualStudio查看类图UML
点击菜单栏中的工具–》获取工具和功能。 然后在资源管理器中对应的代码中鼠标右键选择查看类图 生成一个ClassDiagram.cd文件就是类图的文件了。 根据需要拖拽就可以生成类图了。...
elasticsearch系列九:异地容灾-CCR跨集群复制
概述 起初只在部分业务中采用es存储数据,在主中心搭建了个集群,随着es在我们系统中的地位越来越重要,数据也越来越多,针对它的安全性问题也越发重要,那如何对es做异地容灾呢? 今天咱们就一起看下官方提供的…...
基于Java网上点餐系统设计与实现
博主介绍: ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到 Java项目精品实…...
公司电脑文件加密系统——防止内部核心文件数据 | 资料外泄,自动智能透明加密保护
一套从源头上保障企业电脑数据安全和电脑使用安全的加密软件。天锐绿盾加密软件包含了表格数据加密、图纸加密、文档文件加密、内网文件加密流转、密级管控、电脑离线管理、文件外发管理、灵活的审批流程、工作模式切换、服务器白名单等功能。天锐绿盾加密系统全面覆盖Mac、Win…...
eureka管理平台(开源项目)-eurekaadmin
Table of Contents generated with DocToc 项目背景简单使用交互流程 技术关键点 具体使用 访问地址部署 后端部署前端部署 参考 项目背景 eureka是一个springcloud较为通用流行的服务注册发现中心eureka目前仅仅配套了查询页面,没有配套摘除节点流量和放节点流量…...
告别迷茫!手把手教你用Keil uVision5为LPC1759创建第一个完整工程(附UART驱动避坑指南)
从零构建LPC1759工程:Keil uVision5实战指南与UART深度解析 当你第一次拿到LPC1759开发板时,面对Keil uVision5的复杂界面和芯片手册中密密麻麻的寄存器描述,是否感到无从下手?作为ARM Cortex-M3家族中的经典型号,LPC1…...
3分钟快速掌握:ncmdump终极NCM文件转换指南
3分钟快速掌握:ncmdump终极NCM文件转换指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的加密NCM文件无法在其他设备播放而烦恼吗?ncmdump就是你的终极解决方案!这款简单…...
如何高效管理个人数字记忆:WeChatMsg聊天记录分析与归档实用指南
如何高效管理个人数字记忆:WeChatMsg聊天记录分析与归档实用指南 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trendin…...
BitNet b1.58-2B-4T-gguf实际案例:为IoT设备生成固件更新日志与故障诊断报告
BitNet b1.58-2B-4T-gguf实际案例:为IoT设备生成固件更新日志与故障诊断报告 1. 项目背景与模型特性 在IoT设备运维领域,固件更新日志和故障诊断报告的生成一直是个耗时费力的工作。传统方法需要工程师手动编写,不仅效率低下,还…...
Windows屏幕采集进阶:手把手教你用DXGI对接NVIDIA NVENC实现硬件编码
Windows屏幕采集与硬件编码实战:DXGI对接NVENC全流程解析 在实时视频流处理领域,屏幕采集与硬件编码的高效结合一直是开发者面临的挑战。传统方案往往需要在GPU和CPU之间频繁拷贝数据,导致延迟增加和性能下降。本文将深入探讨如何利用DXGI直接…...
【超全步骤】2026年Hermes Agent/OpenClaw阿里云7分钟简易集成指南
【超全步骤】2026年Hermes Agent/OpenClaw阿里云7分钟简易集成指南。OpenClaw(前身为Clawdbot/Moltbot)作为开源、本地优先的AI助理框架,凭借724小时在线响应、多任务自动化执行、跨平台协同等核心能力,成为个人办公与轻量团队协作…...
从《网络空间独立宣言》到Web3:John Barlow的愿景在区块链时代实现了吗?
数字边疆的进化:从早期互联网理想主义到Web3的技术实践 1996年,当John Barlow写下《网络空间独立宣言》时,他或许想象不到二十多年后,区块链技术会以另一种方式重新诠释他的理念。这位电子前沿基金会的联合创始人曾宣称࿱…...
告别臃肿模拟器:如何在Windows上原生运行安卓应用的三大突破方案
告别臃肿模拟器:如何在Windows上原生运行安卓应用的三大突破方案 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否厌倦了每次运行手机应用都需要启动沉…...
Qt:真正的门槛不是入门,而是维护
很多人第一次写 Qt 项目,感觉还挺顺:拖几个控件,连几个信号槽,按钮一按,界面动了,数据也刷出来了。那一刻很容易产生一种错觉:Qt 也没那么难嘛。 真正让人难受的,往往不是第一个版本…...
