手写哈希表

众所周知,STL 内置的 unodered_map 已经废了。

取而代之的是 __gnu_pbds::cc(gp)_hash_table

不过这两个也跑的不如手写的快,参考了 耳朵龙_ 的哈希函数,在 born_to_sun 语法指导下,手写了一个 unordered_map。

目前来看效率和 耳朵龙_ 的差不多,欢迎测速来卡

不过适用性上加强了,支持了结构体的插入。

template<unsigned Sz,unsigned M,typename T1,typename T2,ULL (*get)(T1)> struct UMap
{
	//Sz: the number of times opeator[] is called
	//M: number of buckets
	//T1: key type(any type you want,note that you should ensure "==" is defined)
	//T2: value type(any type you want)
	//get(T1): the function that trans "T1" into "ULL" 
	int h[M],len,ne[Sz+1];
    struct Data
	{
        T1 key;
		T2 val;
    }e[Sz+1];
    unsigned Hash(ULL x)const
	{
		static const ULL t=
		std::chrono::steady_clock::now().time_since_epoch().count();
		x+=t+0x9e3779b97f4a7c15;
		x=(x^(x>>30))*0xbf58476d1ce4e5b9;
		x=(x^(x>>27))*0x94d049bb133111eb;
		return(x^(x>>31))%M;
	}
    inline int find(const T1 &v,int type=0)
    {
    	int u=Hash(get(v));
    	for(int i=h[u];i;i=ne[i]) if(e[i].key==v) return i;
		if(type) ++len,e[len].key=v,ne[len]=h[u],h[u]=len;
		return len;
	}
	inline T2 &operator[](const T1 &v)
	{
		int i=find(v,1);
		return e[i].val;
	}
	inline bool count(const T1 &v)
	{
		return find(v)!=0;
	}
	inline int size()
	{
		return len;
	}
	Data *begin(){return e+1;}
    Data *end(){return e+len+1;}
};
食用例子
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
typedef unsigned long long ULL;
const int N=2e7+5,Inf=1e9,mod=1e8+7;
mt19937 rnd(time(0));
int n;

inline bool operator==(PII &A,PII &B)
{
	return (A.x==B.x && A.y==B.y);
}

bool St;
template<unsigned Sz,unsigned M,typename T1,typename T2,ULL (*get)(T1)> struct UMap
{
	//Sz: the number of times opeator[] is called
	//M: number of buckets
	//T1: key type(any type you want,note that you should ensure "==" is defined)
	//T2: value type(any type you want)
	//get(T1): the function that trans "T1" into "ULL" 
	int h[M],len,ne[Sz+1];
    struct Data
	{
        T1 key;
		T2 val;
    }e[Sz+1];
    unsigned Hash(ULL x)const
	{
		static const ULL t=
		std::chrono::steady_clock::now().time_since_epoch().count();
		x+=t+0x9e3779b97f4a7c15;
		x=(x^(x>>30))*0xbf58476d1ce4e5b9;
		x=(x^(x>>27))*0x94d049bb133111eb;
		return(x^(x>>31))%M;
	}
    inline int find(const T1 &v,int type=0)
    {
    	int u=Hash(get(v));
    	for(int i=h[u];i;i=ne[i]) if(e[i].key==v) return i;
		if(type) ++len,e[len].key=v,ne[len]=h[u],h[u]=len;
		return len;
	}
	inline T2 &operator[](const T1 &v)
	{
		int i=find(v,1);
		return e[i].val;
	}
	inline bool count(const T1 &v)
	{
		return find(v)!=0;
	}
	inline int size()
	{
		return len;
	}
	Data *begin(){return e+1;}
    Data *end(){return e+len+1;}
};
inline ULL Hash(PII it)
{
	return (ULL)(it.x+Inf)*Inf+(it.y+Inf);
} 
UMap<N,mod,PII,int,Hash> Map;
bool Ed;

int Rand(int l,int r)
{
	return rnd()%(r-l+1)+l;
}

signed main()
{
	cerr<<(&St-&Ed)/1024.0/1024<<"\n";
	
	double st=clock();
	
	n=20000000;

	for(int i=1;i<=n;i++)
	{
		int x=Rand(-Inf,Inf),y=Rand(-Inf,Inf),z=i;
		Map[{x,y}]=z;
	}
	
	LL res=0;
	for(auto [it,w]:Map) res+=w;
	
	cout<<Map.size()<<" "<<res<<"\n";
	double ed=clock();
	
	cerr<<(ed-st)/CLOCKS_PER_SEC<<"\n"; 
	
	return 0;
}
posted @ 2025-05-12 15:43  Richard_whr  阅读(50)  评论(0)    收藏  举报