C++进阶 —— 哈希

一篇文章搞懂C++实现哈希算法 哈希算法,也称为散列算法,是一种从任意长度的输入数据创建固定大小输出的方法,这种输出通常被称为“哈希值”、“散列值”或简单地“哈希”。在计算机科学中,哈希算法主要用于快速数据查找和数据结构中的高效数据管理,如哈希表。哈希也是加密和数据完整性验证的基础。哈希算法通过一个称为哈希函数的数学过程来运作。这个函数接受输入(称为“预映射值”)并返回一个通常较短、固定长度的哈希值。这个哈希值在理想情况下为每个不同的输入值提供一个唯一的标识(尽管在实际中这并不总是可能的)。 阅读详情

目录

一,哈希的介绍

二,哈希函数

二,哈希冲突解决

闭散列

开散列

开散列与闭散列比较


        在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,查询效率可达到logN,即最差情况下需要比较红黑树的高度次,当树节点非常多时,查询效率也不理想;最好的查询是,进行很少的比较次数就能够将元素找到,因此C++11,STL又提供了4个unordered系列的关联式容器(unordered_set/unordered_map、unordered_multiset/unordered_multimap),这4个容器与红黑树结构的关联式容器使用方式基本类似,只是结构不同;

一,哈希的介绍

        unordered系列关联式容器之所以效率高,是因为其底层使用了哈希结构;

        顺序结构以及平衡树中,元素与其存储位置没有对应关系,因此在查找元素时,必须经过元素的多次比较;顺序查找时间复杂度为O(N),平衡树中为树的高度即O(logN),搜索效率取决于搜索过程中的比较次数;

        理想的搜索方法,即可不经过任何比较,一次直接从表中得到要搜索的元素;如构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的元素之间能够建立一一对应的关系,那么在查找时通过该函数可以很快找到该元素;

插入元素,根据待插入元素关键码,以此函数计算出该元素的存储位置并按次位置进行存放;

搜索元素,对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功;

        该方式称为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(散列表)Hash Table;

该方法进行搜索不必进行多次元素比较,因此搜索速度较快;

二,哈希函数

哈希冲突

  • 对于两个元素的关键码k_{i}、k_{j},当hash(k_{i})==hash(k_{j}),即不同关键码通过相同哈希函数计算出相同的哈希地址,称为哈希冲突或哈希碰撞;
  • 把具有不同关键码而具有相同哈希地址的数据元素称为“同义词”;

引发哈希冲突的原因可能是,哈希函数设计不够合理;

哈希函数设计原则

  • 哈希函数的定义域必须包括需要存储的全部关键码,如哈希表允许有m个地址时,其值域必须在0~m-1之间;
  • 哈希函数计算出来的地址能均匀分布在整个空间中;
  • 哈希函数应该比较简单;

常见哈希函数

  • 直接定制法(常用)
    • 取关键码的某个线性函数作为散列地址,Hash(Key)=A*Key+B;
    • 适合查找比较小且连续的情况;
    • 优点,简单、均匀;
    • 缺点,需要事先知道关键码的分布情况;
  • 除留余数法(常用)
    • 假设散列表中允许的地址数为m,取一个不大于m,但最接近或等于m的质子p作为除数,按照哈希函数Hash(Key)=Key%p(p<m),将关键码转换成哈希地址;
  • 平方取中法(了解)
    • 假设关键码为1234,对其平方就是1522756,抽取中间3位227作为哈希地址;
    • 在如关键码为4321,对其平方就是18671041,抽取中间3为671(或710)作为哈希地址;
    • 比较适合不知道关键码的分布,而位数又不是很大的情况;
  • 折叠法(了解)
    • 是将关键码从左到右分割成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和,并按散列表长,取后几位作为散列表地址;
    • 适合事先不知道关键码的分布,适合关键码位数比较多的情况;
  • 随机数法(了解)
    • 选择一个随机函数,取关键码的随机函数值为它的哈希地址,Hash(Key)=random(Key);
    • 通常应用于关键码长度不等时常用此法;
  • 数学分析法(了解)
    • 设有n个d位数,每一位可能有r种不同的符号,这r种不同的符号在各位上出现的频率不一定相同,可能 在某些位上分布比较均匀,每种符号出现的机会均等,在某些位上分布不均匀只有某几种符号经常出现。可根据散列表的大小,选择其中各种符号分布均匀的若干位作为散列地址;
    • 适合处理关键码位数比较大的情况,如事先折叠关键码的分布且关键码的若干位分布较均匀的情况;

