ds通用slist(1.2)

本文介绍如何使用C语言宏实现通用单链表,并提供关键函数如创建、插入、删除等操作的具体代码。

通过前面对于单链表的简单复习, 我想大家也对单链表有些熟悉了吧, 对于其具体实现原理也比较了解了吧。

那今天我们开始正式进入通用单链表的构建。和前面的讲解通用stack的方法是一样的我们通过纯C语言可以有多种方式实现其通用的架构, 首先我们还是使用一种简单的方法来实现。

其实就是使用宏来具体实现了, 说简单, 也就是其动态替换给我们实现各种各样的类型提供了便利。在C语言中没有C++中的template, 利用宏确实解决了各种类型的复杂问题。同时我也一直认为这是一种取巧的实现方法, 不管怎么说, 实现的方法是很多的, 那具体怎么来实现就看个人的喜好了。我这里使用宏, 只是提供了一种建议罢了……

好了, 下面就是使用宏实现的简单的通用slist的具体实现, 希望看到的同学多多指教。

#ifndef __DS_SLIST_HEADER_H__

#define __DS_SLIST_HEADER_H__

#define __DS_SLIST_DECLARE(_type)/

struct _ds_slist_node {/

    _type _data;/

    struct _ds_slist_node* _next;/

};/

/

struct ds_slist {/

    size_t _size;/

    struct _ds_slist_node* _head;/

    struct _ds_slist_node* _tail;/

};/

typedef struct _ds_slist_node* slist_iter;/

typedef void (*_ds_slist_func)(_type);/

/

/

/

/

static inline struct _ds_slist_node* _ds_slist_new_node(_type _x) {/

    struct _ds_slist_node* node = NULL;/

    size_t size = sizeof(struct _ds_slist_node);/

/

    node = (struct _ds_slist_node*)ds_malloc(size);/

    if (NULL != node) node->_data = _x;/

    return node;/

}/

/

/

/

static inline slist_iter /

ds_slist_begin(struct ds_slist* self) {/

    return (NULL != self ? self->_head : NULL);/

}/

/

static inline slist_iter /

ds_slist_end(struct ds_slist* self) {/

    return NULL;/

}/

/

static inline slist_iter ds_slist_next(slist_iter it) {/

    return (NULL != it ? it->_next : NULL);/

}/

/

/

static inline struct ds_slist* ds_slist_new(void) {/

    struct ds_slist* self = NULL;/

    size_t size = sizeof(struct ds_slist);/

/

    self = (struct ds_slist*)ds_malloc(size);/

    return self;/

}/

/

static inline void ds_slist_clear(struct ds_slist* self) {/

    slist_iter node = NULL;/

/

    if (NULL == self) return;/

    while (NULL != self->_head) {/

        node = self->_head;/

        self->_head = self->_head->_next;/

        DS_Free(node);/

    }/

    self->_size = 0;/

}/

/

static inline void ds_slist_free(struct ds_slist** self) {/

    ds_slist_clear(*self);/

    DS_Free(*self);/

}/

/

static inline int ds_slist_empty(struct ds_slist* self) {/

    return ds_slist_begin(self) == ds_slist_end(self);/

}/

/

static inline size_t ds_slist_size(struct ds_slist* self) {/

    return (NULL != self ? self->_size : 0);/

}/

/

static inline int ds_slist_push_back(struct ds_slist* self, _type x) {/

    struct _ds_slist_node* node = _ds_slist_new_node(x);/

/

    if (NULL == self || NULL == node) return 0;/

    if (NULL == self->_head || NULL == self->_tail)/

        self->_head = self->_tail = node;/

    self->_tail->_next = node;/

    self->_tail = node;/

    self->_size++;/

    return 1;/

}/

/

static inline int ds_slist_push_front(struct ds_slist* self, _type x) {/

    struct _ds_slist_node* node = _ds_slist_new_node(x);/

/

    if (NULL == self || NULL == node) return 0;/

    if (NULL == self->_head || NULL == self->_tail)/

        self->_head = self->_tail = node;/

    node->_next = self->_head;/

    self->_head = node;/

    self->_size++;/

    return 1;/

}/

/

static inline int ds_slist_pop_front(struct ds_slist* self) {/

    struct _ds_slist_node* node = ds_slist_begin(self);/

/

    if (NULL == self || NULL == node) return 0;/

    self->_head = node->_next;/

    DS_Free(node);/

    self->_size--;/

    return 1;/

}/

/

static inline _type ds_slist_front(struct ds_slist* self) {/

    struct _ds_slist_node* node = ds_slist_begin(self);/

    _type  v;/

/

    memset(&v, 0sizeof(_type));/

    return (NULL != node ? node->_data : v);/

}/

/

static inline _type ds_slist_back(struct ds_slist* self) {/

    struct _ds_slist_node* node = NULL;/

    _type  v;/

/

    memset(&v, 0sizeof(_type));/

    if (NULL == self) return v;/

    node = self->_tail;/

    return (NULL != node ? node->_data : v);/

}/

