1. 功能说明
- 自定义初始容量和负载因子;
- 当键值对的个数与容量比值超过负载因子时,自动扩容;
- 借鉴Java8的HashMap部分扩容逻辑,定义了单独的桶结构体用于记录hash值,以及2倍扩容,减少了hash运算和移位的开销。
2. 实现原理
采用动态数组加链表的方式实现(之后撸完红黑树,增加动态数组+链表+红黑树的版本)。
3. 定义头文件
#ifndef HASH_MAP_H
#define HASH_MAP_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
// 默认桶的个数(动态数组默认大小)
#define DEFAULT_CAPACITY 8
// 默认负载因子
#define DEFAULT_LOAD_FACTOR 0.75
typedef char* K;
typedef char* V;
// 定义hashmap的链表结点
typedef struct map_node {
K key; // 键
V value; // 值
struct map_node *next; // 下一个结点
} MapNode;
// 定义hashmap的桶结点
typedef struct {
MapNode *head; // 桶中链表的第一个节点
uint32_t hash_code; // 桶中键值对hash值
} Bucket;
// 定义hashmap结构体
typedef struct {
Bucket **buckets; // 存键值对的桶(动态的Bucket指针数组)
int size; // map中键值对个数
int capacity; // map的容量
double load_factor; // map的负载因子
uint32_t hash_seed; // hash函数的种子
} HashMap;
// 创建HashMap(容量和负载因子填NULL则使用默认值)
HashMap* create_hashmap(const void* capacity_p, const void* load_factor_p);
// 销毁HashMap
void destroy_hashmap(HashMap *map);
// ---------------- 基本操作 ----------------
// 存入键值对
V put(HashMap *map, K key, V val);
// 查询键值对
V get(const HashMap *map, K key);
// 删除键值对
bool map_remove(HashMap *map, K key);
// 键key在表中是否有对应的值
bool contains(const HashMap *map, K key);
// 判断表是否为空
bool is_empty(const HashMap *map);
// ---------------- 其他操作 ----------------
// 是否需要扩容
static bool is_need_resize(const HashMap *map);
// 扩容
static void resize(HashMap *map);
// murmur_hash2 哈希函数
static uint32_t