【C++】哈希桶

前言

哈希桶是哈希表中用于存储数据的基本单元,也称为哈希槽或存储桶。

  • 哈希桶(Hash Bucket)** 是哈希表数据结构中的一个概念。、
  • 哈希表通过哈希函数将输入数据映射到一个存储位置,而哈希桶就是这些存储位置中的一个单元。
  • 哈希桶用于存放哈希表中的元素,当不同的元素经过哈希函数映射到同一个桶时,通常通过链表或其他结构来存储这些元素。这种情况称为 哈希冲突

哈希桶的工作机制

  1. 哈希函数的作用:哈希函数根据输入元素计算出一个整数值,称为哈希值,然后根据哈希值来决定元素存储在哪个桶中。

    假设哈希表的桶数为 num_buckets,元素 key 的哈希值为 hash(key),则该元素将被存储在 hash(key) % num_buckets 这个桶中。

  2. 哈希冲突:由于哈希表的容量有限,而插入的元素可能很多,因此会有多个元素映射到同一个桶。这就是哈希冲突。

  3. 冲突解决方式:当发生哈希冲突时,哈希桶中的元素通常会存储在某种结构中。常见的冲突解决方式包括:

    • 拉链法:在每个哈希桶中维护一个链表,当多个元素映射到同一个桶时,这些元素会依次插入链表中。
    • 开放寻址法:当某个桶已经有元素时,寻找下一个空的桶来存储冲突的元素。参考

哈希桶示例

例如,一个哈希表有 5 个桶(编号为 0-4),通过简单的哈希函数 hash(key) = key % 5 来决定桶的位置。

//假设插入的元素为:12, 7, 5, 10, 15, 9
hash(12) = 12 % 5 = 2
hash(7) = 7 % 5 = 2
hash(5) = 5 % 5 = 0
hash(10) = 10 % 5 = 0
hash(15) = 15 % 5 = 0
hash(9) = 9 % 5 = 4

最终得到的哈希桶分布如下:

  • 桶 0:5 -> 10 -> 15
  • 桶 1:(空)
  • 桶 2:12 -> 7
  • 桶 3:(空)
  • 桶 4:9

其中:

  • 桶 0 通过拉链法存储了 5、10 和 15,使用链表处理冲突。
  • 桶 2 同样存储了 12 和 7。

哈希桶的实现

存储结构

  • 类似于链表,在顺序表中存储一个一个节点。’
template<class T>
struct defaultHashfunc
{size_t operator()(const T& data){return (size_t)data;}
};
  • table:使用 std::vector 存储多个链表,每个链表代表一个桶,链表中的元素是映射到这个桶的所有元素。
  • 记录_n进行负载因子的储存
template<class K,class T,class KeyofT,class HashFunc = defaultHashfunc<K>>
class HashTable
{public:...private:vector<Node*> _table;size_t _n = 0;
};

哈希函数

  1. 在函数的内容的不确定的时候进行返回。
  2. 针对string字符串的直接进行特模板化。
  3. 针对26字母有不同的组合,要进行字符串的哈希化处理,目的是针对哈希冲突 (本次采用 BKDR算法)参考:字符串哈希算法
template<class T>
struct defaultHashfunc
{size_t operator()(const T& data){return (size_t)data;}
};
//string特化
template<>
struct defaultHashfunc<string>
{size_t operator()(const string& str){size_t hash = 0;for (auto& ch : str){hash *= 131;hash += ch;}return hash;}
};

插入操作

哈希桶插入步骤

  • 计算哈希值: 使用哈希函数 hash(key) 将键值(key)映射为一个整数,称为 哈希值。这个哈希值决定了 key 应该被存储在哪个桶中。

  • 定位桶:根据哈希值和哈希表的大小(桶的数量),确定目标桶的位置。常用的方式是:bucket = hash(key) % num_buckets,其中 num_buckets 是哈希表的桶数量。

  • 检查冲突:定位到目标桶后,检查桶中是否已经存在与 key 相同的元素。如果已经存在,则插入操作可以直接结束(因为集合不允许重复元素),否则继续进行。

  • 插入元素: 如果目标桶中不存在相同的元素,直接将元素插入到该桶中。对于拉链法,目标桶通常使用链表(或类似结构)存储多个元素,因此新元素会被插入到链表末尾。

  • 哈希桶的扩容: 如果大小不够,一个桶的元素过于多,就需要进行扩容,创建一个新表进行插入操作。