注:哈希函数设计的越精妙,哈希冲突就越低,但无法避免哈希冲突;

二,哈希冲突解决

        解决哈希冲突常见方法,闭散列、开散列;

闭散列

        也叫开放定址法,当发生哈希冲突时,如哈希表未被装满,说明在哈希表中必然还有空位置,那么可把key存放到冲突位置中的“下一个”空位置中去,寻找“下一个”空位置方法有,线性探测和二次探测;

1,线性探测

        如上述案例中,在插入元素44,计算的哈希地址为4,但该位置已存放了元素,发生了哈希冲突;线性探测,从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止;

  • 插入,通过哈希函数获取插入哈希表中的位置;
    • 如该位置没有元素直接插入;
    • 如该位置已有元素使用线性探测找到下一个空位置,插入新元素;
  • 删除,采用闭散列处理哈希冲突时,不能随便物理删除哈希表中已有元素,若直接删除会影响其他元素的搜索;因此线性探测采用标记的伪删除法来删除元素;
//哈希表每个空间给个标记
//EMPTY为空,EXISTY已有元素,DELETE元素已删除
enum State {
    EMPTY,   // 空槽
    EXIST,   // 有元素
    DELETE   // 元素被删除(墓碑状态)
};

优点:实现非常简单;

缺点:一旦发生哈希冲突,所有的冲突连在一起,容易发生数据堆积,即不同关键码占据了可利用的空位置,使得寻找某关键码的位置需要许多次比较,导致效率低下;

//线性探测的实现
template<class K, class V>
class HashTable
{
private:
	struct Elem
	{
        Elem() : _state(EMPTY) {}
		pair<K, V> _val;
		State _state;
	};

	vector<Elem> _ht;
	size_t _size;

	size_t HashFunc(const K& key)
		return key % _ht.capacity();

public:
	HashTable(size_t capacity = 3)
		:_ht(capacity, _size(0))
	{
		for (size_t i = 0; i < capacity; ++i)
		{
			_ht[i]._state = EMPTY;
		}
	}

	bool Insert(const pair<K, V>& val)
	{
		size_t hashAddr = HashFunc(key);
		while (_ht[hashAddr] != EMPTY)
		{
			if (_ht[hashAddr]._state == EXIST && _ht[hashAddr]._val.first == key)
				return false;
			hashAddr++;
			if (hashAddr == _ht.capacty())
				hashAddr = 0;
		}
		_ht[hashAddr]._state = EXIST;
		_ht[hashAddr]._val = val;
		_size++;
		return true;
	}

	int Find(const K& key)
	{
		size_t hashAddr = HashFunc(key);
        size_t startAddr = hashAddr;

		while (_ht[hashAddr]._state != EMPTY)
		{
			if (_ht[hashAddr]._state == EXIST && _ht[hashAddr]._val._first == key)
				return hashAddr;
			hashAddr++;
			if (hashAddr == _ht.capacty())
				hashAddr = 0;
		}
        if (hashAddr == startAddr) break;
		return -1;
	}

	bool Erase(const K& key)
	{
		int index = Find(key);
		if (index != -1)
		{
			_ht[index]._state = DELETE;
			_size--;
			return true;
		}
		return false;
	}
};

