哈希函数取模一般为大于数组范围的第一个质数
如果题目给了100000范围的数据,不妨将const int N=100003;
也就是后面数组都多开大一点,且刚好为大于范围的第一个质数
这刚好能保证存储的数据下标不会越界,而且可以直接用N进行取模操作,不用另外搞什么变量K之类的。
如果对−1e9≤x≤1e9范围内的数据映射哈希值要考虑直接x%N可能为负数,而数组下标不能为负。
补充: a%b=c,c的符号只取决于第一个a的符号,与b的符号没关系,而且C++是向0取整的。
我们设置哈希函数时可以通过
(x%N+N)%N
来避免得到负的下标
总结一下:我们可以采取邻接表的写法来解决哈希冲突,首先通过(x%N+N)%N
映射到h[]中的一个位置,然后插入以这个位置为头节点的邻接表中,不论是存储还是查询都非常方便,也能很好的解决冲突。
下面附上y总的模板,个人推荐邻接表的写法,开放寻址法用的少容易出错。。
(1) 拉链法
int h[N], e[N], ne[N], idx;
// 向哈希表中插入一个数
void insert(int x)
{
int k = (x % N + N) % N;
e[idx] = x;
ne[idx] = h[k];
h[k] = idx ++ ;
}
// 在哈希表中查询某个数是否存在
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;
return false;
}
(2) 开放寻址法
int h[N];
// 如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置
int find(int x)
{
int t = (x % N + N) % N;
while (h[t] != null && h[t] != x)
{
t ++ ;
if (t == N) t = 0;
}
return t;
}