1.哈希表的定义
哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过计算key的hash值,然后将value存放在该位置(将hash值作为下标)处。
2.哈希函数
一个好的hash函数需要满足下面的条件:
- 尽量使关键字对应的记录均匀分配在哈希表里面。
- 关键字极小的变化可以引起哈希值极大的变化。
比较好的哈希函数是time33算法。
unsigned long hash(const char* key){
unsigned long hash=0;
for(int i=0;i<strlen(key);i++){
hash = hash*33+str[i];
}
return hash;
}
3.哈希冲突
1、开发定址法(线性探测再散列、二次探测再散列、伪随机探测再散列)
2、链地址法(冲突时,在对应key的链表中头部插入新节点)
3、公共溢出区法(所有冲突元素放在一块公共区域存储)
4、再哈希法:将结果再次带入一个函数求解
哈希表查找或者插入的情况在大多数情况下可以达到O(1),最坏的情况就是hash值全都映射到同一个地址上,这样哈希表就会退化成链表,查找的时间复杂度变成O(n)。
4.用C++实现链地址法
#define HASHSIZE 10
typedef unsigned int uint;
typedef struct Node{
const char* key;
const char* value;
Node *next;
}Node;
class HashTable{
private:
Node* node[HASHSIZE];
public:
HashTable();
uint hash(const char* key);
Node* lookup(const char* key);
bool install(const char* key,const char* value);
const char* get(const char* key);
void display();
};
HashTable::HashTable(){
for (int i = 0; i < HASHSIZE; ++i)
{
node[i] = NULL;
}
}
uint HashTable::hash(const char* key){
uint hash=0;
for (; *key; ++key)
{
hash=hash*33+*key;
}
return hash%HASHSIZE;
}
Node* HashTable::lookup(const char* key){
Node *np;
uint index;
index = hash(key);
for(np=node[index];np;np=np->next){
if(!strcmp(key,np->key))
return np;
}
return NULL;
}
bool HashTable::install(const char* key,const char* value){
uint index;
Node *np;
if(!(np=lookup(key))){
index = hash(key);
np = (Node*)malloc(sizeof(Node));
if(!np) return false;
np->key=key;
np->next = node[index];
node[index] = np;
}
np->value=value;
return true;
}