list.h
#ifndef __sd_list_h
#define __sd_list_h
#include <stddef.h>
#include "defs.h"
__SD_BEGIN_DECLS
/**
* 声明list类型,实际定义是在list.c文件里
*/
typedef struct __sd_list sd_list_t;
/**
* 定义list中元素的结构,data应该是指向用户数据的指针,
* 双向链表
*/
struct __sd_list_iter {
void* data;
struct __sd_list* list;
struct __sd_list_iter* __next;
struct __sd_list_iter* __prev;
int __foreach;
};
/**
* 对于元素容器进行类型的定义
*/
typedef struct __sd_list_iter sd_list_iter_t;
/**
* foreach遍历时的回调函数类型
*/
typedef unsigned int (*sd_list_func_t)(void* a_data, void* a_userdata);
/**
* 新建一个链表
* @param a_capacity 初始化链表中容纳元素的数量
* @return 链表的入口指针.
*/
extern sd_list_t* sd_list_new(size_t a_capacity);
/**
* 销毁一个链表
* @todo 需要一个回调函数来释放用户数据(尚未实现)
*/
extern void sd_list_delete(sd_list_t* a_this);
/**
* 将用户数据插入到链表的头部
*/
extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data);
/**
* 将用户数据插入到链表的尾部
*/
extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data);
/**
* 在链表里查找用户数据是否存在
* @param a_data 待查找数据
* @return 找到的元素地址,或者NULL.
*/
extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data);
/**
* 在链表里查找数据,如果没有找到就调用sd_list_add().将数据插入到链表里
* @param a_data 待查找数据
* @return 查找到的数据地址,或者NULL.
*/
extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data);
/**
* 将用户数据插入到链表里,如果该数据已经存在则返回数据的指针
* @warning 元素会插入到链表的头部
* @param a_data 带插入数据
* @return 返回插入的或者已存在的元素指针
*/
extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data);
/**
* 用a_func从头遍历链表中的所有元素,直到返回一个非NULL的返回值,则
* 将用户数据插入到返回的数据前面
* @param a_func 排序函数
* @param a_data 待插入的用户数据
* @return 用户数据插入后所在的容器指针
*/
extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
sd_list_func_t a_func,
void* a_data);
/**
* 从链表里删除一个用户数据
* @param a_data 包含用户数据的容器地址
*/
extern int sd_list_del(sd_list_t* a_this, void* a_data);
/**
* 清空一个链表
*/
extern void sd_list_clear(sd_list_t* a_this);
/**
* 调用a_func从头遍历整个链表直到返回一个非0
* @param a_func 遍历回调函数
* @param a_data 传入到回调函数的一个用户数据
*/
extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
void* a_userdata);
/**
* 调用a_func从后向前遍历整个链表直到返回一个非0
* @param a_func 遍历回调函数
* @param a_data 传入到回调函数的用户数据
*/
extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
void* a_userdata);
/**
* 获取链表中元素的个数
*/
extern size_t sd_list_get_nelem(sd_list_t* a_this);
/**
* 获取链表中第一个容器
*/
extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
/**
* Gets the past-the-last-element iterator of the list.
* 函数定义未实现
*/
extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
/**
* 获取链表中最后一个元素
*/
extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
/**
* Gets the before-the-first-element iterator of the list.
* 函数定义未实现
*/
extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
/**
* 得到当前容器的下一个容器
*/
extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this);
/**
* 得到当前容器的前一个容器
*/
extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this);
/**
* 从链表中删除一个容器
*/
extern void sd_list_iter_del(sd_list_iter_t* a_this);
/**
* 创建一个新的容器并将数据插入到a_this前面
* @param a_data 放入到新建容器的数据
*/
extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
void* a_data);
__SD_END_DECLS
#endif
list.h中声明的函数,是在list.c中进行了实现,其中声明的两个函数:
extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
功能与
extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
重复,所以在list.c里面只进行定义了一个空的函数体,并没有进行实现。
以下是list.c中的内容:
#include "list.h"
#include "malloc.h"
#include <stdlib.h>
struct __sd_list {
sd_list_iter_t* head;
sd_list_iter_t* tail;
size_t nelem;
};
list.h中有一个typedef语句:typedef struct __sd_list sd_list_t; 将sd_list_t声明一下然后在这里进行实际的结构体的定义,这样下面的函数声明中就可以使用这个sd_list_t进行参数或者返回值的声明了。并且只要引用了list.h就可以使用sd_list_t来进行定义自己的链表句柄。这样可以比较完美的实现结构体的隐藏同时还能比较容易使用。
从这里就知道了整个链表的结构是什么样的了。具体的可以参考图一:
图一:链表的整体结构图
sd_list_new:
extern sd_list_t* sd_list_new(size_t a_capacity)
{
sd_list_t* this;
//申请内存,并初始化。实际上calloc分配的就是初始化了的内存。
this = sd_calloc(1, sizeof(sd_list_t));
this->head = 0;
this->tail = 0;
this->nelem = 0;
return this;
}
sd_list_prepend:
extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data)
{
//定义一个容器,参数有效性判断。并进行容器内存分配和检查
sd_list_iter_t* i;
if (! a_this) return 0;
if ((i = sd_calloc(1, sizeof(*i))) == 0)
return 0;
//填充容器,用户数据,链表等。
i->list = a_this;
i->data = a_data;
i->__prev = 0;
i->__next = a_this->head;
a_this->head = i;
//接通后面的链表,否则设置链表的tail指针的指向
if (i->__next)
i->__next->__prev = i;
else
a_this->tail = i;
//增加元素计数器
a_this->nelem++;
return i;
}
sd_list_append:
extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data)
{
sd_list_iter_t* i;
if (! a_this) return 0;
//定义一个容器,参数有效性判断。并进行容器内存分配和检查
if ((i = sd_calloc(1, sizeof(*i))) == 0)
return 0;
//填充容器,用户数据,链表等。
i->list = a_this;
i->data = a_data;
i->__prev = a_this->tail;
i->__next = 0;
a_this->tail = i;
//链接前面的链表或者设置链表的head指针
if (i->__prev)
i->__prev->__next = i;
else
a_this->head = i;
//计数器加一
a_this->nelem++;
return i;
}
sd_list_delete:
extern void sd_list_delete(sd_list_t* a_this)
{
sd_list_iter_t *a_next;
sd_list_iter_t *a_current;
if (!a_this)
return;
//释放所有的容器
/* Free the iterators */
if (a_this->nelem > 0){
a_current = a_this->head;
do {
a_next = a_current->__next;
free(a_current);
a_current = a_next;
} while (a_current);
}
//释放链表 句柄
free(a_this);
}
sd_list_clear:
extern void sd_list_clear(sd_list_t* a_this)
{
a_this->head = 0;
a_this->tail = 0;
a_this->nelem = 0;
}
sd_list_get_nelem:
extern size_t sd_list_get_nelem(sd_list_t* a_this)
{
return (a_this ? a_this->nelem : 0);
}
sd_list_begin:
extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this)
{
return (a_this ? a_this->head : 0);
}
sd_list_rbegin:
extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this)
{
return (a_this ? a_this->tail : 0);
}
sd_list_lookup:
extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data)
{
sd_list_iter_t* i;
if (! a_this) return 0;
//遍历直到找到数据地址与用户传入的地址相同,返回容器地址
for (i = a_this->head; i; i = i->__next)
if (a_data == i->data)
return i;
return 0;
}
sd_list_add:
extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data)
{
sd_list_iter_t* i;
if (! a_this) return 0;
//新建一个容器并分配内存检查
if ((i = sd_calloc(1, sizeof(*i))) == 0)
return 0;
//填充
i->data = a_data;
i->list = a_this;
i->__next = a_this->head;
i->__prev = 0;
a_this->head = i;
//插入首部
if (i->__next) i->__next->__prev = i;
if (!a_this->tail) a_this->tail = i;
//计数器加一
a_this->nelem++;
return i;
}
sd_list_lookadd:
extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data)
{
sd_list_iter_t* i;
if (! a_this) return 0;
//调用sd_list_lookup,或者就插入并返回
if ((i = sd_list_lookup(a_this, a_data)) != 0)
return i;
return sd_list_add(a_this, a_data);
}
sd_list_iter_insert:
extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
void* a_data)
{
sd_list_iter_t* i;
if (! a_this) return 0;
//如果錫_this就是头节点那么就头插
if (a_this->list->head == a_this)
return sd_list_prepend(a_this->list, a_data);
//申请内存,填充后插入到a_this之前
if ((i = sd_calloc(1, sizeof(*i))) == 0)
return 0;
i->data = a_data;
i->list = a_this->list;
i->__prev = a_this->__prev;
i->__next = a_this;
/* CAUTION: always exists since a_this is not the head */
a_this->__prev->__next = i;
a_this->__prev = i;
//计数器加一
a_this->list->nelem++;
return i;
}
sd_list_sortadd:
extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
sd_list_func_t a_func, void* a_data)
{
sd_list_iter_t* i;
//参数检查
if (! a_this || ! a_func) return 0;
//从头遍历直到找到一个大于当前用户数据的位置
for (i = a_this->head; i; i = i->__next)
if ((*a_func)(i->data, a_data) > 0)
break;
//如果不是最后的位置,那么插入新节点到a_data之前。否则添加在最后
if (i)
return sd_list_iter_insert(i, a_data);
else
return sd_list_append(a_this, a_data);
}
sd_list_iter_del:
extern void sd_list_iter_del(sd_list_iter_t* a_this)
{
if (!a_this)
return;
if (a_this->__foreach == 1) {
a_this->__foreach = 0;
return;
}
//向后接通
if (a_this->__next)
a_this->__next->__prev = a_this->__prev;
else
a_this->list->tail = a_this->__prev;
//向前接通
if (a_this->__prev)
a_this->__prev->__next = a_this->__next;
else
a_this->list->head = a_this->__next;
//计数器减一
a_this->list->nelem--;
//释放当前数据
free(a_this);
}
sd_list_del:
extern int sd_list_del(sd_list_t* a_this, void* a_data)
{
sd_list_iter_t* i;
if (!a_this)
return -1;
//遍历直到找到这个数据
for (i = a_this->head; i; i = i->__next)
if (a_data == i->data)
break;
//如果没找到
if (!i)
return -1;
//删除这个元素
sd_list_iter_del(i);
return 0;
}
sd_list_foreach:
extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
void* a_userdata)
{
sd_list_iter_t* i;
sd_list_iter_t* j;
if (!a_this || !a_func)
return;
//从头到尾遍历整个链表
for (i = a_this->head; i; i = j)
{
int ret;
i->__foreach = 1;
ret = (*a_func)(i->data, a_userdata);
j = i->__next;
if (i->__foreach == 0)
sd_list_iter_del(i);
else
i->__foreach = 0;
if (ret) return;
}
}
sd_list_rforeach:
extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
void* a_userdata)
{
sd_list_iter_t* i;
sd_list_iter_t* j;
if (!a_this || !a_func)
return;
for (i = a_this->tail; i; i = j) {
int ret;
i->__foreach = 1;
ret = (*a_func)(i->data, a_userdata);
j = i->__prev;
if (i->__foreach == 0)
sd_list_iter_del(i);
else
i->__foreach = 0;
if (ret) return;
}
}
sd_list_iter_next:
extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this)
{
return (a_this ? a_this->__next : 0);
}
sd_list_iter_prev:
extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this)
{
return (a_this ? a_this->__prev : 0);
}
一个简单的样例测试程序如下:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#include "list.h"
typedef struct test
{
int a;
int b;
int c;
}test_t;
static unsigned int print(void *data, void *p)
{
test_t *t = (test_t *)data;
printf("a:%d b:%d c:%d ",t->a, t->b, t->c);
return 0;
}
int main()
{
sd_list_t* a_this = sd_list_new(24);
test_t *t3 = malloc(sizeof(test_t));
t3->a = 3;
t3->b = 4;
t3->c = 5;
sd_list_prepend(a_this, t3);
test_t *t1 = malloc(sizeof(test_t));
t1->a = 1;
t1->b = 2;
t1->c = 3;
sd_list_prepend(a_this, t1);
test_t *t2 = malloc(sizeof(test_t));
t2->a = 2;
t2->b = 3;
t2->c = 4;
sd_list_prepend(a_this, t2);
sd_list_foreach(a_this, print, NULL);
printf("remains in list:%d ", sd_list_get_nelem(a_this));
sd_list_delete(a_this);
return 0;
}