哈希表扩容

        散列表的载荷因子定义为:\alpha = 填入表中的元素个数 / 散列表的长度

        \alpha是散列表装满程度的标志因子,由于表长是定值,\alpha与“填入表中的元素个数”成正比,\alpha越大填入表中元素越多,产生冲突的可能性越大;反之,\alpha越小填入表中的元素越少,产生冲突的可能性就越小;实际上,散列表的平均查找长度是载荷因子\alpha的函数,只是不同处理冲突的方法有不同的函数;

        对于开放定址法,载荷因子是特别重要因素,应严格限制在0.7-0.8以下;超过0.8,查表时cpu缓存不命中(cache missing)按照指数曲线上升,因此一些采用开放定址法的hash库,如Java的系统库限制了载荷因子为0.75,超过此值将resize散列表;

void CheckCapacity()
{
	if (_size * 10 / _ht.capacity() >= 7)
	{
		HashTable(K, V, HF) newHt(GetNextPrime(ht.capacity));
		for (size_t i = 0; i < _ht.capacity(); ++i)
		{
			if (_ht[i]._state == EXIST)
				newHt.Insert(_ht[i]._val);
		}
		Swap(newHt);
	}
}

2,二次探测

        线性探测的缺陷时产生冲突的数据堆积在一块,这与其找下一个位置有关系,因为找空位置的方式就是挨个往后逐个查找的;二次探测就是为了避免该问题的,找下一个空位置的方法为,H_{i}=(H_{0}+i^{2})%m 或 H_{i}=(H_{0}-i^{2})%m(i=1,2,3...,H_{0}是通过散列函数Hash(X)对元素的关键码key进行计算得到的位置,m表示表的大小);

        研究表明,当表长度为质数且表转载因子\alpha不超过0.5时,新表项一定能够插入,而且任何一个位置都不会被探查两次,因此只要表中有一半的位置,就不会存在表满的问题,在搜索时可以不考虑表装满的情况,但在插入时必须确保表的装载因子\alpha不超过0.5,如超过需考虑增容;

         因此,闭散列最大的缺陷就是空间利润率较低,这也是哈希的缺陷;

开散列

        又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头节点存储在哈希表中;

在开散列中,每个桶中放的都是发生哈希冲突的元素;

//开散列的实现
template<class V>
struct HashBucketNode
{
	HashBucketNode(const V& data)
		:_pNext(nullptr)
		,_data(data)
	{}

	HashBucketNode<V>* _pNext;
	V _data;
};

template<class V>
class HashBucket
{
	typedef HashBucketNode<V> Node;
	typedef Node* pNode;
private:
	vector<pNode*> _ht;
	size_t _size;

	size_t HashFunc(const V& data)
		return data % _ht.capacity();

public:
	HashBucket(size_t capacity = 3)
		:_size(0)
	{
		_ht.resize(GetNextPrime(capacity), nullptr);
	}

	pNode* Insert(const V& data)
	{
		size_t bucketNo = HashFunc(data);
		pNode pCur = _ht[bucketNo];
		while (pCur) //查找插入元素是否已存在
		{
			if (pCur->_data == data)
				return pCur;
			pCur = pCur->_pNext;
		}
		pCur = new Node(data);
		pCur->_pNext = _ht[bucketNo];
		_ht[bucketNo] = pCur;
		_size++;
		return pCur;
	}

	pNode* Erase(const V& data)
	{
		size_t bucketNo = HashFunc(data);
		pNode pCur = _ht[bucketNo];
		pNode pPrev = nullptr;
		pNode pRet = nullptr;
		while (pCur)
		{
			if (pCur->_data == data)
			{
				if (pCur == _ht[bucketNo])
					_ht[bucketNo] = pCur->_pNext;
				else
					pPrev->_pNext = pCur->_pNext;
				pRet = pCur->_pNext;
				delete pCur;
				_size--;
				return pRet;
			}
            pPrev = pCur;
            pCur = pCur->_pNext;
		}
		return nullptr;
	}

	pNode* Find(const V& data);
	size_t Size()const;
	bool Empty()const;
	void Clear();
	bool BucketCount()const;
	void Swap(HashBucket<V, HF>& ht);
	~HashBucket();
};

