Python----数据结构(哈希表:哈希表组成,哈希冲突)

一、哈希表

哈希表(Hash table)是一种常用、重要、高效的数据结构。

哈希表通过哈希函数,可以快速地将键(Key)映射到值(Value)。从而允许在近常数时间内对键关联的值进行插入、删除和查找操作。

哈希表的主要思想是通过哈希函数将键转换为索引,将索引映射到数组中的存储位置

通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表,在首字母为L的表中查找“雷”姓的电话号码,显然比直接查找就要快得多。

二、代码展示 

2.1、键值对

class Pair:  """键值对的类,包含一个键和一个值"""  def __init__(self, key: int, val: str):  """初始化键值对"""  self.key = key  # 键,整数类型  self.val = val  # 值,字符串类型  def __repr__(self):  """返回键值对的字符串表示"""  return f"{self.key} -> {self.val}"  

2.2、初始化

    def __init__(self):  """构造方法,初始化哈希表"""  # 创建一个包含 100 个桶的数组  self.buckets: list[Pair | None] = [None] * 100  

2.3、哈希函数

    def hash_func(self, key: int) -> int:  """哈希函数,将键映射到索引"""  index = hash(key) % 100  # 使用内置哈希函数计算键的哈希值,并对桶的数量取模  return index  

2.4、添加键值对

    def put(self, key: int, val: str):  """添加键值对到哈希表"""  pair = Pair(key, val)  # 创建新的键值对  index: int = self.hash_func(key)  # 计算键的哈希索引  self.buckets[index] = pair  # 将键值对放入相应的桶中  

2.5、查询值

    def get(self, key: int) -> str:  """根据给定的键查询值"""  index: int = self.hash_func(key)  # 计算键的哈希索引  pair: Pair = self.buckets[index]  # 获取对应的键值对  if pair is None:  return None  # 如果未找到,返回 None  return pair.val  # 返回找到的值  

2.6、删除键值对

    def remove(self, key: int):  """根据给定的键删除键值对"""  index: int = self.hash_func(key)  # 计算键的哈希索引  self.buckets[index] = None  # 将桶置为 None,表示删除  

2.7、返回所有键值对

    def entry_set(self) -> list[Pair]:  """返回哈希表中所有的键值对"""  result: list[Pair] = []  for pair in self.buckets:  if pair is not None:  result.append(pair)  # 将非空桶的键值对添加到结果列表中  return result  

2.8、返回键

    def key_set(self) -> list[int]:  """返回哈希表中所有的键"""  result = []  for pair in self.buckets:  if pair is not None:  result.append(pair.key)  # 将非空桶的键添加到结果列表中  return result  

2.9、返回值

    def value_set(self) -> list[str]:  """返回哈希表中所有的值"""  result = []  for pair in self.buckets:  if pair is not None:  result.append(pair.val)  # 将非空桶的值添加到结果列表中  return result  

2.10、输出

    def print(self):  """打印哈希表中的所有键值对"""  for pair in self.buckets:  if pair is not None:  print(pair.key, "->", pair.val)  # 打印每个键值对  

2.11、完整代码

