什么是哈希表?
哈希表也称为散列表,强调的是一种映射关系,指的是关键值与存储位置的映射关系
我们常说在建立哈希表的时候,不仅要选择一个好的哈希函数,而且要设定一种处理冲突的方法
哈希函数减少冲突的方法有开放定址法,再哈希法,链地址法,建立公共溢出区
其中最常用减少冲突的方法为链地址法,如图(例)
模拟实现(例下)
#include <stdio.h>
#ifndef _HASH_H_
#define _HASH_H_
#include <assert.h>
#include <malloc.h>
#include <memory.h>
#define HashElemType int
#define P 7
typedef struct HashNode
{
HashElemType data;
struct HashNode* next;
}HashNode;
typedef struct HashTable //表里面元素是链表类型
{
HashNode* *htable;
}HashTable;
void HashTableInit(HashTable* pht); //初始化
void HashTableDestroy(HashTable* pht); //摧毁
void HashTableInsert(HashTable* pht, HashElemType v); //插入元素
void HashTableRemove(HashTable* pht, HashElemType key); //移除元素
HashNode* HashTableFind(HashTable* pht, HashElemType key); //查找元素
void HashTableClear(HashTable* pht); //清空哈希表
size_t HashTableSize(HashTable* pht); //求哈希表长度
void HashTableShow(HashTable* pht); //展示哈希表
int Hash(HashElemType key)
{
//除留余数法
return key % P;
}
void HashTableInit(HashTable* pht)
{
pht->htable = (HashNode**)malloc(sizeof(HashNode*) * P);
assert(pht->htable != NULL);
memset(pht->htable, 0, sizeof(HashNode) * P);
}
void HashTableDestroy(HashTable* pht)
{
HashTableClear(pht);
free(pht->htable);
pht->htable = NULL;
}
void HashTableInsert(HashTable* pht, HashElemType v)
{
assert(pht != NULL);
//1、index
int index = Hash(v);
//2、申请节点进行插入
HashNode* s = (HashNode*)malloc(sizeof(HashNode));
s->data = v;
s->next = pht->htable[index];
pht->htable[index] = s;
}
void HashTableRemove(HashTable* pht, HashElemType key)
{
assert(pht != NULL);
int index = Hash(key);
HashNode* p = pht->htable[index];
if (p == NULL)
return;
if (p->data == key) //存在且是第一个节点
pht->htable[index] = p->next;
else
{
HashNode* pre;
while (p->next != NULL && p->next->data != key)
p = p->next;
if (p->next == NULL)
return;
pre = p;
p = p->next;
pre->next = p->next;
}
free(p);
}
HashNode* HashTableFind(HashTable* pht, HashElemType key)
{
assert(pht != NULL);
int index = Hash(key);
HashNode* p = pht->htable[index];
while (p != NULL && p->data != key)
p = p->next;
return p;
}
void HashTableShow(HashTable* pht)
{
for (int i = 0; i < P; ++i)
{
printf("%d : ", i);
HashNode* p = pht->htable[i];
while (p != NULL)
{
printf("%d-->", p->data);
p = p->next;
}
printf("NULL.\n");
}
}
void HashTableClear(HashTable* pht)
{
assert(pht != NULL);
for (int i = 0; i < P; ++i)
{
HashNode* p = pht->htable[i];
while (p != NULL)
{
pht->htable[i] = p->next;
free(p);
p = pht->htable[i];
}
}
}
size_t HashTableSize(HashTable* pht)
{
assert(pht != NULL);
size_t count = 0;
for (int i = 0; i < P; ++i)
{
HashNode* p = pht->htable[i];
while (p != NULL)
{
count++;
p = p->next;
}
}
return count;
}
#endif