开散列增容

        桶的个数是一定的,随着元素的不断插入,每个桶中的元素个数会不断增加,可能会导致一个桶中链表节点非常多,进而影响哈希表的性能,因此在一定条件下需要对哈希表进行增容;开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此在元素个数刚好等于桶个数时,可给哈希表增容;

void _CheckCapacity()
{
	size_t bucketCount = BucketCount();
	if (_size == bucketCount)
	{
		HashBucket<V, HF> newHt(bucketCount*2);
		for (size_t bucketIdx = 0; bucketIdx < bucketCount; ++bucketIdx)
		{
			pNode pCur = _ht[bucketIdx]; //遍历每个旧桶
			while (pCur)
			{
				_ht[bucketIdx] = pCur->_pNext; //记录旧桶中的下一个节点
				size_t bucketNo = newHt.HashFunc(pCur->_data); 
				pCur->_pNext = newHt._ht[bucketNo]; //将该节点的下一个节点连接到新桶的头节点;
				newHt._ht[bucketNo] = pCur; //新桶连接到该节点;
				pCur = _ht[bucketIdx]; //旧桶的下一个节点
			}
		}
		newHt._size = _size;
		this->Swap(newHt);
	}
}

开散列的思考

只能存储key为整数的元素,其他类型怎么解决?

除留余数法,最好模一个素数,如何每次快速取一个类似两倍关系的素数?

开散列与闭散列比较

        应用链地址法处理溢出,需增设链接指针,似乎增加了存储开销;事实上,由于开地址法必须保持大量的空闲空间以确保搜索效率,如二次探查法要求转载因子\alpha<=0.7,而表项所占空间又比指针大的多,所以使用链地址法反而比开地址法节省存储空间;

、

【C++】-- 哈希算法 如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的key之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。 向该结构中插入元素和查找元素时: 插入元素:将元素key存放到用hashFunc计算出的元素key的位置。 查找元素:对元素的key进行计算,把用hashFunc计算的函数值当做元素的存储位置,在哈希结构中按此位置取元素比较,若key相等,则查找成功。 阅读详情

相关推荐

C++哈希算法详解(hash、hash!)

C++哈希算法详解

2401_90042730的博客 1974

[C++] 哈希详解

哈希

weixin_43717520的博客 9286

C++进阶——哈希的实现

在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到O(log2​N),即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。

weixin_43635473的博客 1276

【C++】哈希

哈希表的基本概念以及如何分别使用闭散列和开散列来模拟实现哈希表。

在平淡的日子里寻找存在的价值 3790

C++11 std::hash 实战进阶:从内置类型到自定义哈希

本文深入探讨了C++11中std::hash的实战应用,从内置类型到自定义哈希的实现方法。通过详细示例和技巧分享,帮助开发者掌握如何为自定义类型实现高效的哈希函数,优化unordered容器的性能,并避免常见陷阱。

weixin_30781107的博客 300

Android应用隐私合规自动化检测:Frida与Camille实战指南

