哈希表Hash:概念与基本操作

什么是Hash

Hash就像是一个桶排,那只不过是把各个元素的数值当做下标进行存储.其最常用的用途就是用来判重.但是,如何对字符串进行判重,不可能一个一个往前超,若n上万则显然不可行.我们可以选择进行Hash,将每一个字符串或者大数字进行一定的操作即可进行.


对大整数类型进行Hash

取模法

对于每一个大整数进行取模,即除以一个大质数(例如107,10007,1000007,1-奇数个0-7),这样就作为数组的下标进行存储了.

为什么要对一个大整数取模

emmmmmm......经众多数学家证明重复的几率较小

万一实在有不可避免的误差/出题人卡你怎么办

有两种方法:

1.线性探测开拓地址法

2.拉链法


对字符串进行Hash

对字符串,我们可以选择按权展开法进行实现.

例如:对于字符abc,我们可以转换成26进制,即:126^0+226^1+3*26^2,很好理解吧

例如,对于字符串3gT,我们可以转换成某个质数进制即可.

但是,不要忘了,在按权展开的时候需要对一个大整数取模

如何避免字符串Hash的误差

同样:

1.线性探测开拓地址法

2.拉链法


线性探测开拓地址法

若hash[k]已经被填入,则尝试填写hash[k+1],hash[k+2]....等数组.最后在查找的时候也逐一查找即可.但毕竟查找不方便,个人更加偏向于拉链发


拉链法

跟据每一个数值的下标扩充一个链表,每次在链表上逐一查找即可.

为了方便实现,我们可以选用STL中的vector(即动态数组或不定长数组)来代替链表,这样也十分容易实现.


整数Hash实例:不重复数字【JLOI2011】

题目描述

给出N个数,要求把其中重复的去掉,只保留第一次出现的数。

例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4。

输入输出格式

输入格式:

输入第一行为正整数T,表示有T组数据。

接下来每组数据包括两行,第一行为正整数N,表示有N个数。第二行为要去重的N个正整数。

输出格式:

对于每组数据,输出一行,为去重后剩下的数字,数字之间用一个空格隔开。

原题体面戳这里

对于这道题,直接除以大质数1000007即可.(数据水,没有判重AC了)

代码如下:

#include<bits/stdc++.h>
using namespace std;
int Hash[1000009];
inline int h(int x){return x%1000007;}
void work()
{
    memset(Hash,0,sizeof(Hash));
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        if (Hash[h(x)]==1) continue;
    }
    printf("\n");
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--) work();
}

字符串Hash

原题题面戳这里

这道题,我们采用301当做位权;我们采用大质数1000007来取模;用拉链法来处理重复;同时用vector来代替链表;代码实现难度不大.

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,ans=0;
int const M=1000007;//最后取模
vector<string>Link[1000009];
inline int hash(string x)
{
    int sum=0;int w=307;//累加的值,位权
    for (int i=0;i<x.length();i++)
        sum=(sum*w+int(x[i]))%M;
    return sum;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        string s;cin>>s;
        int k=hash(s),flag=1;
        for (int j=0;j<Link[k].size();j++)
            if (s==Link[k][j]) flag=0;
        if (flag==1)
        {
            Link[k].push_back(s);
            ans++;
        }
    }
    cout<<ans;
    return 0;
}

原文地址:https://www.cnblogs.com/pigzhouyb/p/10119826.html

时间: 2024-10-08 20:49:40

哈希表Hash:概念与基本操作的相关文章

哈希表Hash

大家都学过数据结构: 内存里面为了更好的管理对象,通常采用链表或者数据以及Hash表来存储数据. 数据存储 一下是数据存储到计算机的两种模式 线性的存储:数组---寻址方便,更新不好(连续的) 链式的存储: 链表----寻址不方便,更新方便.(不连续的) 为了提高检索的速度,我们可以采取Hash机制,key采取数据存储,方便寻址,其次我们可以利用链表方便更新数据的具体的值. 哈希表Hash,布布扣,bubuko.com

哈希表(Hash table)(1)

哈希表(Hash table)经常被用来做字典(dictionary),或称符号表(symbol-table) 直接存取表(Direct-access table): ? 直接存取表(Direct-access table)的基本思想是:如果key的范围为0~m-1而且所有key都不相同, 那么可以设计一个数组T[0..m-1],让T[k]存放key为k的元素, 否则为空(NIL) ? 显然, 所有操作都是O(1)的 ? 问题:key的范围可能很大! 64位整数有18,446,744,073,7

PHP关联数组与哈希表(hash table) 不指定

PHP中有一种数据类型非常重要,它就是关联数组,又称为哈希表(hash table),是一种非常好用的数据结构. 在程序中,我们可能会遇到需要消重的问题,举一个最简单的模型: 有一份用户名列表,存储了 10000 个用户名,没有重复项: 还有一份黑名单列表,存储了 2000 个用户名,格式与用户名列表相同: 现在需要从用户名列表中删除处在黑名单里的用户名,要求用尽量快的时间处理. 这个问题是一个小规模的处理量,如果实际一点,2 个表都可能很大,比如有 2 亿条记录. 我最开始想到的方法,就是做一

什么叫哈希表(Hash Table)

散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构中,有个时间算法复杂度O(n)的概念来衡量某种算法在时间效率上的优劣.哈希表的理想算法复杂度为O(1),也就是说利用哈希表查找某个值,系统所使用的时间在理想情况下为定值,这就是它的优势.那么哈希表是如何做到这一点的呢? - 我们定义一个很大的有序数组,想要得到位于该数组第n个位置的值,它的算法复杂度

哈希表 hash table

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数. 首先问题规模确定,例如5台服务器怎么把数据散落在5台上面呢,就用到了hash算法

(四)Redis哈希表Hash操作

Hash的全部操作如下: hset key field value # 将哈希表key中的字段field的值设为value hget key field # 返回哈希表key中的字段field的值value hmset key field1 value1 field2 value2 ... # 将多个field-value对设置到哈希表key中 hmget key field1 field2 ... # 返回哈希表key中字段field1,field2,...的值 hgetall key # 返

[BS]散列表 哈希表 Hash table

<第五章> 散 列 散列表的实现常常叫做散列(hashing).散列是一种用于以常数平均时间执行插入.删除和查找的技术. 关于散列有一个很重要的概念:散列函数.散列函数是散列的关键处之一,散列函数又是基于映射机制的一种对应关系(一般是多对一的关系). 这章可以分为5个部分:一般想法,散列函数,分离链接法,开放定址法(可分为线性探测.平方探测.双散列).再散列.可扩散列. 本文只写到前四节.即:一般想法,散列函数,分离链接法,开放定址法(可分为线性探测.平方探测.双散列)() 第五章第一节:一般

Redis常用操作-------Hash(哈希表)

1.HDEL key field [field ...] 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略. 在Redis2.4以下的版本里, HDEL 每次只能删除单个域,如果你需要在一个原子时间内删除多个域,请将命令包含在 MULTI / EXEC块内. 可用版本: >= 2.0.0 时间复杂度: O(N), N 为要删除的域的数量. 返回值: 被成功移除的域的数量,不包括被忽略的域. # 测试数据 redis> HGETALL abbr 1) "a" 2)

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

一.哈希表 1.概念 哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度.这个映射函数就做散列函数,存放记录的数组叫做散列表. 2.散列存储的基本思路 以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中. 3.哈希表查找的时间复杂度 哈希表存储的是键值对,其查找的时间复杂度与元素数