From 2b16a9183685bea5b1fe1f4ef65b914cd2937e3e Mon Sep 17 00:00:00 2001 From: krahets Date: Fri, 8 Sep 2023 00:46:04 +0800 Subject: [PATCH] build --- chapter_hashing/hash_algorithm.md | 48 ++++++++- chapter_hashing/hash_collision.md | 174 +++++++++++++++++++++++++++++- 2 files changed, 217 insertions(+), 5 deletions(-) diff --git a/chapter_hashing/hash_algorithm.md b/chapter_hashing/hash_algorithm.md index e60e33317..b57a25999 100644 --- a/chapter_hashing/hash_algorithm.md +++ b/chapter_hashing/hash_algorithm.md @@ -459,13 +459,53 @@ index = hash(key) % capacity === "Rust" ```rust title="simple_hash.rs" - [class]{}-[func]{add_hash} + /* 加法哈希 */ + fn add_hash(key: &str) -> i32 { + let mut hash = 0_i64; + const MODULUS: i64 = 1000000007; - [class]{}-[func]{mul_hash} + for c in key.chars() { + hash = (hash + c as i64) % MODULUS; + } - [class]{}-[func]{xor_hash} + hash as i32 + } - [class]{}-[func]{rot_hash} + /* 乘法哈希 */ + fn mul_hash(key: &str) -> i32 { + let mut hash = 0_i64; + const MODULUS: i64 = 1000000007; + + for c in key.chars() { + hash = (31 * hash + c as i64) % MODULUS; + } + + hash as i32 + } + + /* 异或哈希 */ + fn xor_hash(key: &str) -> i32 { + let mut hash = 0_i64; + const MODULUS: i64 = 1000000007; + + for c in key.chars() { + hash ^= c as i64; + } + + (hash & MODULUS) as i32 + } + + /* 旋转哈希 */ + fn rot_hash(key: &str) -> i32 { + let mut hash = 0_i64; + const MODULUS: i64 = 1000000007; + + for c in key.chars() { + hash = ((hash << 4) ^ (hash >> 28) ^ c as i64) % MODULUS; + } + + hash as i32 + } ``` === "C" diff --git a/chapter_hashing/hash_collision.md b/chapter_hashing/hash_collision.md index 8d3ae42f0..5b74ab87c 100644 --- a/chapter_hashing/hash_collision.md +++ b/chapter_hashing/hash_collision.md @@ -1149,7 +1149,179 @@ comments: true === "C" ```c title="hash_map_chaining.c" - [class]{hashMapChaining}-[func]{} + /* 基于数组简易实现的链式地址哈希表 */ + struct hashMapChaining { + int size; // 键值对数量 + int capacity; // 哈希表容量 + double loadThres; // 触发扩容的负载因子阈值 + int extendRatio; // 扩容倍数 + Pair *buckets; // 桶数组 + }; + + typedef struct hashMapChaining hashMapChaining; + + /* 初始化桶数组 */ + hashMapChaining *newHashMapChaining() { + // 为哈希表分配空间 + int tableSize = 4; + hashMapChaining *hashmap = (hashMapChaining *)malloc(sizeof(hashMapChaining)); + + // 初始化数组 + hashmap->buckets = (Pair *)malloc(sizeof(Pair) * tableSize); + memset(hashmap->buckets, 0, sizeof(Pair) * tableSize); + + hashmap->capacity = tableSize; + hashmap->size = 0; + hashmap->extendRatio = 2; + hashmap->loadThres = 2.0 / 3; + + return hashmap; + } + + /* 销毁哈希表 */ + void delHashMapChaining(hashMapChaining *hashmap) { + for (int i = 0; i < hashmap->capacity; i++) { + Pair *pair = &hashmap->buckets[i]; + Node *node = pair->node; + while (node != NULL) { + Node *temp = node; + node = node->next; + free(temp->val); + free(temp); + } + } + free(hashmap->buckets); + free(hashmap); + } + + /* 哈希函数 */ + int hashFunc(hashMapChaining *hashmap, const int key) { + return key % hashmap->capacity; + } + + /* 负载因子 */ + double loadFactor(hashMapChaining *hashmap) { + return (double)hashmap->size / (double)hashmap->capacity; + } + + /* 添加操作 */ + void put(hashMapChaining *hashmap, const int key, char *val) { + if (loadFactor(hashmap) > hashmap->loadThres) { + extend(hashmap); + } + int index = hashFunc(hashmap, key); + + // 先为新节点分配空间再赋值 + Node *newNode = (Node *)malloc(sizeof(Node)); + memset(newNode, 0, sizeof(Node)); + newNode->key = key; + newNode->val = (char *)malloc(strlen(val) + 1); + strcpy(newNode->val, val); + newNode->val[strlen(val)] = '\0'; + + Pair *pair = &hashmap->buckets[index]; + Node *node = pair->node; + if (node == NULL) { + hashmap->buckets[index].node = newNode; + hashmap->size++; + return; + } + while (node != NULL) { + if (node->key == key) { + // 释放先前分配的内存 + free(node->val); + // 更新节点的值 + node->val = (char *)malloc(strlen(val) + 1); + strcpy(node->val, val); + node->val[strlen(val)] = '\0'; + return; + } + if (node->next == NULL) { + break; + } + node = node->next; + } + node->next = newNode; + hashmap->size++; + } + + /* 删除操作 */ + void removeItem(hashMapChaining *hashmap, int key) { + int index = hashFunc(hashmap, key); + Pair *pair = &hashmap->buckets[index]; + Node *node = pair->node; + // 保存后继的节点 + Node *prev = NULL; + while (node != NULL) { + if (node->key == key) { + // 如果要删除的节点是桶的第一个节点 + if (prev == NULL) { + pair->node = node->next; + } else { + prev->next = node->next; + } + // 释放内存 + free(node->val); + free(node); + hashmap->size--; + return; + } + prev = node; + node = node->next; + } + return; + } + + /* 扩容哈希表 */ + void extend(hashMapChaining *hashmap) { + // 暂存原哈希表 + Pair *oldBuckets = hashmap->buckets; + int oldCapacity = hashmap->capacity; + + // 创建新的哈希表,重新分配一段空间 + hashmap->capacity *= hashmap->extendRatio; + hashmap->buckets = (Pair *)malloc(sizeof(Pair) * hashmap->capacity); + memset(hashmap->buckets, 0, sizeof(Pair) * hashmap->capacity); + hashmap->size = 0; + + // 将原哈希表中的键值对重新哈希到新的哈希表中 + for (int i = 0; i < oldCapacity; i++) { + Node *node = oldBuckets[i].node; + while (node != NULL) { + put(hashmap, node->key, node->val); + node = node->next; + } + } + + // 释放原哈希表的内存 + for (int i = 0; i < oldCapacity; i++) { + Node *node = oldBuckets[i].node; + while (node != NULL) { + Node *temp = node; + node = node->next; + free(temp->val); + free(temp); + } + } + free(oldBuckets); + } + + /* 打印哈希表 */ + void print(hashMapChaining *hashmap) { + for (int i = 0; i < hashmap->capacity; i++) { + printf("["); + Pair *pair = &hashmap->buckets[i]; + Node *node = pair->node; + while (node != NULL) { + if (node->val != NULL) { + printf("%d->%s, ", node->key, node->val); + } + node = node->next; + } + printf("]\n"); + } + return; + } ``` === "Zig"