在移动应用安全与隐私合规领域,动态代码插桩技术已成为核心检测手段。其原理是通过运行时注入,实时监控和修改应用行为,从而绕过传统静态分析的局限。这项技术的核心价值在于能够精准捕获应用在运行时的敏感数据调用与网络传输行为,为隐私合规审计、安全测试提供直接证据。在实际应用场景中,它尤其适用于自动化检测违规收集个人信息、追踪数据流向等任务。本文聚焦于利用Frida这一动态插桩框架,结合Camille隐私合规检测工具集,构建自动化监控环境。通过注入JavaScript代码,实现对Android敏感API(如获取设备标

weixin_34254464的博客 388

c++进阶——哈希表

简单说:三个名字表示三种情况,但是这三个名字底层都是整数值。

2401_83052144的博客 1275

【技术解析】Point-NeRF:如何通过点云优化加速神经辐射场渲染

本文深入解析了Point-NeRF技术,它通过引入3D点云作为几何先验,有效解决了传统神经辐射场渲染速度慢的痛点。该方法利用神经点云构建局部辐射场,结合点剪枝与生长策略进行动态优化,在保证高渲染质量的同时,实现了高达30倍的训练加速,为高效3D场景重建提供了新范式。

weixin_29159127的博客 266

《C++进阶之STL》【哈希表】

本文介绍了哈希表的核心概念和关键术语,重点解析了哈希函数的设计原理和常见类型。文章详细讲解了直接定址法和除法散列法两种哈希函数,分析其优缺点及适用场景。最后指出哈希函数的选择需结合实际场景,平衡性能与资源消耗。全文为理解哈希表实现机制提供了理论基础。

序属秋秋秋的博客 4965

06 - 深度学习处理器原理

深度学习处理器的重要性在于它们可以加速深度学习任务的执行,从而推动了人工智能的发展。传统的通用处理器虽然可以执行深度学习任务,但它们不够高效,需要消耗大量的能量和时间。深度学习处理器通过硬件加速和特定设计来优化深度学习任务的执行,从而可以提高执行效率、降低能耗和加速训练和推断过程。 深度学习处理器的发展也推动了深度学习算法的创新,因为算法的发展需要硬件的支持和驱动。同时,深度学习处理器的出现也促进了更广泛的应用场景,包括自动驾驶、人脸识别、语音识别、图像识别等领域。因此,深度学习处理器的重要性不仅在于加速

m0_51339444的博客 752

算法 | 基于MATLAB的增量式SVD技术综述:实现方法、代码示例与应用实践

效率提升:较传统SVD降低计算复杂度从On3O(n^3)On3至On2O(n^2)On2实时性:支持毫秒级动态数据更新资源友好:内存占用降低60%-80%[5]

尘世冰封的专栏 485

C++进阶:哈希

哈希(hash)⼜称散列,是⼀种组织数据的⽅式。从译名来看,有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系,查找时通过这个哈希函数计算出Key存储的位置,进⾏快速查找。

QinMou 1120

RK3588 部署 YOLO26 目标检测:从环境搭建到 NPU 推理

采集图像(500+ 张,覆盖不同光照和角度)→ 筛选(删除模糊、无目标的图像)→ LabelImg 标注(选择 YOLO 格式)→ 划分 train:val:test = 7:2:1labelImg├── train/├── val/nc: 3类别顺序必须与 LabelImg 标注时一致。YOLO26 在 RK3588 上的部署流程是 PC 端训练 → ONNX 导出(opset=11)→ RKNN 转换(INT8 量化)→ 板端推理。

LXY_LOVE36的博客 418

C++进阶—哈希

在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log₂N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。

Awkwardx的博客 856

uniapp微信小程序 - 解决输入框input软键盘弹起时页面整体上移问题,页面上推导致顶部出现元素遮挡问题,uniapp软键盘导致页面上移头部内容被错位遮住错乱,让页面头固定在顶部不动不会受影响!

解决uni-app微信小程序底部input输入框,键盘弹起时页面整体上移问题,当键盘弹起时,会导致页面整体上移,页面头固定在顶部不动,微信小程序键盘弹起时,底部输入框抬起至键盘上方,顶部导航栏固定不动,uni-app输入框,输入框在底部;当弹出键盘时,页面整体上移,页面头信息会消失不见,小程序底部input输入框,input组件弹起系统键盘时,键盘会顶住页面导致页面会上移,当键盘弹起时整个页面被挤压,导致元素上移或被覆盖,输入框能自动抬起至键盘上方,顶部导航栏保持固定,不被顶上去,如何解决这个问题,动态高度

✅ 精选推荐文章 1万+

第8章 - 异构系统的协同控制及最优控制 --> 最优控制

异构系统的协同控制及最优控制 --> 协同控制

赵继超的笔记 2259

【C++进阶】哈希

桶的个数是一定的,随着元素的不断插入,每个桶中元素的个数不断增多,极端情况下,可能会导致一个桶中链表节点非常多,会影响的哈希表的性能,因此在一定条件下需要对哈希表进行增容,那该条件怎么确认呢?开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增容。问题来了,新闻客户端推荐系统如何实现推送去重的?对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功。

Caihua的博客 1176

SAPGUI 与 ADT 的时代分野:在多云架构下,谁还能代表现代 SAP 开发

摘要(149字) SAP开发工具正经历代际更迭:SAPGUI基于专有协议(NI/DIAG)的厚客户端架构难以适配多云环境,而ADT(ABAP Development Tools)通过HTTP(S)协议和Eclipse生态成为ABAP Cloud/RAP开发的唯一入口。关键差异体现在:ADT支持CDS、行为定义等云原生对象建模,天然对齐BTP的零信任网络;集成ATC、Git等DevOps工具链;而SAPGUI无法创建RAP核心对象,在跨平台、自动化方面存在硬限制。官方文档明确将ADT作为Clean Core战

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 389

C/C++语言进阶-哈希表 <哈希表完全解析:从算法原理到C语言实战,一次彻底搞懂Hash!>

哈希表完全解析:从算法原理到C语言实战,一次彻底搞懂Hash! 内容较多,但非常全面,内容涵盖了哈希表从算法原理 → 代码实现 → 实际应用 → 面试考点的全流程,非常适合做学习资料或面试复盘。 本文将带你从零开始,深入理解哈希算法的原理与实现,掌握链地址法、开放寻址法、负载控制与扩容机制,并通过完整C语言示例代码构建自己的哈希库。 无论你是准备面试、写底层代码,还是做嵌入式内存优化,这都是一篇你读完就能上手实战的 Hash 全指南。

csyys1的博客 657

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

c++进阶——哈希

1. unordered系列关联式容器2. 底层结构3. 模拟实现4.哈希的应用5.海量数据处理面试题。

2201_75453663的博客 1178

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C++进阶——哈希

哈希结构是一种可以不经过任何比较,一次直接从表中得到要搜索的元素的数据结构。如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射关系,那么在查找时通过该函数可以很快找到该元素。通过哈希构造的方式称为为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(Hash Table)或散列表。

Bit_qnw的博客 1021

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++进阶 | [5] 哈希

摘要:概念——哈希、哈希表、哈希碰撞、负载因子;实现哈希表(插入删除查找)(开放定址法)

fantastic_13_7的博客 878

【C++进阶】hash表的封装

通过对哈希表的封装,我们不仅提升了代码的可读性和复用性,还通过合理设计哈希函数和处理冲突机制,优化了哈希表的性能。封装让我们可以将底层的细节隐藏起来,提供一个简洁高效的接口,便于后续在项目中的使用。在实际开发中,理解负载因子、再散列等概念,并针对具体场景合理调整这些参数,能够确保哈希表在性能和内存占用上的平衡。掌握了这些知识后,相信你能够更加自信地在复杂应用中使用哈希表。

2301_79969994的博客 1929

c++进阶——哈希表的实现

本文介绍了哈希表的基本概念及其实现方式。哈希表通过哈希函数将关键字映射到存储位置,以实现快速查找和插入。C++ STL库中的unordered_set和unordered_map基于哈希表实现,与基于红黑树的set和map相比,哈希表在搜索和插入效率上更高,但无序。哈希表的关键在于将关键字转化为整型并通过哈希函数映射到表中,这可能导致哈希冲突。解决冲突的常用方法有开放定址法和链地址法。开放定址法通过线性探测等方式解决冲突,而链地址法则通过链表或红黑树处理冲突。哈希函数的选取对哈希表的性能至关重要,常见的哈希

2301_79705195的博客 1118

C++进阶--哈希

哈希(Hash)是一种常见的密码学技术和数据结构,。。唯一性固定长度高效性不可逆性。

m0_74068921的博客 2859
上一篇: C++进阶 —— 红黑树
下一篇: C++进阶 —— auto/decltype(C++11新特性)
挨代码
博客等级 码龄5年 1696粉丝 384原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值