class Pair:  """键值对的类,包含一个键和一个值"""  def __init__(self, key: int, val: str):  """初始化键值对"""  self.key = key  # 键,整数类型  self.val = val  # 值,字符串类型  def __repr__(self):  """返回键值对的字符串表示"""  return f"{self.key} -> {self.val}"  class ArrayHashMap:  """基于数组实现的哈希表"""  def __init__(self):  """构造方法,初始化哈希表"""  # 创建一个包含 100 个桶的数组  self.buckets: list[Pair | None] = [None] * 100  def hash_func(self, key: int) -> int:  """哈希函数,将键映射到索引"""  index = hash(key) % 100  # 使用内置哈希函数计算键的哈希值,并对桶的数量取模  return index  def put(self, key: int, val: str):  """添加键值对到哈希表"""  pair = Pair(key, val)  # 创建新的键值对  index: int = self.hash_func(key)  # 计算键的哈希索引  self.buckets[index] = pair  # 将键值对放入相应的桶中  def get(self, key: int) -> str:  """根据给定的键查询值"""  index: int = self.hash_func(key)  # 计算键的哈希索引  pair: Pair = self.buckets[index]  # 获取对应的键值对  if pair is None:  return None  # 如果未找到,返回 None  return pair.val  # 返回找到的值  def remove(self, key: int):  """根据给定的键删除键值对"""  index: int = self.hash_func(key)  # 计算键的哈希索引  self.buckets[index] = None  # 将桶置为 None,表示删除  def entry_set(self) -> list[Pair]:  """返回哈希表中所有的键值对"""  result: list[Pair] = []  for pair in self.buckets:  if pair is not None:  result.append(pair)  # 将非空桶的键值对添加到结果列表中  return result  def key_set(self) -> list[int]:  """返回哈希表中所有的键"""  result = []  for pair in self.buckets:  if pair is not None:  result.append(pair.key)  # 将非空桶的键添加到结果列表中  return result  def value_set(self) -> list[str]:  """返回哈希表中所有的值"""  result = []  for pair in self.buckets:  if pair is not None:  result.append(pair.val)  # 将非空桶的值添加到结果列表中  return result  def print(self):  """打印哈希表中的所有键值对"""  for pair in self.buckets:  if pair is not None:  print(pair.key, "->", pair.val)  # 打印每个键值对  if __name__ == '__main__':  map = ArrayHashMap()  # 创建一个新的哈希表实例  map.put('m', '蟒')  # 添加键值对  map.put('s', '蛇')  map.put('c', '程')  map.put('x', '序')  map.put('y', '员')  # 查询并打印值  print(map.get('m'))  # 输出:蟒  print(map.get('s'))  # 输出:蛇  print(map.get('c'))  # 输出:程  print(map.get('x'))  # 输出:序  print(map.get('y'))  # 输出:员  # 打印哈希表的内容  map.print()  print(map.entry_set())  # 输出所有的键值对

三、 哈希冲突

        若key(关键字)为n,则其值存放在 f(n) = n % size 的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f函数为哈希(散列)函数,按这个思想建立的表为哈希(散列)表

        但对不同的关键字可能得到同一散列地址,即n1 ≠ n2,而f(n1)==f(n2),这种现象称为冲突

3.1、散列函数

        哈希表中元素的位置是由哈希函数确定的。将数据n作为自变量,通过一定的函数关系计算出的值,即为该元素的存储地址。

3.1.1、直接定址法

直接使用key的某些部分作为存储地址,适用于关键字的取值范围不大的情况

假设我们有一组学生ID,并决定使用学生ID本身作为哈希地址

公式:哈希地址 = 学生ID

3.1.2、数字分析法

针对key的数位进行分析,选择具有代表性的数位作为哈希地址。

适用于关键字具有一定规律的情况假设我们有一组社交安全号码,我们选择使用最后两位数字作为哈希地址

对于123-45-6789,我们取最后两位89作为哈希地址

3.1.3、平方取中法

将关键字的平方值的中间一部分作为哈希地址。

适用于关键字分布较均匀的情况假设我们有一组三位数,我们将每个数字平方,然后取中间的数字作为哈希地址

对于数字456,平方得到207936。取中间两位数字

哈希地址为79公式:哈希地址 = 取中位数字(平方(关键字))

3.1.4、折叠法

将关键字分割成固定长度的片段,然后将这些片段相加,再取余数作为哈希地址。

适用于关键字长度较长的情况。考虑一组电话号码(例如,123-456-7890)。

我们可以将数字分成两位一组,求和,然后取模得到哈希地址对于电话号码123-456-7890,哈希地址将是(12 + 34 + 56 + 78 + 90) % 表大小

公式:哈希地址 = 组的数字之和(关键字) % 表大小

3.1.5、随机数法

用一个随机数生成器产生哈希地址。适用于关键字分布随机的情况

3.1.6、除留余数数法(常用)

将关键字除以某个不大于哈希表大小的数,取余数作为哈希地址

公式:哈希地址 = 关键字 % 表大小

3.2、 哈希冲突处理的办法

1、单独链表法(常用)

