cpp
复制代码
#include "666.h"
// 字符串哈希函数(djb2算法)
static unsigned long hashString(const char* str) {
unsigned long hash = 5381;
int c;
while ((c = *str++)) {
hash = ((hash << 5) + hash) + c; // hash * 33 + c
}
return hash;
}
// 判断是否为质数
static int isPrime(int n) {
if (n <= 1) return 0;
if (n <= 3) return 1;
if (n % 2 == 0 || n % 3 == 0) return 0;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return 0;
}
return 1;
}
// 获取下一个质数
static int nextPrime(int n) {
while (!isPrime(n)) {
n++;
}
return n;
}
// 创建新节点
static HashNode* createNode(const char* key, int value) {
HashNode* node = (HashNode*)malloc(sizeof(HashNode));
if (node == nullptr) {
printf("createNode err: 内存分配失败\n");
return nullptr;
}
node->key = strdup(key);
if (node->key == nullptr) {
free(node);
printf("createNode err: 字符串复制失败\n");
return nullptr;
}
node->value = value;
node->next = nullptr;
return node;
}
// 释放节点
static void freeNode(HashNode* node) {
if (node) {
free(node->key);
free(node);
}
}
// 计算哈希索引
static int getHashIndex(HashTable* table, const char* key) {
return hashString(key) % table->capacity;
}
// 重新哈希(扩容)
static void rehash(HashTable* table) {
if (table == nullptr) return;
int oldCapacity = table->capacity;
int newCapacity = nextPrime(oldCapacity * 2); // 容量翻倍并找质数
printf("开始重新哈希: %d -> %d (负载因子: %.2f)\n",
oldCapacity, newCapacity,
(double)table->size / table->capacity);
// 创建新的桶数组
HashNode** newBuckets = (HashNode**)calloc(newCapacity, sizeof(HashNode*));
if (newBuckets == nullptr) {
printf("rehash err: 内存分配失败\n");
return;
}
// 重新插入所有元素
for (int i = 0; i < oldCapacity; i++) {
HashNode* node = table->buckets[i];
while (node) {
HashNode* next = node->next;
// 计算在新表中的索引
int newIndex = hashString(node->key) % newCapacity;
// 插入到新表
node->next = newBuckets[newIndex];
newBuckets[newIndex] = node;
node = next;
}
}
// 更新哈希表
free(table->buckets);
table->buckets = newBuckets;
table->capacity = newCapacity;
printf("重新哈希完成\n");
}
// 检查是否需要扩容
static void checkResize(HashTable* table) {
if (table == nullptr) return;
double currentLoad = (double)table->size / table->capacity;
if (currentLoad >= table->load_factor) {
rehash(table);
}
}
// 1. 创建哈希表
HashTable* createHashTable() {
HashTable* table = (HashTable*)malloc(sizeof(HashTable));
if (table == nullptr) {
printf("createHashTable err: 内存分配失败\n");
return nullptr;
}
table->capacity = nextPrime(INITIAL_CAPACITY);
table->size = 0;
table->load_factor = LOAD_FACTOR_THRESHOLD;
table->buckets = (HashNode**)calloc(table->capacity, sizeof(HashNode*));
if (table->buckets == nullptr) {
free(table);
printf("createHashTable err: 桶数组分配失败\n");
return nullptr;
}
printf("创建哈希表成功,容量: %d\n", table->capacity);
return table;
}
// 2. 销毁哈希表
void destroyHashTable(HashTable* table) {
if (table == nullptr) return;
clearHashTable(table);
if (table->buckets) {
free(table->buckets);
}
free(table);
printf("哈希表已销毁\n");
}
// 3. 插入键值对
int hashInsert(HashTable* table, const char* key, int value) {
if (table == nullptr || key == nullptr) return 0;
// 检查是否需要扩容
checkResize(table);
int index = getHashIndex(table, key);
HashNode* head = table->buckets[index];
// 检查键是否已存在
HashNode* current = head;
while (current) {
if (strcmp(current->key, key) == 0) {
// 键已存在,更新值
printf("更新键: %s (旧值: %d -> 新值: %d)\n",
key, current->value, value);
current->value = value;
return 1;
}
current = current->next;
}
// 键不存在,创建新节点
HashNode* newNode = createNode(key, value);
if (newNode == nullptr) {
return 0;
}
// 插入到链表头部
newNode->next = table->buckets[index];
table->buckets[index] = newNode;
table->size++;
printf("插入键值对: [%s: %d] (索引: %d)\n", key, value, index);
return 1;
}
// 4. 查找键对应的值
int* hashSearch(HashTable* table, const char* key) {
if (table == nullptr || key == nullptr) return nullptr;
int index = getHashIndex(table, key);
HashNode* current = table->buckets[index];
while (current) {
if (strcmp(current->key, key) == 0) {
return ¤t->value;
}
current = current->next;
}
return nullptr;
}
// 5. 删除键值对
int hashDelete(HashTable* table, const char* key) {
if (table == nullptr || key == nullptr) return 0;
int index = getHashIndex(table, key);
HashNode* current = table->buckets[index];
HashNode* prev = nullptr;
while (current) {
if (strcmp(current->key, key) == 0) {
// 找到要删除的节点
if (prev) {
prev->next = current->next;
}
else {
// 删除的是头节点
table->buckets[index] = current->next;
}
printf("删除键值对: [%s: %d]\n", key, current->value);
freeNode(current);
table->size--;
return 1;
}
prev = current;
current = current->next;
}
printf("删除失败: 键 %s 不存在\n", key);
return 0;
}
// 6. 获取哈希表大小
int getSize(HashTable* table) {
if (table == nullptr) return 0;
return table->size;
}
// 7. 判断哈希表是否为空
int isEmpty(HashTable* table) {
if (table == nullptr) return 1;
return table->size == 0;
}
// 8. 打印哈希表
void printHashTable(HashTable* table) {
if (table == nullptr) {
printf("哈希表为空指针\n");
return;
}
if (isEmpty(table)) {
printf("哈希表为空\n");
return;
}
printf("\n========== 哈希表内容 ==========\n");
for (int i = 0; i < table->capacity; i++) {
printf("桶[%3d]: ", i);
HashNode* current = table->buckets[i];
if (current == nullptr) {
printf("(空)");
}
else {
while (current) {
printf("[%s:%d]", current->key, current->value);
if (current->next) {
printf(" -> ");
}
current = current->next;
}
}
printf("\n");
}
printf("================================\n");
}
// 9. 清空哈希表
void clearHashTable(HashTable* table) {
if (table == nullptr) return;
for (int i = 0; i < table->capacity; i++) {
HashNode* current = table->buckets[i];
while (current) {
HashNode* next = current->next;
freeNode(current);
current = next;
}
table->buckets[i] = nullptr;
}
table->size = 0;
printf("哈希表已清空\n");
}
// 10. 获取当前负载因子
double getLoadFactor(HashTable* table) {
if (table == nullptr || table->capacity == 0) return 0.0;
return (double)table->size / table->capacity;
}