bool insert(const T& data)
{HashFunc hf;bool it = Find(kot(data));if (it){return false;}if (_n == _table.size()){size_t newsize = _table.size() * 2;vector<Node*> newtable;newtable.resize(newsize,nullptr);for (int i = 0; i < _table.size() ;i++){HashFunc hf;size_t hashi = 0;Node* cur = _table[i];while (cur){Node* next = cur->_next;hashi = hf(cur->_data) % newtable.size();cur->_next = newtable[hashi];newtable[hashi] = cur;cur = next;}_table[i] = nullptr;}_table.swap(newtable);}size_t hashi = hf(data) % _table.size();Node* newnode = new Node(data);newnode->_next = _table[hashi];_table[hashi] = newnode;++_n;return true;
}

插入效率:

  • 时间复杂度:哈希桶的插入操作通常情况下的时间复杂度为 O(1),因为哈希函数能够在常数时间内定位到桶的位置。然而,最坏情况下(所有元素都被映射到同一个桶中),时间复杂度退化为 O(n),其中 n 是桶中元素的数量。
  • 空间复杂度:哈希表的空间复杂度与桶的数量和元素数量成正比,通常为 O(n)

删除操作

哈希桶删除步骤:

  • 计算哈希值: 使用哈希函数 hash(key) 计算出元素的哈希值,找到元素应该所在的桶。

  • 定位桶: 根据哈希值和哈希表的桶数量,确定目标桶的位置,通常通过:bucket = hash(key) % num_buckets 来找到对应的桶。

  • 遍历桶中的元素: 在找到的桶中,遍历桶中存储的所有元素(通常是通过链表存储),寻找需要删除的元素。

  • 删除元素: 一旦找到目标元素,将其从桶中删除(对于拉链法,通常是从链表中删除元素)。如果该元素不存在,则无需做任何操作。

bool Erase(const K& key)
{HashFunc hf;size_t hashi = hf(key) % _table.szie();Node* cur = _table[hashi];Node* prev = nullptr;while (cur){if (cur->_data == key){if (prev == nullptr){_table[hashi] = cur->_next;}else{prev->_next = cur->_next;}delete cur;--_n;return true;}prev = cur;cur = cur->_next;}return false;
}

时间复杂度分析

  • 最佳情况:每个桶中只有一个元素或哈希函数将元素均匀分布到桶中,删除操作的时间复杂度为 O(1),因为只需找到桶后直接删除即可。

  • 最坏情况:所有元素都被映射到同一个桶中,导致链表长度等于元素数量。在这种情况下,删除操作的时间复杂度为 O(n),其中 n 是链表中的元素数量。

  • 平均情况:如果哈希函数分布较好,链表的长度较短,删除操作的平均时间复杂度为 O(1)

查找操作

哈希桶查找步骤

  • 计算哈希值:使用哈希函数 hash(key) 计算出需要查找的元素的哈希值,找到元素应该存储的桶。
  • 定位桶:根据哈希值,计算出目标桶的索引。常用的方式是:bucket = hash(key) % num_buckets,其中 num_buckets 是哈希表的桶数量。
  • 在桶内查找: 如果该桶为空,直接返回元素不存在。如果桶内有元素,遍历桶中的链表或数组,逐个检查每个元素是否与要查找的键值相等。
  • 返回结果
    1. 如果找到与目标键相等的元素,则返回成功查找的结果。
    2. 如果遍历完整个桶(链表或数组)后,未找到目标元素,则返回查找失败。
bool Find(const K& key)
{HashFunc hf; size_t hashi = hf(key) % _table.size();Node* cur = _table[hashi];while (cur){if (kot(cur->_data) == key){return true;}cur = cur->_next;}return false;
}

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

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

