【C++】unordered系列

前言:

在C++11及以后的标准中,unordered容器是标准模板库(STL)的一部分,提供了高效的数据结构选项,适用于需要快速查找和插入操作的场景。

unordered通常与关联容器一起使用,特别是unordered_mapunordered_set。这些容器提供了基于哈希表的实现,它们提供了与map和set相似的接口,但在查找、插入和删除操作上通常具有更高的性能,尤其是在处理大量数据时。

  • unordered_map是一个关联容器,它存储键值对,并根据键的哈希值进行排序,以实现快速的查找操作。
  • unordered_set则存储唯一的元素,并使用哈希表来管理这些元素,以便快速检查一个元素是否存在于集合中。

unordered_map的接口说明

注: unordered_mapunordered_set接口相似就只介绍一个接口。

unordered_map的接口说明

函数声明功能介绍
unordered_map构造不同格式的unordered_map对象

unordered_map的容量

函数声明功能介绍
bool empty()const检测unordered_map是否为空
size_t size() const获取unordered_map的有效元素个数

unordered_map的迭代器

函数声明功能介绍
begin返回unordered_map第一个元素的迭代器
end返回unordered_map最后一个元素下一个位置的迭代器
cbegin返回unordered_map第一个元素的const迭代器
cend返回unordered_map最后一个元素下一个位置的const迭代器

unordered_map的元素访问

函数声明功能介绍
operator[]返回与key对应的value,没有一个默认值

unordered_map的查询

函数声明功能介绍
iterator find(const K& key)返回key在哈希桶中的位置
size_t count(const K& key)返回哈希桶中关键码为key的键值对的个数

unordered_map的修改操作

函数声明功能介绍
insert向容器中插入键值对
erase删除容器中的键值对
void clear()清空容器中有效元素个数
void swap(unordered_map&)交换两个容器中的元素

unordered_map的桶操作

函数声明功能介绍
size_t bucket_count()const返回哈希桶中桶的总个数
size_t bucket_size(size_t n)const返回n号桶中有效元素的总个数
size_t bucket(const K& key)返回元素key所在的桶号

哈希

  1. **哈希(Hash)**是一种将任意大小的数据映射为固定大小值的函数,通常用于数据的快速查找和存储。
  2. **哈希表(Hash Table)**是基于哈希函数的一种数据结构,它通过计算关键字的哈希值来直接访问存储位置,从而实现常数时间复杂度的查找性能。

在这里插入图片描述

  • 在这里面的经过一系列的处理,得到的结果就映射到对应的位置,方便查找,加快了查找的速度。但是也会引发一系列的问题(哈希冲突)。

哈希函数

向上面的通过一系列的计算的过程就是哈希函数,有点类似于数学上的函数,一个数经过对应关系会得到两者的映射的关系。

常见的哈希函数

  1. 直接定址法:这种方法通过一个简单的线性函数计算哈希地址,公式为 Hash(Key) = A * Key + B。这种方法简单且分布均匀,但需要提前知道键值的分布情况。
  2. 除留余数法:这是一种常用的哈希函数,通过取关键字除以一个质数后的余数作为哈希地址,公式为 Hash(Key) = Key % p,其中 p 是一个不大于哈希表大小且最接近或等于哈希表大小的质数。
  3. 乘法取余法:这种方法通过将关键字乘以一个固定的数(通常是一个接近2的数),然后取结果的整数部分并进行取模运算来计算哈希地址。这种方法适用于处理字符串等非整数类型的键值。
  4. 平方取中法:这种方法适用于不清楚键值分布的情况,通过计算关键字平方后的中间几位数作为哈希地址。
  5. 折叠法:折叠法将键值分割成几部分,然后将这些部分叠加求和,并取后几位作为散列地址,适用于键值位数较多的情况。
  6. 标准库中的std::hash:C++标准库提供了std::hash模板,它为内置数据类型和一些标准库类型提供了默认的哈希函数实现。对于自定义类型,可以通过特化std::hash模板来提供自定义的哈希函数。

哈希冲突

