将-10^9-10^9的数指向0-10^5的数 称为哈希函数
一般情况 x mod 10^5
但是这个简单方法可能将两个数映射到一个数而冲突
1.拉链法 如果两条链是冲突的 那么在同一位置用一个链将两个数都存下来
2.开放寻址法 (感觉这个简单一点)
[拉链法模拟散列表] [c++]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include<bits/stdc++.h> using namespace std; const int N=100003; //模的数是质数且离2的n次方远 冲突概率最小 int h[N];//"给拉链开槽" int e[N],ne[N],idx;
void insert(int x) { int k= (x%N+N)%N; //c++里负数mod整数是负数 modN再+N再modN就是正的 k就是哈希值 e[idx]=k; //先把新点值赋好 ne[idx]=h[k]; //这一点的next指针指向槽里的下一个点 h[k]=idx;//再让h[k]指向新点 idx++; //插入操作 让新的点的next指针为h[k],让h[k]再指向这个新点 }
bool find(int x) { int k=(x%N+N)%N; for(int i=h[k];i!=-1;i=ne[i]) if(e[i]=x) return true; else return false; } int main() { int n; cin>>n; memset(h,-1,sizeof h); //清空 while(n--) { char op[2]; int x; cin>>op>>x;
if(*op=='I') insert(x); else { if(find(x)) cout<<"Yes"<<endl; else cout<<"No"<<endl; } } }
|
开放寻址法不用开链表 但是一维数组开的长度要是题目的三倍
添加操作:先算k 从数组中第k个开始找 找到第一个空的就填
查找操作: 也是从第k位开始找 如果有数 对比是不是k 不是就找下一个 如果找到空就不存在
删除(不常用): 查找到后bool标记
[开放寻址法模拟散列表] [c++]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include<bits/stdc++.h> using namespace std; const int N=200003; //需要开两到三倍 const int null=0x3f3f3f; //在数据之外的一个数 表示此位置无数 int h[N]; int e[N],ne[N],idx;
bool find(int x) { int k=(x%N+N)%N; while(h[k]!=null&&h[k]!=x) //如果这个位置有数 且不等于x 就下个位置 { k++; if(k==N) k=0; //如果直到最后也没找到 从0开始循环 } return k; //如果存在返回下标 不然返回应该存储的位置的下标 //所以如果h[k]=null 那么就说明没有这个数
} int main() { int n; cin>>n; memset(h,0x3f,sizeof h); //全初始化为null while(n--) { char op[2]; int x; cin>>op>>x;
if(*op=='I') //插入 { int k=find(x); h[k]=x; } else //查找 { if(h[k]!=null) cout<<"Yes"; else cout<<"No"; //如果h[k]是null 所以k不存在 } } }
|