《STL基础之hashtable》

【hashtable导读】STL为大家提供了丰富的容器,hashtable也是值得大家学习和掌握的基础容器,而且面试官经常会把它和hashmap混在一起,让同学们做下区分。因此关于hashtable的一些特性,比如:底层的数据结构、插入、查找元素的时间复杂度,这些很有必要和大家一起分享下

开门见山,hashtable设计的初衷就是为了方便元素的快速插入、查找,到底有多快速呢?查找、删除元素的时间复杂度为O(1),那支持时间复杂度为O(1)的数据结构,无非就是数组,比如:vector。vector其实就是操作系统为大家分配的一段连续的内存空间,支持随机跳转访问。

因此根据上述推论,hashtable底层的数据结构肯定是含有vector这个数据结构的。但只有vector还是不够的,因为操作系统的内存空间有限,要支持存储海量数据,而且这些海量数据都存放在连续的内存中,肯定不现实,比如:笔者有1000万个,大小为3字节的随机字符串,我们如果把这些数据存放在一段连续的内存空间中,我们就需要申请长度为10000000的指针数组,依次存放这些字符串,总共占用内存大小将近410010000字节,也就是38G多!很恐怖。

char* strArr[1000*10000];
for (int i = 0; i < 1000 * 10000; ++i)
    strArr[i] = "xx" + std::itoa(rand() % 10);

而且strArr还存在一个问题,如何去快速地查找,指定地某个元素?strArr只支持下标访问,比如:strArr[10]、strArr[1000]这种方式去获取第11位、1001位的字符串。

因此为了能实现以下标地方式去获取指定地字符串,hashtable实现了比较完备的hash函数,将指定的字符串计算成特定的哈希值(整数值),再对hashtable底层的vector的大小Size进行求余,便可得到该字符串对应的哈希值再vector中索引值。
在这里插入图片描述
那么就实现了以O(1)的时间复杂度定位到指定字符串的位置,那字符串应该存到哪里?注意上图中的vector并不是一个空的vector,vector中存储的元素类型就是__hashtable_node,STL是这样定义这个节点的。

template <class Value>
struct __hashtable_node
{
  __hashtable_node* next;
  Value val;
}

其中next指针指向下一个节点,val便用来存储指定的字符串。可以这么理解,vector中每个单元便是链表的头节点,如果有其它的字符串的哈希值也是2,那么就在索引值为2的单元下扩展这个单链表。效果图如下:

在这里插入图片描述
假如有其他的字符串“abc”,经过hash计算得到的索引值也是2,那么“abc”应该怎样插到这个链表中。我们直接看STL源码,针对哈希冲突的场景,看字符串是如何被插进去的?