相关文章

WPF入门教学六 Grid布局进阶

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;Grid布局是一种非常强大且灵活的布局控件&#xff0c;它允许你创建复杂的用户界面。以下是Grid布局的一些进阶技巧和教学&#xff1a; 一、基本概念回顾 Grid定义&#xff1a;Grid是一个用于布局…

深度学习(6):Dataset 和 DataLoader

文章目录 Dataset 类DataLoader 类 Dataset 类 概念&#xff1a; Dataset 是一个抽象类&#xff0c;用于表示数据集。它定义了如何获取数据集中的单个样本和标签。 作用&#xff1a; 为数据集提供统一的接口&#xff0c;便于数据的读取、预处理和管理。 关键方法&#xff…

AI公司的妄念:招个AI产品经理来想idea

AI公司在探索方向时&#xff0c;一旦老板或负责人的想法陷入瓶颈&#xff08;或没时间想特别细分的方向&#xff09;&#xff0c;往往会希望招一个AI产品经理来想idea&#xff08;创新/探索新方向&#xff09;&#xff0c;预期他某天突然想出个特别好的idea。 一、这个思路&…

【机器学习】12-决策树1——概念、特征选择

机器学习10-决策树1 学习样本的特征&#xff0c;将样本划分到不同的类别&#xff08;分类问题&#xff09;或预测连续的数值&#xff08;回归问题&#xff09;。 选择特征&#xff0c;划分数据集&#xff0c;划分完成形成模型&#xff08;树结构&#xff09;&#xff0c;一个…

OSI 七层模型和TCP/IP 四层模型的区别

目录 OSI 七层模型 介绍 1. 物理层&#xff08;Physical Layer&#xff09; 2. 数据链路层&#xff08;Data Link Layer&#xff09; 3. 网络层&#xff08;Network Layer&#xff09; 4. 传输层&#xff08;Transport Layer&#xff09; 5. 会话层&#xff08;Session …

【网络安全】基础知识详解(非常详细)零基础入门到精通,收藏这一篇就够了

一、什么是网络安全&#xff1f; 百度上对“网络安全”是这么介绍的&#xff1a; 网络安全是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然的或者恶意的原因而遭受到破坏、更改、泄露、系统连续可靠正常地运行&#xff0c;网络服务不中断。” 嗯…是不…

地表最强开源大模型!Llama 3.2,如何让你的手机变身私人智能助理

你有没有想过&#xff0c;为什么现在的手机越来越像小型电脑&#xff1f;无论是拍照、看视频&#xff0c;还是用各种APP&#xff0c;甚至是AI助手&#xff0c;手机的功能几乎无所不能。其实&#xff0c;这一切的背后有一个技术正在悄悄改变我们的生活&#xff0c;那就是Llama 3…

开发手札:内网开发Unity导致操作和编译卡顿的问题

最近一个工程切换了最新的unity和packages&#xff0c;在外网开发没什么问题&#xff0c;切换到内网接入保密开发后&#xff0c;发现不论是操作编辑器还是编译代码&#xff0c;巨卡无比。 以上是仅仅写了一句int a 1;后&#xff0c;编译代码的速度。 经过分…

初试Bootstrap前端框架

文章目录 一、Bootstrap概述二、Bootstrap实例1、创建网页2、编写代码3、代码说明4、浏览网页&#xff0c;查看结果5、登录按钮事件处理6、浏览网页&#xff0c;查看结果 三、实战小结 一、Bootstrap概述 大家好&#xff0c;今天我们将一起学习一个非常流行的前端框架——Boot…

在虚幻引擎中实时显示帧率

引擎自带了显示帧率的功能 但是只能在编辑器中显示 , 在游戏发布后就没有了 , 所以我们要自己做一个 创建一个控件蓝图 创建画布和文本 , 修改文本 文本绑定函数 , 点击创建绑定 添加一个名为 FPS 的变量 格式化文本 用大括号把变量包起来 {FPS Int} FPS 然后转到事件图表…

