几种比较好的哈希方法

本文介绍了四种不同的哈希函数实现方法:直接寻址哈希、邻接链表哈希、康托展开及线性探测哈希。每种方法都有详细的代码示例,包括哈希表的构建、插入和查找等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[哈希函数]
//1.第一种hash方法 
typedef long long LL;
const int HashMax = 1000003;
LL Hash[HashMax];
//y,w为需要哈希的两个值 
int MakeHash(int y, int w)
{
	LL situ=(LL)y<<24|w;//定义哈希策略 
	LL big=situ%HashMax;
	while( Hash[big]!=-1&&Hash[big]!=situ )
		big=(big<<1|1)%HashMax;
	if( Hash[big]==-1 )
		Hash[big]=situ;
	return big;
}
//2.邻接链表hash 
#define H 21997
int next[H],head[H];
void insert(int i)
{
    int key=(p[i].x*p[i].x+p[i].y*p[i].y)%H;
    next[m]=head[key];
    p[m].x=p[i].x;
    p[m].y=p[i].y;
    head[key]=m++;
}
int find(int x,int y)
{
    int key=(x*x+y*y)%H;
    register int i;
    for(i=head[key];i!=-1;i=next[i])
        if(p[i].x==x && p[i].y==y)
            return i;
    return -1;
}
//3.康托展开 
int cantor( node a )
{
 	int ret=0;
 	bool flag[10]={false};
 	
 	for( int i=0;i<9;i++ )
 	{
	 	 int k=a.eight[i];
	 	 flag[k]=true;
	 	 int p=0;
	 	 for( int j=1;j<k;j++ )
	 	 	  if( flag[j]==false )
	 	 	  	  p++;
 	  	 ret+=p*fec[8-i];
	}
	return ret;
}
//4.
const int size=20345677;
int hash[size];
int sum[size];
const int key=1777;
const int MAX=1000000000;

void Insert(int num)
{
    int temp=num;
    num=(num+MAX)%size;
    while( hash[num]!=MAX && hash[num]!=temp )
        num=(key+num)%size;
    hash[num]=temp;
    sum[num]++;
}

int Find(int num)
{
    int temp=num;
    num=(num+MAX)%size;
    
	while(hash[num]!=MAX && hash[num]!=temp)
        num=(num+key)%size;
    if( hash[num]==MAX ) return 0;
    else return sum[num];
}

<think>好的,我现在需要回答用户关于哈希表算法种类的问题。根据用户提供的引用内容,我需要整合信息,确保回答结构清晰,符合用户的要求。 首先,用户提到的引用中,引用[1]提到了哈希函数构建的方法和冲突解决方法,包括直接定址法、除留余数法等哈希函数方法,以及开放地址法和链地址法解决冲突。引用[3]和[4]也提到了哈希表的映射方式和基本思想。用户的问题是关于哈希表算法的类型,这可能包括哈希函数的类型和冲突解决方法的类型。 我需要将这两个部分分开来回答。首先介绍哈希函数的种类,然后说明冲突解决的不同方法。同时,要确保使用正确的中文表达,并遵循格式要求,比如行内数学表达式用$...$,独立公式用$$...$$,但当前问题可能不需要复杂公式,所以可能主要用行内格式。 另外,用户要求生成相关问题,我需要根据内容提出几个相关问题,比如哈希函数的选择因素、不同冲突解决方法比较等。还要注意引用标识的位置,例如在提到直接定址法时,后面添加[^1]。 需要检查是否涵盖了所有主要的哈希函数方法,如直接定址法、除留余数法、平方取中法、基数转换法、数字分析法、折叠法、随机数法、乘积法、点积法等,并正确引用来源。同时,冲突解决方法部分要区分开放地址法和链地址法,以及可能的其他方法如再哈希法,但根据引用[1],主要提到的是前两种。 最后,确保回答结构清晰,分点列出,并符合用户给出的示例结构,比如先详细回答,再生成相关问题。</think>### 哈希表算法类型详解 哈希表算法的类型主要分为**哈希函数构建方法**和**哈希冲突解决方法**两大类,两者共同决定了哈希表的性能和适用场景。 --- #### 一、哈希函数构建方法 哈希函数的设计直接影响哈希冲突的概率和分布均匀性,常见方法包括: 1. **直接定址法** 直接以键值$key$或线性变换$(a \cdot key + b)$作为哈希值,适用于键值分布连续的场景[^1]。 公式:$$H(key) = key \quad \text{或} \quad H(key) = a \cdot key + b$$ 2. **除留余数法** 最常用的方法,通过取模运算将键映射到固定范围$[0, N-1]$,公式为:$$H(key) = key \mod p$$ 其中$p$通常选择接近哈希表大小的质数以减少冲突[^1][^3]。 3. **平方取中法** 将键值平方后取中间几位作为哈希值,适合键值分布不均匀的情况[^1]。 4. **数字分析法** 分析键值的数字分布规律,抽取均匀分布的位组成哈希值,例如身份证号中取出生日期部分[^1]。 5. **折叠法** 将键值分割为多段后求和,例如将$123456$拆分为$12 + 34 + 56 = 102$,再取后两位$02$作为哈希值[^1]。 6. **随机数法** 通过随机函数生成哈希值,适用于对安全性有要求的场景[^1]。 --- #### 二、哈希冲突解决方法 当不同键值映射到同一哈希地址时,需通过冲突解决策略处理,主要方法包括: 1. **开放地址法** - **线性探测**:冲突时顺序查找下一个空闲位置,公式:$$H_i = (H(key) + i) \mod N \quad (i=1,2,3,...)$$ - **二次探测**:使用平方步长避免聚集现象,公式:$$H_i = (H(key) + i^2) \mod N$$ - **双重哈希**:使用第二个哈希函数计算步长,公式:$$H_i = (H_1(key) + i \cdot H_2(key)) \mod N$$[^1][^3] 2. **链地址法(拉链法)** 将哈希表的每个槽位作为链表头节点,冲突元素直接添加到链表中。此方法空间利用率高,适合频繁插入/删除的场景[^1][^4]。 3. **再哈希法** 当冲突发生时,使用另一个哈希函数重新计算地址,直到找到空闲位置[^3]。 --- #### 三、综合应用示例 例如在解决“存在重复元素”问题时,使用哈希表存储遍历过的元素。若采用链地址法,冲突元素会形成链表;若用开放地址法,则会线性向后探测空位[^2][^4]。 ```python # 使用哈希集合检测重复元素(Python示例) def contains_duplicate(nums): hash_set = set() for num in nums: if num in hash_set: return True hash_set.add(num) return False ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值