#include<stdint.h>
#define DEFAULT_CAPACITY 8
#define LOAD_FACTOR 0.75
#define MAX_PREALLOCATE 1024
typedef char* K;
typedef char* V;
typedef struct Node {
K key;
V val;
struct Node* next;
} Node;
typedef struct HashMap {
Node** table; //HashMap*→**table→Node*
int size; //键值对个数
int capacity;
uint32_t hashseed; //32位无符号二进制整数
} HashMap;
HashMap* hashmap_create(void) {
HashMap* map = malloc(sizeof(HashMap));
map->table = calloc(DEFAULT_CAPACITY, sizeof(Node*));
map->size = 0;
map->capacity = DEFAULT_CAPACITY;
map->hashseed = time(NULL);
return map;
}
void hashmap_destroy(HashMap* map) {
for (int i = 0; i < map->capacity; i++) {
Node* cur = map->table[i];
while (cur) {
Node* guard = cur->next;
free(cur);
cur = guard;
}
}
free(map->table);
free(map);
}
//key: 关键字地址
//len: 关键字的字节长度
//seed: 哈希种子,避免攻击
//MurmurHash2算法
uint32_t hash(const void* key, int len, uint32_t seed) {
const uint32_t m = 0x5bd1e995;
const int r = 24;
uint32_t h = seed ^ len;
const unsigned char* data = (const unsigned char*)key;
while (len >= 4) {
uint32_t k = *(uint32_t*)data;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
switch (len) {
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
void rehash(Node* cur, Node** new_table, int new_capacity, uint32_t new_seed) {
int index = hash(cur->key, strlen(cur->key), new_seed) % new_capacity;
cur->next = new_table[index];
new_table[index] = cur;
}
void grow_capacity(HashMap* map) {
int new_capacity = (map->capacity <= MAX_PREALLOCATE) ?
(map->capacity << 1) : (map->capacity + MAX_PREALLOCATE);
Node** new_table = calloc(new_capacity, sizeof(Node*));
uint32_t new_seed = time(NULL);
//重新映射
for (int i = 0; i < map->capacity; i++) {
Node* cur = map->table[i];
while (cur) {
Node* tmp = cur->next;
rehash(cur, new_table, new_capacity, new_seed);
cur = tmp;
}
}
free(map->table);
map->table = new_table;
map->capacity = new_capacity;
map->hashseed = new_seed;
}
//如果key存在,更新key关联的值,并返回原来关联的值
//如果key不存在:则添加(key, val)
V hashmap_put(HashMap* map, K key, V val) {
int index = hash(key, strlen(key), map->hashseed) % map->capacity;
Node* cur = map->table[index];
//key存在
while (cur) {
if (cur->key == key) {
V oldval = cur->val;
cur->val = val;
return oldval;
}
cur = cur->next;
}
//key不存在
Node* newNode = malloc(sizeof(Node));
newNode->key = key;
newNode->val = val;
double load = (1.0 * map->size) / map->capacity;
if (load >= LOAD_FACTOR) {
grow_capacity(map);
index = hash(key, strlen(key), map->hashseed) % map->capacity;
}
//头插法
newNode->next = map->table[index];
map->table[index] = newNode;
map->size++;
return NULL;
}
V hashmap_get(HashMap* map, K key) {
int index = hash(key, strlen(key), map->hashseed) % map->capacity;
Node* cur = map->table[index];
while (cur) {
if (cur->key == key) {
return cur->val;
}
cur = cur->next;
}
return NULL;
}
void hashmap_delete(HashMap* map, K key) {
int index = hash(key, strlen(key), map->hashseed) % map->capacity;
Node* pre = NULL;
Node* cur = map->table[index];
while (cur) {
if (cur->key == key) {
if (!pre) {
map->table[index] = cur->next;
} else {
pre->next = cur->next;
}
free(cur);
map->size--;
return;
}
pre = cur;
cur = cur->next;
}
}
【C语言】23_结构体实现哈希表
最新推荐文章于 2024-07-08 22:12:26 发布