手写哈希表 & 既好写又快的 pbds 哈希表

手写哈希表 & 既好写又快的 pbds 哈希表

例题:P11615 【模板】哈希表 - 洛谷

手写哈希表

const int M=1e7+19;
struct _hash {
	ull key[M],val[M],mix;
	_hash() {
		mix=mt19937_64(chrono::steady_clock::now().time_since_epoch().count())();
	}
	ull& operator[](ull x) {
		x^=mix;
		ull y=x%M;
		while(key[y]&&key[y]!=x) {
			++y;
			if(y==M) y=0;
		}
		key[y]=x;
		return val[y];
	}
}hs;

不想手写哈希表怎么办?

unordered_map

unordered_map 不能自己传入哈希函数可以传入哈希函数,很容易被卡。

gp_hash_table

gp_hash_table 是探查法,cc_hash_table 是拉链法,前者效率更好。

它在 pbds 里,直接用会使用默认的哈希函数,也会被卡。接下来将怎么自定义哈希函数,以及怎么使用。

头文件 & 命名空间

#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>

也可以使用 <bits/extc++.h>

命名空间:__gnu_pbds

定义 & 使用

__gnu_pbds::gp_hash_table<ull,ull,_Hash> Map;

类似 std::unordered_map 的定义,前两个分别是键和值,最后是可选的哈希函数。

使用方法同 std::unordered_map,内部元素是无序的,也可以使用迭代器遍历。

哈希函数

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
struct _Hash {
	ull operator()(ull x)const{
		static const ull s1=rng(),s2=rng(),s3=rng();
		x+=s1;
		(x^=x>>33)*=s2;
		(x^=x>>30)*=s3;
		return x;
	}
};

定义一个类,重载 () 运算符,注意函数一定要用 const 修饰不然会报错。

函数内用 static const 定义三个随机值,它们是静态局部变量,这意味着它们在初次初始化后将保留它们的值,并在之后都不会再次初始化。

定义哈希表时把类名传入哈希表的第三个参数即可。

posted @ 2025-08-14 22:40  dengchengyu  阅读(96)  评论(0)    收藏  举报