C语言数据结构 - 哈希表

565 篇文章

已下架不支持订阅

#include <stdio.h>
#include <stdlib.h>

/************** 哈希表结构实现 **************/
typedef int bool;

typedef struct ListNode {
    void *key;
    void *val;
    struct ListNode *next;
} Node;

typedef struct {
    int size; // 哈希表存入数据的个数
    int length; // 哈希表底层数组容器的长度
    Node **buckets; // 哈希表底层数组容器,数组元素是Node*
    unsigned int (*hashCode)(void *); // 外部指定的hashCode方法,用于求解key的hash值
    bool (*equals)(void *, void *); // 外部指定的equals方法,用于比较两个key是否相同
} HashTable;

/*!
 * 创建哈希表
 * @param length 指定的哈希表底层数组的长度
 * @param hashCode 指定的求解key的hash值的方法
 * @param equals 指定的比较两个key是否相同的方法
 * @return 哈希表
 */
HashTable *new_HashTable(int length, unsigned int (*hashCode)(void *), bool (*equals)(void *, void *)) {
    HashTable *

已下架不支持订阅

### C语言中的哈希表数据结构 #### 定义哈希表节点 为了构建一个高效的哈希表,在C语言中通常定义两个主要结构体:一个是用于存储实际数据项的`DataNode`,另一个是指向这些节点并管理它们访问方式的桶(bucket)。这里先展示如何创建基本的数据节点。 ```c typedef struct _DataNode { uint32_t key; void* value; // 可以指向任何类型的值 struct _DataNode *next; // 链接到下一个具有相同hashcode的元素 } DataNode; ``` 此部分代码定义了一个名为`_DataNode`的结构体来表示哈希表内的单个条目[^1]。注意这里的`key`字段被设置为无符号整数类型(`uint32_t`),而`value`则是一个指针变量可以用来保存任意类型的数据对象;此外还包含了指向同一散列位置处其他项目的链接指针`next`。 #### 创建哈希函数 一个好的哈希算法对于确保哈希表性能至关重要。下面给出了一种简单的字符串到索引映射的方法作为例子: ```c unsigned int hash_function(const char* str, unsigned int table_size){ unsigned long hash = 5381; int c; while ((c = *str++)) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ return hash % table_size; } ``` 这段程序实现了DJB2哈希算法的一个变体,它接收待处理的关键字串以及目标数组大小,并返回介于0至table_size-1之间的数值作为该键对应的槽位编号。 #### 初始化哈希表 接下来初始化哈希表本身,这涉及到分配适当数量的空间给各个桶,并将每个桶置为空列表形式准备接受新成员加入进来。 ```c #define INITIAL_SIZE 100 typedef struct HashTable{ DataNode **buckets; // 动态分配的一维指针数组 size_t capacity; // 表的最大容量 }s_HashTable; s_HashTable* create_hash_table(size_t initial_capacity){ s_HashTable *ht = malloc(sizeof(s_HashTable)); ht->capacity = initial_capacity ? : INITIAL_SIZE ; ht->buckets = calloc(ht->capacity , sizeof(DataNode *)); if (!ht || !ht->buckets ) { free(ht); return NULL; } return ht; } ``` 上述片段展示了怎样通过动态内存分配技术建立一个新的哈希表实例及其内部容器——即一系列预先设定长度的空闲链表头结点集合。 #### 插入操作 当要往已存在的哈希表里添加新的(key,value)对时,则需遵循如下逻辑流程执行插入动作: ```c int insert_into_hash_table(s_HashTable *ht, const char* key,void* val){ unsigned int index = hash_function((char*)key, ht->capacity); DataNode *new_node = (DataNode *)malloc(sizeof(DataNode)); new_node->key = *(uint32_t*)key; new_node->value=val; new_node->next=NULL; if(!ht->buckets[index]){ ht->buckets[index]=new_node; }else{ DataNode *current=ht->buckets[index]; while(current->next!=NULL){ current=current->next; } current->next=new_node; } return 0; } ``` 在此过程中,首先计算出指定关键字应当放置的位置index,之后检查对应位置是否已有记录存在。如果不存在就直接赋值;反之则遍历现有链条直至找到合适的地方追加进去。 #### 查找功能 最后提供一种方法去检索特定键关联起来的信息内容: ```c void* search_in_hash_table(s_HashTable *ht,const char* key){ unsigned int index = hash_function((char*)key, ht->capacity); DataNode *node = ht->buckets[index]; while(node != NULL && node->key !=*(uint32_t*)key ){ node=node->next; } if(node==NULL)return NULL;//未发现匹配项目 return node->value; } ``` 这个过程同样依赖之前提到过的哈希运算得出定位坐标,随后沿着可能形成的冲突路径逐一检验直到遇到相等条件为止或是到达终点仍未命中所需查找的目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员阿甘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值