哈希表原理和哈希冲突

假设有一个数组An = {81, 62, 55, 43, 97, 76, 49, 98, 64};  如果判断任意一个数x是否在该给定的数列An中呢? 作为一个正常的人, 我们自然会想, 把x先和81, 62, ...,  逐一比较,这样复杂度是O(n)。 

提出哈希表的人, 确实很了不起, 因为他没有采用正常人的思路。我们来看看哈希表人的思路:

哈希的思想是:你给我一个key和value,我用这个key和我设计的哈希函数去算出一个地址,然后把value存到这个地址。

在查询的时候,我用x和哈希函数去找到地址中的值来比对,所以复杂度是O(1)。具体见代码:

#include <iostream>
using namespace std;
 
int hash(int key, int n)//用key作为哈希函数的参数
{
	return key % n;
}
 
int main()
{
	int a[9] = {81, 62, 55, 43, 97, 76, 49, 98, 64};
	int b[9] = {-1, -1, -1, -1, -1, -1, -1, -1, -1};
	int i = 0;
	for(i = 0; i < 9; i++)
	{
		b[hash(a[i], 10)] = a[i];//把value存到哈希函数计算得到的地址中去
	}
	
	int x = 0;
	for(x = 0; x < 1000000; x++)
	{
		if(b[hash(x, 10)] == x) 
		{
			cout << x << " is in a[...]" << endl;
		}
	}
 
	return 0;
}

上述程序的结果为:
43 is in a[...]
49 is in a[...]
55 is in a[...]
62 is in a[...]
64 is in a[...]
76 is in a[...]
81 is in a[...]
97 is in a[...]
98 is in a[...]

上面例子中的数组是故意设计的,各位分别为1~9.为什么要选择那么特殊的数组An呢? 因为经历h(z) = z %10的哈希变化后, 不会冲突。那么假如数组中多一个元素11。那么经过哈希函数后就会有哈希冲突。

如果遇到哈希冲突怎么办

解决方法有两类,

开放寻址法(open addressing)和链表法(chaining)。

1. 开放寻址法

 2. 链表法

链表法是一种更加常用的散列冲突解决办法,相比开放寻址法,它要简单很多。我们来看这个图,在散列表中,

“桶(bucket)”或者“槽(slot)”会对应一条链表,所有散列值相同的元素我们都放到相同槽位对应的链表中。

参考:

1.https://blog.csdn.net/stpeace/article/details/38615647

2.https://time.geekbang.org/column/article/64233

猜你喜欢

转载自blog.csdn.net/zpznba/article/details/88788071