哈希表(散列表)

本文介绍了哈希表(散列表)这一数据结构,详细阐述了其快速插入和查找的特性,时间复杂度为O(1)。讨论了哈希函数设计与冲突处理的重要性,包括直接定址法、除留余数法和平方取中法等设计方法,以及开放寻址法和拉链法两种冲突解决策略。并提供了一个模拟散列表操作的编程实例,展示了哈希表在实际问题中的应用。
摘要由CSDN通过智能技术生成

散列表(哈希表)

哈希表也叫散列表,哈希表是一种数据结构,它提供了快速的插入操作和查找操作,无论哈希表总中有多少条数据,插入和查找的时间复杂度都是为O(1),因为哈希表的查找速度非常快,所以在很多程序中都有使用哈希表,例如拼音检查器。这里先说一下哈希(hash)表的定义:哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过关键码映射的位置去寻找存放值的地方。

将关键码映射为散列表中适当存储位置的函数称为散列函数(哈希函数),所得的存储位置称为散列地址(hash address)。

由于hash的特性,导致有可能存在两个不相同的元素a和b要存放到同一位置,这种现象叫做冲突,也称碰撞,a和b相对于hash函数称作同义词。

要考虑的问题

1.hash函数的设计。设计简单,均匀,随机,利用率高的hash函数
2.冲突 的处理。如何采取合理方式解决冲突。

设计散列函数

下面介绍三种常见的散列函数设计:
直接定址法
直接定址法的散列函数是关键码的线性函数,
H ( k e y ) = a ∗ k e y + b H(key)=a*key+b H(key)=akey+b
特点:不会产生冲突,适用于事先知道关键码的分布,关键码集合不是很大且连续性好的情况。
除留余数法
选择某个适当的正整数p,以关键码除以p的余数作为散列地址:
H ( k e y ) = ( k e y ) m o d ( p ) H(key)=(key)mod(p) H(key)=(key)mod(p)
这个方法关键在于选出合适的p,否则容易出现冲突。一般情况下,选择p为小于或等于表长的最大素数或不包含小于20 质因子 的合数。
平方取中法
对关键码平方后,取中间的若干位
适用于不知道关键码的分布,且关键码位数不是很大 的情况。

处理冲突的方法

开放寻址法
如果由关键码得到的散列地址发生了冲突,通过 H ( k e y ) = ( H ( k e y ) + d i ) m o d ( m ) H(key)=(H(key)+d_i) mod (m) H(key)=(H(key)+di)mod(m)寻找下一个空的散列地址。
拉链法
将所有散列地址相同的记录存储在一个单链表中,散列表中存储的是所有同义词子表的头指针。

题目链接:模拟散列表

维护一个集合,支持如下几种操作:

I x,插入一个数 x;
Q x,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果。

输入格式

第一行包含整数 N,表示操作数量。

接下来 N 行,每行包含一个操作指令,操作指令为 I x,Q x 中的一种。

输出格式

对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No。

每个结果占一行。
数据范围

1≤N≤105
−109≤x≤109

输入样例:

5
I 1
I 2
I 3
Q 2
Q 5

输出样例:

Yes
No

#include<iostream>
#include<cstring>
using namespace std;
const int N=100003;
int x,t;
int e[N],h[N],ne[N],idx;
void insert(int x)
{
    int u=(x%N+N)%N;
    e[idx]=x;
    ne[idx]=h[u];
    h[u]=idx++;
}

bool quary(int x)
{
    int u=(x%N+N)%N;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        if(e[i]==x)return true;
    }
    return false;
}

int main()
{
    char op[2];
    memset(h,-1,4*N);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s%d",op,&x);
        if(*op=='I')insert(x);
        else printf(quary(x)?"Yes\n":"No\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值