【论文串烧】多媒体推荐中的模态平衡学习 | 音视频语音识别中丢失导致的模态偏差对丢失视频帧鲁棒性的影响

文章目录 一、多媒体推荐中的模态平衡学习1.1 研究背景1.2 解决问题1.3 实施方案1.4 文章摘要1.5 文章重点1.6 文章图示图 1&#xff1a;不同模型变体在 AmazonClothing 数据集上的初步研究图 2&#xff1a;CKD模型架构的说明图 3&#xff1a;在 Amazon-Clothing 数据集上训练过…

Android 内核开发之—— repo 使用教程

前言 repo 是一个用于管理多个 Git 仓库的工具&#xff0c;特别适用于管理大型项目如 Android 的源码。它是由 Google 开发的&#xff0c;用于解决多个 Git 仓库的同步、管理和代码审查等问题。因此&#xff0c;做 Android 内核开发&#xff0c;首先要了解 repo 是什么&#x…

企业级-pdf预览-前后端

作者&#xff1a;fyupeng 技术专栏&#xff1a;☞ https://github.com/fyupeng 项目地址&#xff1a;☞ https://github.com/fyupeng/distributed-blog-system-api 留给读者 本文 一、介绍 对于PDF预览&#xff0c;有很多开发者都遇到过头疼的难题&#xff0c;今天给大家介绍…

数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式

数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式。 全透明加密&#xff08;也称作无损加密或自动加密&#xff09;就像是给文字戴上了一层无形的面具。在用户看来&#xff0c;他们在数据库中输入的是明文&#xff08;比如姓名、密码&#xff09;&#xf…

科研绘图系列:R语言多个AUC曲线图(multiple AUC curves)

文章目录 介绍加载R包导入数据数据预处理画图输出结果组图系统信息介绍 多个ROC曲线在同一张图上可以直观地展示和比较不同模型或方法的性能。这种图通常被称为ROC曲线图,它通过比较不同模型的ROC曲线下的面积(AUC)大小来比较模型的优劣。AUC值越大,模型的诊断或预测效果越…

《C++编程魔法:构建绿色主题的奇幻游戏世界》

在游戏开发的浩瀚宇宙中&#xff0c;色彩扮演着至关重要的角色。它不仅能营造氛围、激发情感&#xff0c;还能为玩家带来沉浸式的体验。想象一下&#xff0c;一个以绿色为主色调的游戏场景&#xff0c;充满生机与活力&#xff0c;仿佛让人置身于神秘的自然世界。本文将带你深入…

[vulnhub] pWnOS v2.0

https://www.vulnhub.com/entry/pwnos-20-pre-release,34/ 主机发现端口扫描 探测存活主机&#xff0c;150为靶机 nmap -sP 192.168.75.0/24 // Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-24 12:44 CST Nmap scan report for 192.168.75.1 Host is up (0.00013s lat…

介绍 Agent Q:迎接下一代 AI 自动化助手

引言 在科技领域&#xff0c;随着人工智能的不断进步&#xff0c;自动化工具日益成为提升效率的重要手段。今天&#xff0c;我将向大家介绍一款名为 Agent Q 的 AI 自动化助手。这款工具不仅能够完成复杂的任务&#xff0c;还支持交互式命令行操作&#xff0c;使得用户体验更为…

Linux相关概念和重要知识点(8)(操作系统、进程的概念)

1.操作系统&#xff08;OS&#xff09; &#xff08;1&#xff09;基本结构的认识 任何计算机系统都包含一个基本的程序集合&#xff0c;用于实现计算机最基本最底层的操作&#xff0c;这个软件称为操作系统。操作系统大部分使用C语言编写&#xff0c;少量使用汇编语言。 从…

利用低代码快速搭建电商小程序之商品列表页

目标&#xff1a; 搭建商城的一个商品列表页面&#xff08;先做静态页&#xff09; 开发环境&#xff1a; 访问白码低代码平台&#xff1a;https://www.bnocode.com/ 白码的新自定义页功能&#xff08;使用vue框架&#xff09; 前期准备&#xff1a; 需要先准备商品数据表…