每个桶(数组元素)存储一个链表或其他数据结构(如列表)。所有哈希到同一索引的元素都放在这个链表中。

2、开放定址法

当发生哈希冲突时,试探性地寻找下一个空桶以存储新的键值对。可以使用线性探测、二次探测或者双重散列来确定下一个桶的位置。

3、双散列

是开放定址法的一种变体,使用两个不同的哈希函数。当发生冲突时,第二个哈希函数决定下一步的探测位置,从而实现更均匀的分布。

4、再散列

当哈希表达到一定的负载因子时,扩展表的大小并重新计算所有元素的位置,分散冲突。一般会将哈希表的容量加倍,并使用新的哈希函数或改变现有的哈希函数。

5、建立一个公共溢出区

设计一个额外的数组(溢出区)用于存储溢出(冲突)的元素。每当一个桶中溢出时,它就会将该元素放入溢出区。

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

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

相关文章

使用excel中的VBA合并多个excel文件

需求是这样的: 在Windows下,用excel文件让多个小组填写了统计信息,现在我需要把收集的多个文件汇总到一个文件中,前三行为标题可以忽略,第四行为收集信息的列名,处理每一行数据的时候,发现某一行…

功能全面的手机壁纸应用,种类齐全、众多高清壁纸

软件介绍 应用亮点:今天给大家分享一款超神奇的手机应用 —— 奇幻壁纸。它作为手机动态壁纸软件,功能超全面,操作还便捷,极具创意,能瞬间将你的手机屏幕变成奇幻世界,带来全新视觉感受。 使用便捷性&…

docker安装kafka,并通过springboot快速集成kafka

目录 一、docker安装和配置Kafka 1.拉取 Zookeeper 的 Docker 镜像 2.运行 Zookeeper 容器 3.拉取 Kafka 的 Docker 镜像 4.运行 Kafka 容器 5.下载 Kafdrop 6.运行 Kafdrop 7.如果docker pull wurstmeister/zookeeper或docker pull wurstmeister/kafka下载很慢&#x…

前端导出word文件,并包含导出Echarts图表等

