算法未动 粮草先行(基础篇四---散列表/哈希表)

本文深入探讨了散列表(哈希表)的工作原理,包括其定义、作用、散列函数设计,以及解决冲突的策略。介绍了直接定址法、除留余数法和平方取中法等散列函数构建方法,并讨论了开放定址法和链地址法处理冲突的技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

散列表

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
来源:维基百科

4.1定义

作用:不进行比较就能一步到位地查找到指定的元素
将在结构的元素存储位置和元素值之间建立一种映射关系
称上面这种关系为哈希函数f,称元素值为关键字
关系f的作用就是使每一个关键字与表中的一个元素的存储位置相对应

4.2散列函数

将关键字映射为散列表中适当位置的函数
通过散列函数计算出的元素的存储地址称为散列地址
构建散列表的关键就是设计一个好的散列函数
什么是好的散列函数
需要具有两个特点:冲突少+均匀
冲突
是指两个不同的关键字经过散列函数映射到了同一个地址(value1!=value2 but f(value1)=f(value2)) 是我们在建造散列函数需要避免的情况(尽量)
均匀
如果对关键字集合中的任何一个关键字 通过散列函数映射到地址集合的任何一个地址的概率是相等的------->这个函数是均匀的

4.2.1直接定址法

取关键字的某个线性函数为散列函数

f(v)=a*v+b (a,b为常数)
比较简单的设计散列函数的方法,一般情况用已知的关键字集合,且关键字集合不大且连续性好
4.2.2除留余数法
F(v)=v mod p (p为常数)
一般p的值取小于或等于表长的最小素数

不需要已知关键字集合
比较常用的构造散列函数

4.2.3平方取中法

将关键字平方后,根据散列表的设计大小,取平方结果的中间若干位作为散列地址,较为常用
例如 如果散列地址取2位,则345的散列地址为:

345^2=119025 取90为其散列地址

4.3基于散列的查找

散列表在查找的时候有个很大的缺点——冲突
如何处理冲突

4.3.1开放定址法

在数据存取的时候 发生冲突后 就寻找下一个空白的散列地址

F_i = (f(v) + d_i )mod n i=1,2,…,v (v<=n-1)
n为散列表长度,f(v)为散列函数 d_i为增量序列 增量序列的确定方法: 1.线性探测法:从发生冲突的位置往后遍历 直到空白地址 存放 2.二次探测再散列:d_i = 1, -1 2^2, -2^2, 3^2……v^2,-v^2 (v<=n/2) 3.伪随机探测:d_i为一个伪随机数序列
4.3.2链地址法

将所有具有相同散列地址的不同关键字存放在一个单链表中(同义词子表),散列表中存放在一个单链表中

4.3.3公共溢出区法

将散列表分为基本表和溢出表两部分,两部分大小相同
将发生冲突的关键字存放在溢出表
查找时,对给定的关键字计算散列表地址,然后与基本表中相应位置的元素进行比较 如果一致查找成功 如果不一致 到溢出表中查找

template<typename DataType>class HashTable
{
public:
	HashTable(int size)
	{
		maxSize = size;
		count = 0;
		elements = new DataType[size];
		if(elements==NULL)
			exit(1);
		for (int i=0;i<size;i++)
			elements[i]=NULL;
		}
		~HashTable()
		{
			delete elements;
		}
		//散列函数——除留余数法 p为根据关键字集合设定的值
		int hash(DataType value, int p)
		{
			return value%p;
		}
		//查找函数, 返回所查找元素的地址
		int searchHash(DataType value)
		{
			int p = hash(value);
			if (elements[p]==value)
				return p;
			int rp=(p+1)%maxSize;
			while(rp!=p)
			{
				if(elements[rp]==value)
					return rp;
				if(elements[rp]==NULL)
					break;
				rp=(rp+1)%maxSize;
			}
			if(rp==p)
				return -1;
			else
			{
				elements[rp]=value;
				return rp;
			}
		}
	private:
		int maxSize;
		int count;
		DataType *elements;
	};

参考书籍《妙趣横生的算法(C++语言实现)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值