C语言实现容器

实现思路

最近在看Redis源代码,发现了许多自己不知道的C语言的书写方式,这些写法可以实现许多结构。
CXX使用泛型提供了容器,但是C语言中不允许将数据类型作为参数进行传递,所以我们必须使用另一种方式来实现我们的目的结构。

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

typedef struct list {
    listNode *head;    
    listNode *tail;    
    void *(*dup)(void *ptr);   
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    unsigned long len;   
} list;

list *listCreate(void);    // 创建
void listRelease(list *list);   // 删除
list *listAddNode(list *list, void *value); // 添加
listNode *listSearchKey(list *list, void *key);  // 查找

Redis使用这种定义结构实现容器的定义,我们可以看到容器内部的数据使用void *value去指向,而我们的容器中包含四个函数void *(*dup)(void *ptr)void (*free)(void *ptr)int (*match)(void *ptr, void *key)void (*print)(void *ptr)。每当我们需要操作容器内部的数据value时,我们就调用这个函数指针对应的方法进行操作,这样就实现了不同的数据类型能够达到不同的操作的方式。
其中我们看到我们给出了free函数,因为我们释放链表节点的同时我们需要释放其value *所指向内容的地址空间,然而这个结构可能还引用了其他的结构,所以我们必须手动提供一个free函数,来指导链表正确释放所指向的空间。
从中我们也能看到,CPP中析构函数的动态顺序也符合这个顺序,先析构子成员再析构自身。
完整示例

在C语言中,我们可以手动模拟队列(Queue)的实现,特别是在处理数组作为内部存储的情况下。这里简单介绍一下如何用数组实现一个基本的FIFO(First-In-First-Out)队列: ```c #include <stdio.h> #define MAX_SIZE 10 typedef struct { int data[MAX_SIZE]; // 存储数组 int front; // 前端指针 int rear; // 后端指针 } Queue; // 初始化队列 void init(Queue *q) { q->front = -1; q->rear = -1; } // 判断队列是否为空 int is_empty(Queue *q) { return q->front == -1 && q->rear == -1; } // 判断队列是否已满 int is_full(Queue *q) { return (q->rear + 1) % MAX_SIZE == q->front; } // 入队操作 void enqueue(Queue *q, int value) { if (is_full(q)) { printf("Queue is full.\n"); return; } q->rear = (q->rear + 1) % MAX_SIZE; // 循环索引 q->data[q->rear] = value; if (q->front == -1) q->front = 0; // 如果队列之前为空,设置前端 } // 出队操作 int dequeue(Queue *q) { if (is_empty(q)) { printf("Queue is empty.\n"); return -1; // 返回错误值或特殊标志 } int value = q->data[q->front]; q->front = (q->front + 1) % MAX_SIZE; if (q-1; q->rear = -1; } return value; } // 打印队列内容 void print_queue(Queue *q) { if (is_empty(q)) printf("Queue is empty.\n"); else { for (int i = q->front; i != q->rear; i = (i + 1) % MAX_SIZE) { printf("%d ", q->data[i]); } printf("\n"); } } // 示例用法 int main() { Queue q; init(&q); enqueue(&q, 1); enqueue(&q, 2); enqueue(&q, 3); print_queue(&q); // 输出: 1 2 3 dequeue(&q); print_queue(&q); // 输出: 2 3 return 0; } ``` 这个简单的实现仅适用于整数,并且数组大小固定。在实际应用中,你可能还需要考虑内存管理、错误处理等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值