基本数据结构--hash表示例代码


#include <stdlib.h>
#include <string.h>
 
// 哈希表节点结构 
typedef struct HashNode {
    char *key;              // 键(字符串类型)
    int value;               // 值(整数类型)
    struct HashNode *next;   // 链表指针 
} HashNode;
 
// 哈希表主体结构 
typedef struct {
    HashNode **buckets;     // 桶数组 
    int capacity;           // 总容量 
    int size;               // 当前元素数 
} HashMap;
 
// 哈希函数(djb2算法)
unsigned long hash_func(const char *str) {
    unsigned long hash = 5381;
    int c;
    while ((c = *str++))
        hash = ((hash << 5) + hash) + c; // hash * 33 + c 
    return hash;
}
 
// 创建哈希表 
HashMap* hashmap_create(int init_capacity) {
    HashMap *map = (HashMap*)malloc(sizeof(HashMap));
    map->capacity = init_capacity;
    map->size = 0;
    
    map->buckets = (HashNode**)calloc(init_capacity, sizeof(HashNode*));
    return map;
}
 
// 扩容哈希表 
static void resize(HashMap *map, int new_capacity) {
    HashNode **new_buckets = (HashNode**)calloc(new_capacity, sizeof(HashNode*));
    
    // 重新哈希所有元素 
    for (int i = 0; i < map->capacity; i++) {
        HashNode *node = map->buckets[i];
        while (node) {
            HashNode *next = node->next;
            unsigned long idx = hash_func(node->key) % new_capacity;
            node->next = new_buckets[idx];
            new_buckets[idx] = node;
            node = next;
        }
    }
    
    free(map->buckets);
    map->buckets = new_buckets;
    map->capacity = new_capacity;
}
 
// 插入键值对 
void hashmap_put(HashMap *map, const char *key, int value) {
    // 自动扩容(负载因子 > 0.75)
    if (map->size * 4 > map->capacity * 3) {
        resize(map, map->capacity * 2);
    }
    
    unsigned long idx = hash_func(key) % map->capacity;
    HashNode **head = &map->buckets[idx];
    
    // 检查是否已存在相同key 
    while (*head) {
        if (strcmp((*head)->key, key) == 0) {
            (*head)->value = value;
            return;
        }
        head = &(*head)->next;
    }
    
    // 创建新节点 
    HashNode *new_node = (HashNode*)malloc(sizeof(HashNode));
    new_node->key = strdup(key); // 复制key字符串 
    new_node->value = value;
    new_node->next = map->buckets[idx];
    map->buckets[idx] = new_node;
    map->size++;
}
 
// 查找键值 
int hashmap_get(HashMap *map, const char *key, int *found) {
    unsigned long idx = hash_func(key) % map->capacity;
    HashNode *node = map->buckets[idx];
    
    while (node) {
        if (strcmp(node->key, key) == 0) {
            if (found) *found = 1;
            return node->value;
        }
        node = node->next;
    }
    
    if (found) *found = 0;
    return 0;
}
 
// 删除键值对 
int hashmap_remove(HashMap *map, const char *key) {
    unsigned long idx = hash_func(key) % map->capacity;
    HashNode **head = &map->buckets[idx];
    
    while (*head) {
        if (strcmp((*head)->key, key) == 0) {
            HashNode *to_delete = *head;
            *head = (*head)->next;
            free(to_delete->key);
            free(to_delete);
            map->size--;
            return 1;
        }
        head = &(*head)->next;
    }
    return 0;
}
 
// 销毁哈希表 
void hashmap_destroy(HashMap *map) {
    for (int i = 0; i < map->capacity; i++) {
        HashNode *node = map->buckets[i];
        while (node) {
            HashNode *next = node->next;
            free(node->key);
            free(node);
            node = next;
        }
    }
    free(map->buckets);
    free(map);
}
// 示例用法 
#include <stdio.h>
int main() {
    HashMap *map = hashmap_create(8);
    
    // 插入数据 
    hashmap_put(map, "apple", 42);
    hashmap_put(map, "banana", 17);
    
    // 查找数据 
    int found;
    int val = hashmap_get(map, "apple", &found);
    if (found) {
        printf("apple: %d\n", val); // 输出 apple: 42 
    }
    
    // 删除数据 
    hashmap_remove(map, "banana");
    
    hashmap_destroy(map);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和风化雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值