数据结构第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.rhkb.cn/news/374358.html

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

相关文章

“删错文件后如何高效挽救?两大恢复策略全解析“

在数字化日益深入生活的今天&#xff0c;数据已成为我们工作、学习和娱乐不可或缺的一部分。然而&#xff0c;删错文件的经历却如同数字世界中的一场“小插曲”&#xff0c;不经意间就可能让我们陷入数据丢失的困境。无论是误触删除键、清空回收站&#xff0c;还是软件故障导致…

springboot中通过jwt令牌校验以及前端token请求头进行登录拦截实战

前言 大家从b站大学学习的项目侧重点好像都在基础功能的实现上&#xff0c;反而一个项目最根本的登录拦截请求接口都不会写&#xff0c;怎么拦截&#xff1f;为什么拦截&#xff1f;只知道用户登录时我后端会返回一个token&#xff0c;这个token是怎么生成的&#xff0c;我把它…

Matlab中collectPlaneWave函数的应用

查看文档如下&#xff1a; 可以看出最多5个参数&#xff0c;分别是阵列对象&#xff0c;信号幅度&#xff0c;入射角度&#xff0c;信号频率&#xff0c;光速。 在下面的代码中&#xff0c;我们先创建一个3阵元的阵列&#xff0c;位置为&#xff1a;&#xff08;-1,0,0&#x…

项目管理工具评测:2024年国内外最顶级的10款项目管理工具排行

国内外涌现出众多优秀的项目管理工具&#xff0c;它们各自在功能、易用性、集成能力等方面展现出独特优势。以下是国内外顶级的10款项目管理工具&#xff1a; 一、进度猫 推荐理由&#xff1a;进度猫以其直观的任务管理和进度跟踪功能&#xff0c;成为许多团队和项目的首选…

javaweb学习day4--《maven篇》maven的项目创建及其依赖管理详解(基于最新版本的idea)

一、前言 javaweb学习的第四天&#xff0c;不知道今天你们是否坚持下去了。今天学习到的是maven&#xff0c;温馨提示一下&#xff0c;idea中自带maven不用自行去下载了。前期的配置工作太过复杂了&#xff0c;小编感觉自己能力有限并不能将其讲的太清楚&#xff0c;还请大家在…

PlugLink的技术架构实例解析(附源码)

在探讨PlugLink这一开源应用的实际应用与技术细节时&#xff0c;我们可以从其构建的几个核心方面入手&#xff0c;结合当前AI编程的发展趋势&#xff0c;为您提供既有实例又有深度解析的内容。 PlugLink的技术架构实例解析 前端技术选型 —— layui框架&#xff1a; PlugLi…

maven——(重要)手动创建,构建项目

创建项目 手动按照maven层级建好文件夹&#xff0c;并写上java&#xff0c;测试代码和pom文件 构建项目 在dos窗口中执行如下命令 compile编译 当前maven仓库中什么都没有。 在pom所在层级下&#xff0c;执行&#xff1a; mvn compile 就开始显示下面这些&#xff0c;…

MQTT是什么,物联网

写文思路&#xff1a; 以下从几个方面介绍MQTT&#xff0c;包括&#xff1a;MQTT是什么&#xff0c;MQTT和webSocket的结合&#xff0c;以及使用场景&#xff0c; 一、MQTT是什么 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的发布/订阅消息…

JavaScript(7)——数组

JavaScript中数组的用法与Java差不多&#xff0c;但还是有一些区别 声明数组 语法: let 数组名 [数据1,数据2,数据...] let arr new Array(数据1,数据2,...数据n) 添加数据 数组.push()方法将一个或多个元素添加到数组末尾&#xff0c;并返回该数组新长度 <script>…

[k8s源码]1.client-go集群外部署

client-go是由k8s发布且维护的专门用于开发者和kubernetes交互的客户端库。它支持对k8s资源的CRUD操作&#xff08;create、read、update、delete&#xff09;&#xff0c;事件监听和处理&#xff0c;访问kubernetes集群的上下文和配置。 client go是独立于kubernetes集群之外…

SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建 前言&#xff1a; 1、主要功能 zuul主要提供动态路由&#xff08;内置ribbon实现&#xff09;和过滤&#xff08;可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器&#xff08;可以配合Sentinel实现&#xff09;&#xff09;功能…

css简单易懂的加载动画,看不会算我输好吧

效果展示 步骤 第一阶段 先准备结构&#xff0c;并且放置12个div&#xff0c;每一个div旋转30*n度&#xff0c; 做一个圆圈 dom <div class"modal"><div class"loading"><div class"item1"></div><div class&quo…

Vue 项目中 history 路由模式的使用

在最近帮客户开发的一个项目中&#xff0c;由于项目的特殊性&#xff0c;需要用到 Vue 中的 history路由模式。该模式使用时会涉及到“上传白屏”和“刷新 404 问题”。在帮助客户解决这两个问题的过程中&#xff0c;总结问题的解决方案并记录下来&#xff0c;希望能够保留这篇…

分布式训练

一、分布式计算 跟多GPU不同是&#xff1a;数据不是从主存拿的&#xff0c;是在分布式文件系统拿的&#xff0c;有多个工作站&#xff0c;工作站中有多个GPU&#xff0c;通过网络读取数据到GPU中&#xff0c;GPU通过网络接收到来自参数服务器的参数进行运算计算梯度&#xff0c…

怎样免费在线文字转语音?5个配音工具一键包揽

日常在享受有声读物的乐趣时&#xff0c;不知道大家是否也曾渴望将手中的精彩文本以生动的声音演绎出来&#xff1f; 无论是为了自我沉浸&#xff0c;还是为家人朋友创造独特的听觉盛宴&#xff0c;一款支持文本转语音的配音软件都能成为你的得力助手。它不仅能让文字跃然耳边…

【C++深度探索】全面解析多态性机制(一)

hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1…

演唱会售票系统(Springboot+MySQL+Mybatis+BootStrap)

本演唱会售票系统结合了多个流行的技术栈&#xff0c;提供了全面的功能模块&#xff0c;包括用户和管理员两个角色。前端采用Bootstrap框架设计响应式界面&#xff0c;后端采用Spring Boot和MyBatis Plus实现业务逻辑和数据库操作&#xff0c;Sa-Token确保系统的安全性。通过这…

深入分析与解决4.3问题:iOS应用版本更新审核被拒原因解析

深入分析与解决4.3问题&#xff1a;iOS应用版本更新审核被拒原因解析 在iOS应用开发和发布过程中&#xff0c;遇到4.3问题&#xff08;设计 - 垃圾邮件&#xff09;是一个常见且令人头疼的情况。即使您的应用已成功发布其第一个版本&#xff0c;但在进行版本更新时&#xff0c…

【机器学习】初学者经典案例(随记)

&#x1f388;边走、边悟&#x1f388;迟早会好 一、概念 机器学习是一种利用数据来改进模型性能的计算方法&#xff0c;属于人工智能的一个分支。它旨在让计算机系统通过经验自动改进&#xff0c;而不需要明确编程。 类型 监督学习&#xff1a;使用带标签的数据进行训练&…

队列+二叉树广度优先

题目出自力扣-n叉树的层序遍历 我是原始人&#xff0c;递归写出一道题就只有递归思路&#xff0c;开始的想法是写深搜函数&#xff0c;传一个随着层数递增的int参数q&#xff0c;节点空就return&#xff0c;否则遍历所有节点&#xff0c;每个子节点又以q1为层数递归&#xff…