其他分享
首页 > 其他分享> > 哈希表(散列表)

哈希表(散列表)

作者:互联网

散列表(哈希表)

哈希表也叫散列表,哈希表是一种数据结构,它提供了快速的插入操作和查找操作,无论哈希表总中有多少条数据,插入和查找的时间复杂度都是为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)=a∗key+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");
    }
}

标签:hash,哈希,关键码,int,列表,key,散列
来源: https://blog.csdn.net/qq_52841268/article/details/120095581