考研算法第22天: 模拟散列表 【哈希,解决冲突:链表法】

HASH算法

优秀的hash算法一定是将值映射的比较均匀。因为这样的话利于可以避免冲突。

先来说说常见的hash算法:

 

1.除余法 

hash值就是x%M(M一般取质数);

为啥是质数?因为举个例子,因为质数是除了1和自身之外没法整除的数,取用反证法

如果我们取用奇数作为M,那么如果是偶数取模的话,那么一定就是奇数,如果是奇数的话那么一定是偶数,那么这样的话冲突一定很多。对于拉链法,也需要比较均匀,因为查找的时候如果一个节点的链表有很多个节点的话,那么就会造成查找的时间增加。

2.乘余取整法

没听太懂

3.平方取中法

x的平方然后取其平方中间的一段二进制然后转为10进制作为hash值。

4.基数转换法

转换成其它的机制,然后取中间一段转为10进制作为hash值。

5.ELFHASH

算法太难,能理解它是一个字符串转换的函数就行。

HASH算法解决冲突的方法

1.拉链法

2.开发寻址法

算法详解

拉链法:

#include <iostream>

#include <cstring>

using namespace std;


//h存放多个字链表的头指针
int h[N];
//存放每个值,并且会被拆成多个数组
int e[N];
//存放每个链表的元素的下一个元素的位置(e数组的下标)
int ne[N];
//和单链表一样是用来存正在操作的指针
int idx;
//插入元素 他输入的的范围是-N~N 但是你需要用只有大小为N的散列表去存放这些值,所以就要
//hash将数据结构弄得和java的hashmap一样,
void add(int t,int x){
    e[idx] = x;
    ne[idx] = h[t];
    h[t] = idx++;
}

bool find(int x){
    // cout<<-1;
    int t = ((x%N)+N)%N;
    for(int i=h[t];i!=-1;i=ne[i]){
        if(e[i]==x)return true;
    }
    return false;
}

void insert(int x){
    if(find(x)) return;
    int t = ((x%N)+N)%N;
    add(t,x);
}


int main(){
    int n;
    int a;
    char op;
    cin>>n;
    memset(ne,-1,sizeof ne);
    memset(h,-1,sizeof h);
    memset(e,-1,sizeof e);
    while(n--){
        cin>>op;
        if(op=='I'){
            cin>>a;
            insert(a);
        }else{
            cin>>a;
            // cout<<-1;
            if(find(a)){
                cout<<"Yes"<<endl;
            }else{
                cout<<"No"<<endl;
            }
        }     
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值