哈希冲突是指不同的输入值通过哈希函数计算得到了相同的哈希值的现象。

  1. 在哈希表等数据结构中,哈希冲突是不可避免的,因为哈希函数的输出范围通常远小于可能的输入值范围。

解决方法

  • **开放定址法(闭散列):**当发生冲突时,会在哈希表中寻找下一个空位置来存放新元素。常见的开放定址法有线性探测和二次探测。线性探测是从冲突位置开始,依次向后查找空位置;二次探测则是通过更复杂的数学公式来确定下一个探测位置。
  • **再哈希法:**使用一个或多个备用哈希函数来处理冲突,将冲突的元素重新映射到哈希表的其他位置。
  • 链地址法(开散列):在哈希表的每个存储位置不是存储元素本身,而是存储一个指向元素的指针,冲突的元素会被添加到一个链表中。这种方法可以很好地处理大量冲突,但可能会导致链表过长,影响性能。
  • **建立公共溢出区:**为所有可能的哈希冲突预留一个或多个区域,冲突的元素被存储在这些区域中。

**注:**降低哈希冲突是提高效率的一个很好的方法

简单哈希

  • 在数组里面存储结构体
  • 定义哈希要有存在的状态定义了枚举
template<class K,class V>
struct Hashdata
{
	pair<K, V> _kv;
	state _state = EMPTY;
};
enum state
{
	EXIST,
	EMPTY,
	DELETE
};

Hash结构

  1. 两个模板参数K V结构
  2. 最后是存储hash的取值,针对整形、浮点型、字符串。进行仿函数的重写
template<class K,class V,class HashFunc = Defaulthashfunc<K>>
class Hash
{
public:

private:
	vector<Hashdata<K, V>> _table;
	size_t _n = 0;
};

仿函数

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

template<>
struct Defaulthashfunc<string>
{
	size_t operator()(const string& str)
	{
		size_t hash = 0;
		for (auto e : str)
		{
			hash *= 131;
			hash += e;
		}
		return hash;
	}
};

插入

  • 将hash表直接扩容,进行哈希计算
  • 进行哈希扩容 : 不建议直接将哈希表填写满,不利于哈数的查找,将哈希的负载因子(已经存储的数据比总空间的大小)设置到0.7到0.8之间即可。
  • 扩容: 重新定义哈希表(扩容后),进行数据的重新插入,进行交换
  • 进行哈希的冲突的解决
	bool insert(const pair<K, V>& kv)
	{
		size_t hashi = 0;
		HashFunc hf;
		hashi = hf(kv.first) % _table.size();

		if ((_n * 10 / _table.size()) >= 7)
		{
			size_t newsize = _table.size() * 2;
			Hash<K, V, HashFunc> newhash;
			newhash._table.resize(newsize);
			for (int i = 0; i < _table.size(); i++)
			{
				if (_table[i]._state == EXIST)
				{
					newhash.insert(_table[i]._kv);
				}
			}

			_table.swap(newhash._table);
		}

		//线性探测
		while (_table[hashi]._state == EXIST)
		{
			++hashi;
			hashi %= _table.size();
		}

		_table[hashi]._kv = kv;
		_table[hashi]._state = EXIST;
		++_n;

		return true;
	}

开放定址法(闭散列)

发生冲突会在哈希表的另外一个空位置寻找。

//线性探测
while (_table[hashi]._state == EXIST)
{
    ++hashi;
    hashi %= _table.size();
}

_table[hashi]._kv = kv;
_table[hashi]._state = EXIST;
++_n;

return true;
}

查找、删除

查找

返回结构体的指针利于后面的额删除

Hashdata<const K, V>* find(const K& key)
{
	HashFunc hf;
	size_t hashi = hf(key) % _table.size();
	while (_table[hashi]._state != EMPTY)
	{
		if (_table[hashi]._state == EXIST
			&& _table[hashi]._kv.first == key)
		{
			return (Hashdata<const K,V>*) & _table[hashi];
		}
		++hashi;
		hashi %= _table.size();
	}
	return nullptr;
}

删除

在删除的时候直接进行状态的修改

