Hash
设某元素的关键字为key,用函数Hash(key)的值作为该元素的地址,所构造的查找表称为哈希表(或散列表),函数Hash(key)称为哈希(Hash)函数(或散列函数)。
若两个关键字k1 != k2,但H(k1) = H(k2)。这种现象称为冲突,k1和k2称为同义词。
要避免冲突,需要构造一个恰当的哈希函数。常见的构造哈希函数的方法有:直接定址法、除留余数法、平方取中法等。
有时冲突是不能完全避免的,须妥善处理。
处理冲突的方法:链地址法(拉链法)、开放定址法
链地址法(拉链法)
将所有发生冲突的元素存储在一个链表中,并将这些链表的表头指针存放在一个表中。所构造的散列表称为开散列表。
插入操作的最坏情况运行时间为O(1),查找操作的最坏情况运行时间与表的长度成正比。
ChainedHashMain.c
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
"
hash.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*简单操作示例*/
int
main(
int
argc,
char
**
argv)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
CHashTable t;
CHashNode *p;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
int a[N] = ...{47, 7, 29, 11, 16, 92, 22, 8, 3, 0, 37, 89, 4, 21};
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
ChainedHashCreate(&t, a);
printf("[+] hash table create ok. ");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
p = ChainedHashSearch(&t, 92);
PrintNodeKey(p);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
ChainedHashInsert(&t, 92);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
ChainedHashDelete(&t, 92);
p = ChainedHashSearch(&t, 92);
PrintNodeKey(p);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 1;
}
hash.h
#ifndef _HASH_H
#define
_HASH_H
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#define
M 11
#define
N 14
#define
DELETE -1
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
typedef
int
KeyType;
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
typedef
struct
Node
...
{
KeyType key;
struct Node *next;
}
CHashNode;
typedef CHashNode
*
CHashTable[M];
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
Hash(KeyType
k);
int
ChainedHashInsert(CHashTable
*
t, KeyType k);
int
ChainedHashCreate(CHashTable
*
t,
int
*
a);
int
ChainedHashDelete(CHashTable
*
t, KeyType k);
CHashNode
*
ChainedHashSearch(CHashTable
*
t, KeyType k);
void
PrintNodeKey(CHashNode
*
ph);
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#endif
hash.c
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
"
hash.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
Hash(KeyType
k)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
return k % M;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*
*根据a[0..N-1]中结点建立散列表t[0..M-1]
*/
int
ChainedHashCreate(CHashTable
*
t,
int
*
a)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int i;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for(i = 0; i < M; i++)
(*t)[i] = NULL;
for(i = 0; i < N; i++)
ChainedHashInsert(&(*t), a[i]);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 1;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*
*将关键字k插入散列表t中
*/
int
ChainedHashInsert(CHashTable
*
t, KeyType k)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
CHashNode *p;
int addr;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
p = ChainedHashSearch(&(*t), k);
if(p)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("Duplicate Key! ");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 0;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
addr = Hash(k);
p = (CHashNode *)malloc(sizeof(CHashNode));
p->key = k;
p->next = (*t)[addr];
(*t)[addr] = p;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 1;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*
*在散列表t中查找关键字k
*/
CHashNode
*
ChainedHashSearch(CHashTable
*
t, KeyType k)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
CHashNode *p;
int addr;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
addr = Hash(k);
p = (*t)[addr];
if(p == NULL)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return NULL;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
while(p && p->key != k)
p = p->next;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return p;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*
*在散列表t中删除关键字k
*/
int
ChainedHashDelete(CHashTable
*
t, KeyType k)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
CHashNode *p, *q;
int addr;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
addr = Hash(k);
p = (*t)[addr];
if((p == NULL) || (p->key == DELETE))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("No such key! ");
return 0;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
q = p;
while(p && p->key != k)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
q = p;
p = p->next;
}
if(q != p)
q->next = p->next;
else
p->key = DELETE;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return 1;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
PrintNodeKey(CHashNode
*
p)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(p == NULL)
printf("It's a NULL node! ");
else
printf("%d ", p->key);
}