C语言实现模板函数,解决多数据结构复用及存储难题
问题解决方案
问题1:避免队列与集合的重复实现
核心思路是定义统一的集合操作抽象接口,通过编译期宏替换绑定具体集合类型,让队列代码只依赖抽象接口,无需为每种集合重写队列逻辑。
步骤1:定义集合操作的抽象宏接口
创建collection_interface.h,用宏封装不同集合的统一操作:
// collection_interface.h #ifndef COLLECTION_INTERFACE_H #define COLLECTION_INTERFACE_H // 编译时根据配置选择集合类型 #ifdef USE_VECTOR #include "vector.h" #define COLLECTION_TYPE VECTOR #define COLLECTION_INIT(col) vector_init(col) #define COLLECTION_INSERT(col, val) vector_insert(col, val) #define COLLECTION_REMOVE(col, val) vector_remove(col, val) #define COLLECTION_FIND(col, val) vector_find(col, val) #elif defined(USE_BST) #include "bst.h" #define COLLECTION_TYPE BST #define COLLECTION_INIT(col) bst_init(col) #define COLLECTION_INSERT(col, val) bst_insert(col, val) #define COLLECTION_REMOVE(col, val) bst_remove(col, val) #define COLLECTION_FIND(col, val) bst_find(col, val) #elif defined(USE_HT) #include "hashset.h" #define COLLECTION_TYPE HT #define COLLECTION_INIT(col) hashset_init(col) #define COLLECTION_INSERT(col, val) hashset_insert(col, val) #define COLLECTION_REMOVE(col, val) hashset_remove(col, val) #define COLLECTION_FIND(col, val) hashset_find(col, val) #endif #endif // COLLECTION_INTERFACE_H
步骤2:编写通用队列实现
队列代码仅依赖抽象接口,无需关心具体集合:
// queue_generic.h #ifndef QUEUE_GENERIC_H #define QUEUE_GENERIC_H #include "collection_interface.h" typedef struct { COLLECTION_TYPE storage; } GenericQueue; void generic_queue_init(GenericQueue *q) { COLLECTION_INIT(&q->storage); } void generic_queue_enqueue(GenericQueue *q, void *val) { COLLECTION_INSERT(&q->storage, val); } void* generic_queue_dequeue(GenericQueue *q) { // 根据队列特性实现出队逻辑(如堆结构取极值) void *val = COLLECTION_FIND(&q->storage, /* 队列规则对应元素 */); if (val) { COLLECTION_REMOVE(&q->storage, val); } return val; } #endif // QUEUE_GENERIC_H
步骤3:编译期绑定配置
解析配置文件后,通过编译宏指定集合和队列类型。例如解析到HashSet和BinomialHeap时,编译命令为:
gcc -DUSE_HT -DBINOMIAL_Q your_code.c -o your_program
这样队列代码只需编写一次,编译时自动适配配置指定的集合类型,彻底避免重复实现。
问题2:在HashSet中存储Queue
HashSet存储自定义类型(如Queue)需要实现哈希值计算和元素相等判断两个核心函数。
步骤1:为Queue实现哈希与比较函数
以队列内存地址作为唯一标识(简单直接,适合内存固定的场景):
// 计算Queue的哈希值 unsigned int queue_hash(const void *elem) { const GenericQueue *q = (const GenericQueue*)elem; return (unsigned int)(uintptr_t)q; } // 判断两个Queue是否相等 int queue_equals(const void *a, const void *b) { return a == b; }
如果需要基于队列内容判断相等,只需修改上述函数,遍历队列元素计算哈希或比较即可。
步骤2:修改HashSet支持自定义函数
让HashSet初始化时可传入自定义哈希和比较逻辑:
// hashset.h typedef unsigned int (*HashFunc)(const void *elem); typedef int (*EqualsFunc)(const void *a, const void *b); typedef struct { // HashSet内部结构 HashFunc hash_func; EqualsFunc equals_func; } HashSet; void hashset_init(HashSet *ht, HashFunc hash, EqualsFunc equals);
步骤3:存储Queue到HashSet
int main() { HashSet queue_set; // 初始化HashSet,传入Queue的哈希和比较函数 hashset_init(&queue_set, queue_hash, queue_equals); GenericQueue q1, q2; generic_queue_init(&q1); generic_queue_init(&q2); // 将Queue存入HashSet hashset_insert(&queue_set, &q1); hashset_insert(&queue_set, &q2); // 查找指定Queue if (hashset_find(&queue_set, &q1)) { printf("Queue q1 exists in HashSet\n"); } return 0; }
内容的提问来源于stack exchange,提问作者Роберт Батоян
相关产品推荐
相关产品推荐