/

static inline int /

ds_slist_print(struct ds_slist* self, _ds_slist_func _func) {/

    struct _ds_slist_node* node = NULL;/

/

    if (NULL == self) return 0;/

    node = self->_head;/

    while (NULL != node) {/

        if (NULL != _func) _func(node->_data);/

        else printf("%d ", node->_data);/

        node = node->_next;/

    }/

    printf("/n");/

    return 1;/

}

#endif  /* __DS_SLIST_HEADER_H__ */

好了这就是使用C语言的宏来"投机"实现的一种方法, 是不是看过之后也觉得不过如此呢? 不管怎么说, 或许对大家来说也很简单的吧, 但是自己动手去实现一遍我想也会有不一样的收获吧。

好了, 今天就到这里吧, 下一次我们再来一起探讨通用slist的其他实现方法。

<think>好的,用户想了解SLIST_HEAD宏的用法和定义,特别是在C语言中如何用它来实现单链表。我需要先回忆一下相关的知识,并结合提供的引用内容来组织回答。 首先,根据引用[1]中的结构体定义和SLIST_HEAD的声明,用户可能在使用类似于BSD系统中的队列宏,这些宏定义在<sys/queue.h>中。这类宏通常用于实现链表、队列等数据结构,而不需要手动管理指针操作,减少错误。 接下来,用户提供的引用[4]提到链表的头指针变量,称为头结点,存放第一个节点的地址。引用[5]中的代码示例展示了单链表的打印和插入操作,这可能与SLIST_HEAD的使用有关联。 我需要解释SLIST_HEAD宏的作用,它用于定义链表的头结构。例如,struct slisthead可能包含一个指向链表第一个元素的指针。然后,SLIST_ENTRY宏用于在结构体中嵌入链表节点所需的指针,比如next指针。 使用方法方面,用户需要先使用SLIST_HEAD声明头结构类型,然后在每个节点结构体中使用SLIST_ENTRY来添加链接部分。例如,在struct entry中,SLIST_ENTRY(entry) entries; 会生成一个指向entry结构体的next指针。 接着,初始化链表头,使用SLIST_INIT或手动设置为NULL。插入操作可能有SLIST_INSERT_AFTER、SLIST_INSERT_HEAD等宏。遍历链表可以用SLIST_FOREACH宏或者手动遍历。 需要确保引用的内容与用户的引用对应,比如引用[1]中的结构体定义和SLIST_HEAD的声明,引用[5]中的操作函数可能展示了如何遍历链表,尽管使用的是手动方式而非宏。 可能需要注意用户提供的代码示例中的函数,如SListPrint,虽然用户可能没有直接使用SLIST宏,但可以对比说明手动实现和宏实现的区别。 最后,生成相关问题,可能需要包括BSD队列宏的其他部分,单链表操作,或者对比不同实现方式。 需要检查是否所有信息准确,特别是宏的具体用法,可能需要确认BSD的SLIST宏的标准用法,确保和用户提供的引用内容一致。</think>关于`SLIST_HEAD`宏的使用方法,结合C语言单链表实现分析如下: ### 一、SLIST_HEAD宏的定义作用 `SLIST_HEAD`是BSD系统队列宏中用于定义单链表头节点的宏,属于系统级链表实现工具。其典型定义形式为: $$SLIST\_HEAD(HEADNAME, TYPE)$$ 其中: - `HEADNAME`是链表头结构体类型名 - `TYPE`是链表节点结构体类型 示例定义: ```c SLIST_HEAD(slisthead, entry) { struct entry *slh_first; // 指向第一个节点的指针[^1][^4] }; ``` ### 二、使用方法步骤 1. **声明链表头类型** ```c SLIST_HEAD(slisthead, entry); // 创建名为slisthead的头节点类型 ``` 2. **定义节点结构体** ```c struct entry { int data; SLIST_ENTRY(entry) entries; // 嵌入链表指针域[^1] }; ``` `SLIST_ENTRY`会生成包含`next`指针的匿名结构体 3. **初始化链表** ```c struct slisthead head; SLIST_INIT(&head); // 等价于 head.slh_first = NULL; ``` 4. **插入节点示例** ```c struct entry *n1 = malloc(sizeof(struct entry)); SLIST_INSERT_HEAD(&head, n1, entries); // 头插法[^5] ``` 5. **遍历链表** ```c struct entry *np; SLIST_FOREACH(np, &head, entries) { printf("%d\n", np->data); } ``` ### 三、配套操作宏 - `SLIST_EMPTY()`:判断链表是否为空 - `SLIST_FIRST()`:获取第一个节点 - `SLIST_REMOVE_HEAD()`:删除头节点 - `SLIST_FOREACH_SAFE()`:安全遍历(允许删除节点)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值