算法笔记——散列定义及整型散列

本文深入探讨散列算法在处理大量数据查找问题中的应用,对比直接遍历与使用散列表的方法,介绍散列函数的设计,包括直接定址法、平方取中法及除留余数法,并讨论解决哈希冲突的策略。

散列的定义与整数散列

散列是常用的算法思想之一,在很多程序中都能见到。
经典问题:给出N个正整数,再给出M个正整数,问这M个数中的每个数分别在N个数中是否出现过。
最直观的思路:对每个欲查询的正整数x,遍历所有N个数,看是否有一个数与x相等。这种做法的时间复杂度为O(MN),当M和N很大时,显然这种方法是不可取!

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int N,M;
    cin>>N>>M;
    int a[N],b[M];
    for(int i=0;i<N;i++)
        cin>>a[i];
        for(int j=0;j<M;j++)
            cin>>b[j];
        for(int i=0;i<N;i++)
        for(int j=0;j<M;j++)//时间复杂度为O(NM)
        if(b[j]==a[i])
            cout<<"true"<<endl;
        else
            cout<<"false"<<endl;
        return 0;
}

这时候我们不妨用空间来换时间,即设定一个bool型数组hashTable[100010],其中hashTable[x]==true表示正整数x在N个正整数中出现过,而hashTable[x]==false则表示整数x在N个整数没有出现过。这样就可以在一开始读入N个正整数时就能进行预处理,即当读入的数为x,令hashTable[x]=true,对M个书进行查询时,就那个根据hashTable数组判断出每个数是否出现过,这中算法的时件复杂度为O(N+M);

#include<bits/stdc++.h>
using namespace std;
int main()
{
    bool hashTable[100010]={false};//初始化未出现
    int N,M,x;
    cin>>N>>M;
    for(int i=0;i<N;i++) {
        cin>>x;
        hashTable[x]=true;
    }
    for(int j=0;j<M;j++) {
        cin>>x;
    if(hashTable[x]==true)//时间复杂度为O(N+M)
        cout<<"true"<<endl;
    else
        cout<<"false"<<endl;
    }
    return 0;
}

经典问题:M个欲查询的数中每个数在N个数中出现的次数。
此时bool hashTable[100010]改为int hashTable[100010]

#include<bits/stdc++.h>
using namespace std;
#define Max 100010
int  main()
{
    int hashTable[Max]={0};//初始化次数为0
    int N,M,x;
    cin>>N>>M;
    for(int i=0;i<N;i++) {
        cin>>x;
    hashTable[x]++;
    }
    for(int j=0;j<M;j++) {
        cin>>x;
        cout<<hashTable[x]<<endl;
    }
    return 0;
}

这种方法固然好用,但数组下标数过大时,超过10^9时,此时就会出现错误,那这是该如何解决呢?
*
解决方法就是散列(hash),散列(hash)就是将元素通过一个函数转化为整数,使得该整数可以尽量唯一的代表这个元素。
这个转换函数就叫做散列函数H,元素转换为key,则转换后就是H(key)。
当key是整数时常用方法:直接定址法,平方取中法,除留余数法。

上面的程序用到的就是直接定址法:H(key)=key
平方取中法:取key的平方的中间若干位作为hash值
除留取余法:H(key)=key%mod

把一个很大的数转化为了一个不超过mod的数,把这个数作为数组的下标(表长TSize不能小于mod),mod一般取素数,这样H(key)就能尽可能覆盖[0,mod)范围内的每一个数了,因此为了方便起见,TSize是一个素数,而mod直接取成与TSize相等。

这个时候就会出现一种情况,就是key1,key2,它们的数组下标是一样的,key1已经占用那个位置了,key2就不能再用了。这种情况成为冲突

解决方法

  1. 线性探查法(Linear Probing)
  2. 平方探查法(Quadratic probing)
  3. 链地址法(拉链法)
    具体内容请见: 解决哈希冲突的三种方法.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无所畏惧的man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值