bool erase(const K& key)
{
	Hashdata<const K, V>* ret = find(key);

	if (ret)
	{
		ret->_state = DELETE;
		--_n;
		return true;
	}
	return false;

}

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

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

相关文章

图论篇--代码随想录算法训练营第六十一天打卡| Floyd 算法,A*算法

Floyd 算法&#xff08;求多源汇最短路&#xff09; 题目链接&#xff1a;97. 小明逛公园 题目描述&#xff1a; 小明喜欢去公园散步&#xff0c;公园内布置了许多的景点&#xff0c;相互之间通过小路连接&#xff0c;小明希望在观看景点的同时&#xff0c;能够节省体力&…

句子成分——每日一划(八)

目录 一、原句 二、第一部分 三、第二部分 一、原句 In class society everyone lives as a member of a particular class, and every kind of thinking, without exception, is stamped with the brand of a class. 来源&#xff1a;二、阶级和阶级斗争 二、第一部分 In…

谷粒商城のElasticsearch

文章目录 前言一、前置知识1、Elasticsearch 的结构2、倒排索引 (Inverted Index)2.1、 索引阶段2.2、查询阶段 二、环境准备1、安装Es2、安装Kibana3、安装 ik 分词器 三、项目整合1、引入依赖2、整合业务2.1、创建索引、文档、构建查询语句2.2、整合业务代码 后记 前言 本篇介…

初识php库管理工具composer的体验【爽】使用phpword模板功能替换里面的字符串文本

需求&#xff1a; 做了一个租赁的项目&#xff0c;里面要求签署个人授权协议&#xff0c;里面要填写姓名&#xff0c;手机号&#xff0c;身份证号&#xff0c;签署日期等参数&#xff0c;格式如下图 格式&#xff1a; 如上图&#xff0c;word中的字符串模板变量使用${varname…

Java设计模式—面向对象设计原则(三) -----> 依赖倒转原则DIP(完整详解,附有代码+案例)

文章目录 3.3 依赖倒转原则(DIP)3.3.1概述3.3.2 案例 3.3 依赖倒转原则(DIP) 依赖倒转原则&#xff1a;Dependency Inversion Principle&#xff0c;DIP 3.3.1概述 高层模块不应该依赖低层模块&#xff0c;两者都应该依赖其抽象&#xff1b;抽象不应该依赖细节&#xff0c;细…

演示:基于WPF的自绘的中国地铁轨道控件

一、目的&#xff1a;演示一个基于WPF的自绘的中国地铁轨道控件 二、效果演示 北京地铁 成都地铁 上海地铁 深圳地铁 南京地铁 长春地铁 哈尔滨地铁 武汉地铁 厦门地铁 香港地铁 三、功能 支持平移、缩放等操作 鼠标悬停显示线路信息和站点信息 按表格显示&#xff0c;按纸张…

MySQL —— 索引

索引的概念 MySQL的索引是⼀种数据结构&#xff0c;它可以帮助数据库高效地查询、更新数据表中的数据。索引通过 ⼀定的规则排列数据表中的记录&#xff0c;使得对表的查询可以通过对索引的搜索来加快速度。 MySQL索引类似于书籍的目录&#xff0c;通过指向数据行的位置&…

PCIe进阶之TL:First/Last DW Byte Enables Rules Traffic Class Field

1 First/Last DW Byte Enables Rules & Attributes Field 1.1 First/Last DW Byte Enables Rules Byte Enable 包含在 Memory、I/O 和 Configuration Request 中。本文定义了相应的规则。Byte Enable 位于 header 的 byte 7 。对于 TH 字段值为 1 的 Memory Read Request…

Requests-HTML模块怎样安装和使用?

要安装和使用Requests-HTML模块&#xff0c;您可以按照以下步骤进行操作&#xff1a; 打开命令行界面&#xff08;如Windows的命令提示符或Mac的终端&#xff09;。 使用pip命令安装Requests-HTML模块。在命令行中输入以下命令并按回车键执行&#xff1a; pip install request…

前端网页代码编辑器 Monaco Editor

