数据结构第18节 散列表 - 应用

散列表(Hash Table),也被称为哈希表,是一种数据结构,它通过使用哈希函数将键映射到数组的某个位置来实现快速查找。散列表通常提供平均时间复杂度为O(1)的查找、插入和删除操作,这使得它们在处理大量数据时非常高效。

基本概念

  • 哈希函数:一个将键转换为数组索引的函数。理想情况下,这个函数应该均匀地分布键,以避免冲突。
  • 冲突:当两个或多个不同的键被哈希函数映射到同一个数组索引时,就发生了冲突。解决冲突的方法包括开放寻址法和链地址法。
  • 负载因子:是散列表中元素的数量与散列表大小的比例。当负载因子过高时,散列表可能需要重新调整大小(扩容)以减少冲突。

Java中的散列表实现

在Java中,散列表可以通过HashMap类实现,它是Java集合框架的一部分。HashMap允许我们存储键值对,并且提供了快速的查找、插入和删除操作。

示例代码

假设我们要创建一个简单的散列表,用于存储学生ID和他们的成绩。以下是一个使用HashMap的示例:

import java.util.HashMap;public class StudentScores {public static void main(String[] args) {HashMap<Integer, Integer> scores = new HashMap<>();// 插入数据scores.put(101, 90);scores.put(102, 85);scores.put(103, 95);// 查找数据System.out.println("Score of student 101: " + scores.get(101));// 更新数据scores.put(101, 92);System.out.println("Updated score of student 101: " + scores.get(101));// 删除数据scores.remove(102);System.out.println("After removing student 102: " + scores);// 检查是否包含键System.out.println("Does the map contain student 101? " + scores.containsKey(101));}
}

在这个例子中,HashMap<Integer, Integer>表示散列表的键类型是整数,值类型也是整数。我们使用put方法插入数据,get方法查找数据,remove方法删除数据,以及containsKey方法检查散列表是否包含特定的键。

散列表的内部工作原理

HashMap的内部使用一个数组来存储键值对,每个位置上可以是一个链表或者红黑树(当链表长度达到一定阈值时)。当向HashMap中添加元素时,它会计算键的哈希码,然后使用该哈希码确定元素在数组中的位置。如果发生冲突,即多个键的哈希码指向同一位置,那么这些键值对会被链接在一起形成一个链表或红黑树。

当从HashMap中查找元素时,同样的哈希计算过程被用来定位元素。如果存在冲突,则遍历链表或红黑树直到找到正确的元素。

总结

散列表通过哈希函数和解决冲突的策略来实现高效的键值存储和检索。在Java中,HashMap是实现这一功能的常用工具。理解其内部工作原理有助于更有效地使用它并优化应用程序的性能。

让我们通过另一个案例来深入理解散列表(哈希表)的应用。这次我们将创建一个简单的图书管理系统,使用散列表来存储和管理图书馆中的书籍信息。

案例:图书管理系统

在这个案例中,我们将使用HashMap来存储图书的ISBN(国际标准书号)作为键,以及每本书的详细信息作为值。图书的详细信息可以用一个自定义的Book类来表示,其中包含书名、作者和出版年份等属性。

创建Book

首先,我们需要创建一个Book类,用于存储图书的详细信息。

public class Book {private String title;private String author;private int publicationYear;public Book(String title, String author, int publicationYear) {this.title = title;this.author = author;this.publicationYear = publicationYear;}@Overridepublic String toString() {return "Book{" +"title='" + title + '\'' +", author='" + author + '\'' +", publicationYear=" + publicationYear +'}';}
}
使用HashMap创建图书管理系统

接下来,我们使用HashMap<String, Book>来创建图书管理系统。我们将ISBN作为键,因为它是图书的唯一标识符。

import java.util.HashMap;public class LibrarySystem {private HashMap<String, Book> books;public LibrarySystem() {this.books = new HashMap<>();}public void addBook(String isbn, String title, String author, int publicationYear) {Book book = new Book(title, author, publicationYear);books.put(isbn, book);}public Book getBook(String isbn) {return books.get(isbn);}public void removeBook(String isbn) {books.remove(isbn);}public boolean containsBook(String isbn) {return books.containsKey(isbn);}
}
测试图书管理系统

现在我们可以创建一个LibrarySystem实例,并测试添加、获取和删除图书的功能。

public class Main {public static void main(String[] args) {LibrarySystem library = new LibrarySystem();// 添加图书library.addBook("978-0-306-40615-7", "The C Programming Language", "Brian W. Kernighan", 1978);library.addBook("978-0-201-63361-0", "Clean Code: A Handbook of Agile Software Craftsmanship", "Robert C. Martin", 2008);// 获取图书信息Book book = library.getBook("978-0-306-40615-7");System.out.println(book); // 输出: Book{title='The C Programming Language', author='Brian W. Kernighan', publicationYear=1978}// 检查图书是否存在System.out.println(library.containsBook("978-0-201-63361-0")); // 输出: true// 删除图书library.removeBook("978-0-201-63361-0");System.out.println(library.containsBook("978-0-201-63361-0")); // 输出: false}
}

在这个案例中,我们利用散列表的快速查找特性来高效地管理图书馆中的图书信息。由于ISBN是唯一的,因此使用它作为散列表的键可以确保没有重复的条目,同时也简化了查找和删除操作。

通过这个案例,你可以看到散列表在实际应用中如何提高数据访问效率,尤其是在处理具有唯一标识符的大数据集时。

好的,让我们继续扩展案例,这次我们将构建一个更复杂的场景——一个任务管理器,它能够帮助用户跟踪个人的任务清单。我们将使用散列表来存储任务,以便于快速查找和管理。

案例:任务管理器

定义Task

首先,我们需要定义一个Task类来存储任务的信息,比如任务的名称、描述、优先级和截止日期。

import java.time.LocalDate;public class Task {private String name;private String description;private int priority;private LocalDate dueDate;public Task(String name, String description, int priority, LocalDate dueDate) {this.name = name;this.description = description;this.priority = priority;this.dueDate = dueDate;}public String getName() {return name;}public String getDescription() {return description;}public int getPriority() {return priority;}public LocalDate getDueDate() {return dueDate;}@Overridepublic String toString() {return "Task{" +"name='" + name + '\'' +", description='" + description + '\'' +", priority=" + priority +", dueDate=" + dueDate +'}';}
}
创建任务管理器

接下来,我们创建一个TaskManager类,使用HashMap来存储任务。我们将使用任务的名称作为键,因为任务的名称应该是唯一的,以避免混淆。

import java.util.HashMap;public class TaskManager {private HashMap<String, Task> tasks;public TaskManager() {this.tasks = new HashMap<>();}public void addTask(Task task) {tasks.put(task.getName(), task);}public Task getTask(String name) {return tasks.get(name);}public void removeTask(String name) {tasks.remove(name);}public boolean containsTask(String name) {return tasks.containsKey(name);}
}
测试任务管理器

现在,我们可以创建一个TaskManager实例,并测试添加、获取和删除任务的功能。

import java.time.LocalDate;public class Main {public static void main(String[] args) {TaskManager manager = new TaskManager();// 添加任务manager.addTask(new Task("Buy groceries", "Milk, bread, eggs", 2, LocalDate.of(2024, 7, 12)));manager.addTask(new Task("Write report", "Finish Q2 sales report", 1, LocalDate.of(2024, 7, 15)));// 获取任务Task task = manager.getTask("Write report");System.out.println(task); // 输出: Task{name='Write report', description='Finish Q2 sales report', priority=1, dueDate=2024-07-15}// 检查任务是否存在System.out.println(manager.containsTask("Buy groceries")); // 输出: true// 删除任务manager.removeTask("Buy groceries");System.out.println(manager.containsTask("Buy groceries")); // 输出: false}
}

扩展功能:按优先级排序

为了使任务管理器更加实用,我们可以添加一个功能来按优先级对任务进行排序。虽然HashMap不保证顺序,但我们可以在TaskManager类中添加一个方法,使用优先级对任务进行排序并返回一个新的List

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;public class TaskManager {// ...public List<Task> getTasksSortedByPriority() {List<Task> sortedTasks = new ArrayList<>(tasks.values());Collections.sort(sortedTasks, Comparator.comparingInt(Task::getPriority));return sortedTasks;}
}

然后,在Main类中,我们可以调用getTasksSortedByPriority方法来获取按优先级排序的任务列表。

// 在Main类中
List<Task> sortedTasks = manager.getTasksSortedByPriority();
sortedTasks.forEach(System.out::println);

通过这些扩展,我们不仅能够有效地存储和管理任务,还能根据优先级对它们进行排序,从而帮助用户更好地组织和规划他们的工作。这个案例展示了散列表如何与其他数据结构如列表结合使用,以满足更复杂的需求。

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

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

相关文章

【mybatis】mybatisX插件概述

一、主要功能 智能补全与提示 MyBatisX 可以智能地提示和补全 SQL 语句中的关键字、表名、列名等信息&#xff0c;从而显著提高开发效率。代码生成器 虽然 MyBatisX 本身可能不直接提供一个完整的、独立的代码生成器&#xff0c;但它可能集成了或支持与其他代码生成工具&#…

卤味江湖中,周黑鸭究竟该抓住什么赛点?

近年来&#xff0c;卤味江湖的决斗从未停止。 随着休闲卤味、佐餐卤味等细分赛道逐渐形成&#xff0c;“卤味三巨头”&#xff08;周黑鸭、绝味食品、煌上煌&#xff09;的牌桌上有了更多新对手&#xff0c;赛道变挤了&#xff0c;“周黑鸭们”也到了转型关键期。 这个夏天&a…

MySQL字符串相关数据处理函数

目录 1. 转大小写 2. 截取字符串 sunstr 3. 获取字符长度 4. 字符串拼接 concat 5. 去掉空白 trim 1. 转大小写 转大写&#xff1a;upper() 转小写&#xff1a;lower() 虽然MySQL不严格区分大小写&#xff0c;但是我们还是需要掌握这种大小写的操作以方便学习其他…

python的入门知识(下)

目录 学习内容数字字符串、列表和元组映射和集合类型 学习内容 数字 长整型&#xff08;Long Integer&#xff09;: 在Python中&#xff0c;整数没有大小限制&#xff0c;但是可以用大写或小写的L来表示长整型&#xff0c;尽管这不是Python 3推荐的做法。 复数&#xff08;Co…

Nessus相关

tenable 1 安装nessus scanner 1 )安装nessus scanner: 方法一 curl -H X-Key: xxxxx https://cloud.tenable.com/install/scanner?namescanner-name&groupsscanner-group | bash方法二&#xff1a; **# for ubuntu, its https://www.tenable.com/downloads/api/v1/pu…

【JavaScript脚本宇宙】JavaScript 库概览:数字、货币值、日期时间处理一网打尽

简化数据处理&#xff1a;掌握六大 JavaScript 库的核心功能和使用技巧 前言 在现代的软件开发中&#xff0c;处理数字、货币和日期时间是非常常见的需求。为了简化这些任务&#xff0c;开发人员可以使用各种 JavaScript 库来轻松地进行数字格式化、货币计算和日期时间操作。…

Google登录时人机身份验证的图片类型和通过的经验建议,以及一些常见问题

很多朋友在登录谷歌账号时&#xff0c;都遇到过要求人机身份验证的步骤&#xff0c;而且有一些时候人机身份验证这个步骤很让人纠结&#xff0c;甚至压根就出不来具体的验证图片&#xff0c;或者花了十几分钟、几十分钟都过不去。 所以今天GG账号服务就来为您解析一下谷歌登录…

初学SpringMVC之接收请求参数及数据回显

pom.xml 文件导入 lombok 的依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version></dependency> Controller 表示这是一个控制器 RequestParam 表示从前端接收…

夏日智启:我的Datawhale AI夏令营探索之旅

前言 最近几年&#xff0c;AI&#xff08;人工智能&#xff09;的发展呈现出了前所未有的迅猛势头&#xff0c;其影响力和应用范围不断扩大&#xff0c;深刻地改变着我们的生活、工作和社会结构。尤其是AI大模型技术&#xff0c;国内外可谓是“百模大战”&#xff0c;百舸争流…

github恢复码怎么备份

https://docs.github.com/zh/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication-recovery-methods

最强文本编辑器 VIM 指令大全

Vim 是从 Vi 编辑器发展出来的一款极其强大的文本编辑器&#xff0c;它保留了 Vi 编辑器的所有功能&#xff0c;并添加了许多新特性。Vim 具有代码补全、语法高亮、错误跳转、批量化处理等编辑功能&#xff0c;还支持异常丰富的插件扩展&#xff0c;且整个编辑全程可通过键盘完…

谷歌插件之一键关闭同域名页面

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 谷歌插件之一键关闭同域名页面 前言项目结构mainfest.jsonbackgroud.js 项目实现效果展示展望 前…

13019.CUDA问题积累

文章目录 1 内存不断增长的问题1.1 主机从GPU拷贝内存1.1.1 htop 内存增长到一定阶段后&#xff0c;保持稳定 1.2 GPU拷贝到Host修改之后内存稳定无变化1.3 结论 2 主机与GPU数据拷贝方案2.1 cudaMemcpy 拷贝内存2.2 cudaMemcpyAsync 异步数据拷贝2.3 采用多线程拷贝技术2.3.1 …

群主必学!轻松Get如何解散微信群的技巧

作为一个微信群的群主&#xff0c;解散群聊可能是你需要掌握的重要技能之一。不管是因为群聊的目的已经达成&#xff0c;还是因为群成员过少或不活跃&#xff0c;了解如何解散微信群都能帮助你更好地管理你的群聊。 如何解散微信群&#xff1f;本文将为您提供一些简单易行的技…

代码随想录算法训练营第五十天| 739. 每日温度、496.下一个更大元素 I、503.下一个更大元素II

739. 每日温度 题目链接&#xff1a; 739. 每日温度 文档讲解&#xff1a;代码随想录 状态&#xff1a;不会 思路&#xff1a; 这道题需要找到下一个更大元素。 使用栈来存储未找到更高温度的下标&#xff0c;那么栈中的下标对应的温度从栈底到栈顶是递减的。这意味着&#xff…

Redis数据同步

文章简单介绍基于redis-shake的redis数据同步&#xff0c;该工具基于每个节点同步数据&#xff0c;即每个主节点需同步一次&#xff0c;才能完成整个redis集群的数据同步。 1、redis节点操作 ### 查看redis版本 ./bin/redis-server --version### 登录redis ./bin/redis-cli -…

改变Ubuntu的Tab没有缩进4格(Makefile)

1.vim里的Tab 用vi指令打开这个文件&#xff0c;没有的话就新创建一个 vi ~/.vimrc在打开的文件中输入以下两行 1 set tabstop42 set shiftwidth4 ~ Esc &#xff1a; x&#xff0c;保存并退出即可 资料来源&#xff1a; 2024年5月21日-vi/vim …

Linux Ubuntu MySQL环境安装

1. 更新软件源 首先&#xff0c;确保你的Ubuntu系统已经更新了软件源列表&#xff0c;以便能够下载到最新的软件包。打开终端并输入以下命令&#xff1a; sudo apt update 2. 安装MySQL服务器 打开终端并输入以下命令来安装MySQL服务器 sudo apt install mysql-server 在…

一个便捷的web截图库~【送源码】

随着时间的发展&#xff0c;前端开发的范围越来越广&#xff0c;能够实现的功能也越来越多&#xff0c;要实现的功能也五花八门&#xff0c;今天就给大家介绍一个web截图库,让前端也能实现截图功能—— js-web-screen-shot js-web-screen-shot js-web-screen-shot 是一个基于 …

嵌入式板级支持包(BSP)80道面试题及参考答案(3万字长文)

目录 解释什么是通用输入输出(GPIO)接口及其在BSP中的作用。 描述SPI接口的主要特点和用途。 说明IC总线协议的工作原理。 如何在BSP中配置一个UART接口? USB设备控制器在BSP中的初始化步骤是什么? 以太网接口如何在BSP中被支持? 什么是SDIO,它在哪些场景下会被使…