【C语言】23_结构体实现哈希表

#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;
	}
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值