前端网页代码编辑器 Monaco Editor Monaco Editor Monaco Editor 是由 Microsoft 开发的一款基于 Web 技术的开源代码编辑器&#xff0c;它是 Visual Studio Code 编辑器的核心。Monaco Editor 可以嵌入到网页中&#xff0c;提供类似于 Visual Studio Code 的编辑体验。 官方…

数据结构 Java DS——分享部分链表题目 (2)

目录 前言 题目一 —— 链表的回文结构 题目二 —— 二进制链表转整数 题目三 —— 设计链表 结尾 前言 关于JAVA的链表,笔者已经写了两篇博客来介绍了,今天给笔者们带来第三篇,也是分享了一些笔者写过的,觉得挺好的题目,链接也已经挂上了,笔者们可以去看看…

redis 基本数据类型—string类型

一、介绍 Redis 中的字符串&#xff0c;直接就是按照二进制数据的方式存储的&#xff0c;不会做任何的编码转换。 Redis对于 string 类型&#xff0c;限制了大小最大是512M 二、命令 SET 将 string 类型的 value 设置到 key 中。如果 key 之前存在&#xff0c;则覆盖&#…

亚马逊、沃尔玛、敦煌网、Target塔吉特、Temu环境搭建测评技术!

海外跨境电商各大主要平台正不断力推半托管模式&#xff0c;不断对商家开出众多吸引和扶持政策。全托管是指电商平台全面负责店铺的运营&#xff0c;包括仓储、配送、售后等&#xff0c;而商家主要负责提供货品。半托管模式则基本由商家自主经营&#xff0c;平台只负责仓配物流…

java中Class文件的文件格式

无关性的基石 计算机底层只能识别二进制&#xff0c;由CPU直接处理二进制&#xff0c;在底层上面是操作系统&#xff0c;在操作系统上面就是虚拟机&#xff0c;java有一个口号&#xff0c;“一次编写&#xff0c;到处运行”这个不太可能在操作系统层面上实现&#xff0c;不同的…

俄罗斯方块——C语言实践(Dev-Cpp)

目录 1、创建项目(尽量不使用中文路径) 2、项目复制 3、项目配置 ​1、调整编译器 2、在配置窗口选择参数标签 3、添加头文件路径和库文件路径 4、代码实现 4.1、main.c 4.2、draw.h 4.3、draw.c 4.4、shape.h 4.5、shape.c 4.6、board.h 4.7、board.c 4.8、cont…

Vue.js入门系列(二十九):深入理解编程式路由导航、路由组件缓存与路由守卫

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

解锁编程潜力,从掌握GitHub开始

目录&#xff1a; 一、搜索开源项目 1、什么是Git 2、Github常用词含义 3、一个完整的项目界面 4、使用Github搜索项目 1&#xff09;in关键词 2&#xff09;star或fork数量去查找 3&#xff09;awesome加强搜索 二、访问速度慢的解决 1、使用网易UU加速器 2、使用…

Visual Studio(vs)下载安装C/C++运行环境配置和基本使用注意事项

基本安装 点击跳转到vs官网点击箭头所指的按钮进行下载双击运行刚才下载好的下载器点击继续勾选“使用C的桌面开发”和“Visual Studio扩展开发”点击“安装位置”&#xff0c;对vs的安装位置进行更改。你可以跟我一样只选择D盘或者其他你空闲的盘&#xff0c;然后将默认的路径…

响应式CSS 媒体查询——WEB开发系列39

CSS媒体查询&#xff08;Media Queries&#xff09;是响应式设计中的核心技术之一&#xff0c;帮助我们在不同设备上展示不同的样式。通过媒体查询&#xff0c;开发者可以检测用户设备的特性&#xff0c;如屏幕宽度、高度、分辨率、方向等&#xff0c;针对性地调整网页布局。 一…

架构师知识梳理(七):软件工程-工程管理与开发模型

软件工程概述 软件开发生命周期 软件定义时期&#xff1a;包括可行性研究和详细需求分析过程&#xff0c;任务是确定软件开发工程必须完成的总目标&#xff0c;具体可分成问题定义、可行性研究、需求分析等。软件开发时期&#xff1a;就是软件的设计与实现&#xff0c;可分成…