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;
}