基础导出模板 const html <html><head><style>body {font-family: Times New Roman;}h1 {text-align: center;}table {border-collapse: collapse;width: 100%;color: #1118FF;font-weight: 600;}th,td {border: 1px solid black;padding: 8px;text-align: …

2024系统编程语言风云变幻:Rust持续领跑,Zig与Ada异军突起

2024年系统编程语言调查报告新鲜出炉&#xff01;这份报告对Rust、Zig、Ada、C、C等主流语言进行了全面评估&#xff0c;结果令人瞩目。Rust凭借其强大的类型系统和内存安全机制继续领跑&#xff0c;而Zig和Ada则展现出巨大的潜力&#xff0c;为系统编程领域带来了新的活力。本…

Jenkins 构建 Unity 打包 .apk 同时生成 .aab

Jenkins 构建 Unity 打包 .apk 同时生成 .aab Android App Bundle简称 AAB&#xff0c;想了解更多关于 AAB 的知识&#xff0c;请看官网 https://developer.android.google.cn/guide/app-bundle/faq?hlzh-cn APK 打包部分在复用上一篇 Jenkins 构建 Unity打包APK 一、新建一…

JAVAweb-标签选择器,盒模型,定位,浮动

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>标签</title><style type"text/css&q…

计算机视觉:主流数据集整理

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络(附代码) 第五章&#xff1…

二级公共基础之数据结构与算法篇(五)树和二叉树

目录 前言 一、树的基本概念 1.父结点和根节点 2.子节点和叶子节点 3.度和深度 4.子树 二、二叉树及其基本性质 1. 二叉树的定义 2. 二叉树的基本性质 性质1 性质2 性质3 性质4 性质5 性质6 三、二叉树的存储结构 四、二叉树的遍历 1.遍历二叉树的概念 1. 前…

自制操作系统学习第七天

今天要做什么&#xff1f; 实现HLT&#xff0c;不让计算机处于HALT&#xff08;HLT&#xff09;.用C语言实现内存写入&#xff08;错误&#xff0c;需要分析&#xff09; 一:使用HLT&#xff0c;让计算机处于睡眠状态 写了下面这个程序&#xff0c;naskfunc.nas 函数名叫io_h…

Python Django系列—入门实例(二)

数据库配置 现在&#xff0c;打开 mysite/settings.py 。这是个包含了 Django 项目设置的 Python 模块。 默认情况下&#xff0c;​ DATABASES 配置使用 SQLite。如果你是数据库新手&#xff0c;或者只是想尝试 Django&#xff0c;这是最简单的选择。SQLite 包含在 Python 中…

DeepSeek接入Siri(已升级支持苹果手表)完整版硅基流动DeepSeek-R1部署

DeepSeek接入Siri&#xff08;已升级支持苹果手表&#xff09;完整版硅基流动DeepSeek-R1部署 **DeepSeek** 是一款专注于深度学习和人工智能的工具或平台&#xff0c;通常与人工智能、机器学习、自动化分析等领域有关。它的主要功能可能包括&#xff1a;深度学习模型搜索&…

抗辐照加固CAN FD芯片的商业航天与车规级应用解析

在工业自动化、智能汽车、航空航天及国防装备等关键领域&#xff0c;数据传输的安全性、可靠性与极端环境适应能力是技术升级的核心挑战。国科安芯推出全新一代CANFD&#xff08;Controller Area Network Flexible Data Rate&#xff09;芯片&#xff0c;以高安全、高可靠、断电…

Java数据结构第十二期:走进二叉树的奇妙世界(一)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、树型结构 1.1. 树的定义 1.2. 树的基本概念 1.3. 树的表示形式 二、二叉树 2.1. 概念 2.2. 两种特殊的二叉树 2.3. 二叉树的性质 2.4. 二叉树的存储 三、二叉树的基本操作 一、树型结构 1.…

nginx 反向代理 配置请求路由

nginx | 反向代理 | 配置请求路由 nginx简介 Nginx&#xff08;发音为“Engine-X”&#xff09;是一款高性能、开源的 Web 服务器和反向代理服务器&#xff0c;同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;于 2004…

ath9k(Atheros芯片)开源驱动之wifi连接

为什么会推荐这个wifi 驱动进行学习&#xff1f; ath9k&#xff08;Atheros芯片&#xff09;&#xff1a;代码结构清晰&#xff0c;适合学习实践 为什么我只在开篇写了一个wifi连接的操作&#xff1f; 先让一个开源驱动在你的硬件上跑起来&#xff0c;再逐步修改&#xff0c…

LLaMA-Factory|微调大语言模型初探索(4),64G显存微调13b模型

上篇文章记录了使用lora微调deepseek-7b&#xff0c;微调成功&#xff0c;但是微调llama3-8b显存爆炸&#xff0c;这次尝试使用qlora微调HQQ方式量化&#xff0c;微调更大参数体量的大语言模型&#xff0c;记录下来微调过程&#xff0c;仅供参考。 对过程不感兴趣的兄弟们可以直…

知识管理平台如何实现高效数据整合?

内容概要 现代知识管理平台通过架构化的四库体系&#xff08;资源库、规则库、模型库、知识库&#xff09;驱动数据智能整合进程。核心机制依托智能数据工具集对异构数据进行自动化清洗与语义标注&#xff0c;其跨源数据汇聚能力支持超过200种结构化与非结构化数据源的接入&am…

近10年气象分析(深度学习)

这是一个气象数据分析程序&#xff0c;主要用于分析和可视化气象数据。以下是该文件的主要功能&#xff1a; 1. 数据加载 在线数据&#xff1a;尝试从 GitHub 加载气象数据。 示例数据&#xff1a;如果无法加载在线数据&#xff0c;程序会自动生成示例数据。 2. 数据分析 …

DeepSeek最新开源动态:核心技术公布

2月21日午间&#xff0c;DeepSeek在社交平台X发文称&#xff0c;从下周开始&#xff0c;他们将开源5个代码库&#xff0c;以完全透明的方式与全球开发者社区分享他们的研究进展。并将这一计划定义为“Open Source Week”。 DeepSeek表示&#xff0c;即将开源的代码库是他们在线…