template <class V, class K, class HF, class Ex, class Eq, class A>
pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool>
hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)
{
   //bkt_num就是就算插入对象的哈希值为n
   const size_type n = bkt_num(obj);
   //取出vetor中索引值为n的节点
   node* first = buckets[n];
   for (node* cur = first; cur; cur = cur->next)
   {
       if (equals(get_key(cur->val), get_key(obj))
            return pair<iterator, bool>(iterator(cur, this), false);
   }
   //使用头插法将obj插入到索引值为n的单元下的链表中去
   //使用头插法,所以时间复杂度一直为O(1)
   node* temp = new_node(obj);
   temp->next = first;
   buckets[n] = temp;
   ++num_elements;
   return pair<iterator, bool>(iterator(temp, this), true);
}

有点需要注意,如果插入失败,就返回链表中头结点。介绍完插入节点,那查找节点的流程又是怎样的?


iterator find(const key_type& key)
{
  size_type n = bkt_num_key(key);
  mode* first;
  for (first = buckets[n]; first && !equals(get_key(first->val), key);
  first = first->next)
  {}
  return iterator(first, this);
}

查找流程很简单,逐个遍历节点,如果没找到,就返回链表中最后一个节点给应用层,虽然是逐个遍历链表,但时间复杂度也是O(1),因为哈希表的开链算法、哈希算法绝对能保证哈希冲突不会太大,即buckets中每个单元下挂载的链表长度不会太长。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

本地大模型编程实战(02)语义检索(2)

文章目录 准备按批次嵌入加载csv文件&#xff0c;分割文档并嵌入测试嵌入效果总结代码 上一篇文章&#xff1a; 本地大模型编程实战(02)语义检索(1) 详细介绍了如何使用 langchain 实现语义检索&#xff0c;为了演示方便&#xff0c;使用的是 langchain 提供的内存数据库。 在实…

猿人学第一题 js混淆源码乱码

首先检查刷新网络可知&#xff0c;m参数被加密&#xff0c;这是一个ajax请求 那么我们直接去定位该路径 定位成功 观察堆栈之后可以分析出来这应该是一个混淆&#xff0c;我们放到解码平台去还原一下 window["url"] "/api/match/1";request function…

Dev-C++分辨率低-解决办法

目录 【工具】Dev-C分辨率低-解决办法问题背景完整操作指南第一步&#xff1a;打开属性设置 【工具】Dev-C分辨率低-解决办法 问题背景 Dev-C因版本老旧&#xff08;长期未更新&#xff09;&#xff0c;在高分辨率显示器上存在界面模糊问题。通过修改Windows兼容性设置可优化…

Linux 小火车

1.添加epel软件源 2.安装sl 3. 安装完成后输入&#xff1a; sl

iic、spi以及uart

何为总线&#xff1f; 连接多个部件的信息传输线&#xff0c;是部件共享的传输介质 总线的作用&#xff1f; 实现数据传输&#xff0c;即模块之间的通信 总线如何分类&#xff1f; 根据总线连接的外设属于内部外设还是外部外设将总线可以分为片内总线和片外总线 可分为数…

Linux_线程控制

线程控制的相关接口 进程创建相关 之前我们已经认识到了pthread_create函数用来创建线程&#xff0c;这里不再赘述。 pthread_self函数 void* routine(void* args) {std::cout << "我是新线程..." << pthread_self() << std::endl;return null…

利用双指针一次遍历实现”找到“并”删除“单链表倒数第K个节点(力扣题目为例)

Problem: 19. 删除链表的倒数第 N 个结点 文章目录 题目描述思路复杂度Code 题目描述 思路 1.欲找到倒数第k个节点&#xff0c;即是找到正数的第n-k1、其中n为单链表中节点的个数个节点。 2.为实现只遍历一次单链表&#xff0c;我们先可以使一个指针p1指向链表头部再让其先走k步…

Ubuntu-手动安装 SBT

文章目录 前言Ubuntu-手动安装 SBT1. SBT是什么?1.1. SBT 的特点1.2. SBT 的基本功能1.3. SBT 的常用命令 2. 安装2.1. 下载2.2. 解压 sbt 二进制包2.3. 确认 sbt 可执行文件的位置2.4. 设置执行权限2.5. 创建符号链接2.6. 更新 PATH 环境变量2.7. 验证 sbt 安装 前言 如果您觉…

【ProtoBuf 安装】ProtoBuf在window/Linux下的安装 创建/删除swap分区

文章目录 1.ProtoBuf在window下的安装2.ProtoBuf在Linux下的安装创建swap分区命令解析关闭swap分区删除swap分区的影响 1.ProtoBuf在window下的安装 1、下载ProtoBuf编译器 下载地址&#xff1a;https://github.com/protocolbuffers/protobuf/releases 如果要在 C 下使用 Pro…

BAHD酰基转移酶对紫草素的手性催化-文献精读105

Two BAHD Acyltransferases Catalyze the Last Step in the Shikonin/Alkannin Biosynthetic Pathway 两个BAHD酰基转移酶催化了紫草素/左旋紫草素生物合成途径中的最后一步 一个BAHD酰基转移酶专门催化紫草素的酰基化&#xff0c;而另一个BAHD酰基转移酶则仅催化紫草素的对映…

C语言初阶力扣刷题——349. 两个数组的交集【难度:简单】

1. 题目描述 力扣在线OJ题目 给定两个数组&#xff0c;编写一个函数来计算它们的交集。 示例&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2] 输入&#xff1a;nums1 [4,9,5], nums2 [9,4,9,8,4] 输出&#xff1a;[9,4] 2. 思路 直接暴力…

在Docker 容器中安装 Oracle 19c

在 Docker 容器中安装 Oracle 19c 是可行的&#xff0c;但它相较于其他数据库&#xff08;如 MySQL、PostgreSQL 等&#xff09;会复杂一些&#xff0c;因为 Oracle 数据库有一些特定的要求&#xff0c;如操作系统和库的依赖&#xff0c;以及许可证问题。 不过&#xff0c;Ora…

WGCLOUD使用介绍 - 如何监控ActiveMQ和RabbitMQ

根据WGCLOUD官网的信息&#xff0c;目前没有针对ActiveMQ和RabbitMQ这两个组件专门做适配 不过可以使用WGCLOUD已经具备的通用监测模块&#xff1a;进程监测、端口监测或者日志监测、接口监测 来对这两个组件进行监控

初学stm32 --- FreeRTOS移植

目录 移植前准备 1. 基础工程 2. FreeRTOS 源码 添加 FreeRTOS 文件 1. 添加 FreeRTOS 源码 2. 将文件添加到工程 3. 添加头文件路径 4. 添加 FreeRTOSConfig.h 文件 (1) FreeRTOSConfig.h 获取途径一 (2) FreeRTOSConfig.h 获取途径二 (3) FreeRTOSConfig.h 获取途径…

ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法

①. ThreadLocal简介 ①. ThreadLocal是什么 ①. ThreadLocal本地线程变量,线程自带的变量副本(实现了每一个线程副本都有一个专属的本地变量,主要解决的就是让每一个线程绑定自己的值,自己用自己的,不跟别人争抢。通过使用get()和set()方法,获取默认值或将其值更改为当前线程…

【2024年 CSDN博客之星】我的2024年创作之旅:从C语言到人工智能,个人成长与突破的全景回顾

我的2024年创作之旅&#xff1a;从C语言到人工智能&#xff0c;个人成长与突破的全景回顾 引言 回望2024年&#xff0c;我不仅收获了技术上的成长&#xff0c;更收获了来自CSDN平台上无数粉丝、朋友以及网友们的支持与鼓励。在这条创作之路上&#xff0c;CSDN不仅是我展示技术成…

Windows11恢复传统右键菜单

Windows11恢复传统右键菜单 执行下面的命令(管理员下) reg add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /vetaskkill /f /im explorer.exestart explorer.exe或者 reg add "HKCU\Software\Classes\CLSID\{8…

PCIE模式配置

对于VU系列FPGA&#xff0c;当DMA/Bridge Subsystem for PCI Express IP配置为Bridge模式时&#xff0c;等同于K7系列中的AXI Memory Mapped To PCI Express IP。

WPS数据分析000008

目录 一、替换 通配符 求出橙色底纹单元格的和 二、定位 拆分并填充内容 删除空行 一、替换 快捷键ctrlh 注意&#xff1a;限制数据区域。 若为单元格&#xff0c;表示选择整个工作表。 通配符 求出橙色底纹单元格的和 第一步&#xff1a;查找出橙色单元格&#xff0c;c…

Excel制作合同到期自动提醒!

大家好&#xff0c;我是小鱼。 今天分享一下如何利用Excel制作合同到期提醒表&#xff0c;实现Excel表格自动计算合同到期日和天数&#xff0c;根据合同状态和到期天数自动填充颜色提醒&#xff0c;超实用。先看一下效果&#xff0c;已经到期的合同会自动被填充为红色&#xf…