哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数,存放记录的数组叫做哈希表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
哈希表的存储结构一般有两种,一个是开放寻址法,一个是拉链法。这两种存储结构在处理冲突上效果比较好。
哈希表用途哈希表可以把一个比较庞大的空间映射到一个比较小的空间,一般情况下是映射到0~N,N一般是1e5,1e6的大小。比较常见的一种场景是把0-1e9的这些数映射到0-1e5。我们这里主要针对哈希表在算法上的用途,然后举一个案例来详细说明,不会讲解哈希表在数据结构上的实现。
哈希表冲突上面说了什么是哈希函数,比如值域在-1e9~1e9的数,通过一个函数比如H(x)可以把这个值域中的数映射到0~1e5的之间的一个数。这个H(x)就是哈希函数。
哈希函数一般可以写成x mod 1e5这样的形式,这样对1e5取模后的范围一定在0~1e5,但是这样写可能会有冲突,可能有两个不一样的数映射到一个数,因为把一个庞大的空间映射到小空间肯定是映射不完的,一定会有冲突。所以我们要处理冲突,按照不同的处理方式我们把哈希表分成开放寻址发和拉链法。
拉链法我们开一个一维数组来存储所有数的哈希值,比如我们映射到0~1e5的空间,那么我们就创建一个1e5大小的数组。拉链法是如何处理冲突的呢,我们给这个数组的上的每个位置都拉一条链,用来存储当前这个位置已经有的所有的数
我们举个栗子,假设H(x)是哈希函数,我们给每一个位置都拉一条链,如果H(13)=4,这样就把13映射到了4这个位置,我们把13放到4位置的链上去,如果H(34)=4,我们也把34放到4位置的链上去,如图所示。就是说两个数是冲突的,我们就用一个链把他们都存下来。
哈希表是一个期望算法,每个链可以看做一个常数,它的时间复杂度可以看做O(1)
这里的链我们用邻接表实现
开放寻址法处理冲突的思路是什么呢,首先它是只开了一个一维数组,没有开一个链表。但是这个一维数组的长度要开到题目要求的两到三倍。它处理冲突的思路是如果某个数的哈希值这个位置被占了那么就去下一个位置,一直找到空的位置,这样就要给每一个哈希值留一定的空间来放置他们,这也是为什么开放寻址法要开这么大数组的原因。
下面我们用一个例题,分别用拉链法和开放寻址法解决
例题维护一个集合,支持如下几种操作:
I x
,插入一个数 x;Q x
,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果。
输入格式
第一行包含整数 N,表示操作数量。
接下来 N 行,每行包含一个操作指令,操作指令为 I x
,Q x
中的一种。
输出格式
对于每个询问指令 Q x
,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes
,否则输出 No
。
每个结果占一行。
数据范围
1≤N≤1e5 −1e9≤x≤1e9
输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No
拉链法
#include
#include
#include
using namespace std;
const int N=1e5+10;
int h[N];//映射到的槽
int e[N],ne[N],idx;//邻接表模板
//插入一个数
void insert(int x)
{
int k=abs(x%N);
//邻接表模板,头插法
e[idx]=x;
ne[idx]=h[k];
h[k]=idx++;
}
//查询一个数
bool find(int x)
{
int k=abs(x%N);
for(int i=h[k];i!=-1;i=ne[i])
{
if(x==e[i])
return true;
}
return false;
}
int main()
{
int n;
cin>>n;
//初始化槽,每个槽都是一个头结点
memset(h,-1,sizeof h);
for(int i=0;i>op>>x;
if(op=='I')
insert(x);
else
{
if(find(x)) coutx;
if(op=='I')
{
m[x]++;
}
else
{
if(m[x]>0)
cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?