数据结构
// 链表节点结构
typedef struct listNode {
// 前置节点
struct listNode *prev;
// 后置节点
struct listNode *next;
// 节点值
void *value;
} listNode;
链表节点包含前置和后置节点的指针。
// 链表结构
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;
链表结构包含头结点指针、尾结点指针、链表长度,以及三个函数指针(复制dup、释放free、match)。
方法列表
listCreate
创建一个新链表。
listRelease
释放整个链表。
listAddNodeHead
添加一个节点到链表头。
listAddNodeTail
添加一个节点到链表尾。
listInsertNode
在指定位置插入一个节点。
listDelNode
删除指定节点。
listGetIterator
给指定链表创建一个迭代器。
// 迭代器结构
typedef struct listIter {
// 当前迭代到的节点
listNode *next;
// 迭代的方向
int direction;
} listIter;
listReleaseIterator
释放迭代器。
listRewind
将迭代器的方向设置为从头到尾,并重新指向表头。
listRewindTail
将迭代器的方向设置为从尾到头,并重新指向表尾。
listNext
返回迭代器的下个元素(直接返回iter->next,如果不为NULL,再把next指向下一个节点)。
listDup
复制链表。
流程是创建一个空链表,然后用迭代器遍历原链表,将每个节点值依次添加到新的链表尾部。
// 拷贝值的代码块
// copy是新链表,dup是原链表dup函数的指针
if (copy->dup)
{
value = copy->dup(node->value); // 如果设置了复制函数,就调用复制函数去复制value
if (value == NULL) // value复制失败,链表复制失败。
{
listRelease(copy);
listReleaseIterator(iter);
return NULL;
}
}
// 如果没有设置dup函数,直接赋值。
else
//注意这里value是void*指针,直接赋值后,新链表节点和原链表节点指向同一个值。
value = node->value;
listSearchKey
查找指定的值。
流程是用迭代器遍历链表,将每个节点值做比较。
// 比较值的代码块
// list是链表,match是匹配函数
if (list->match)
{
if (list->match(node->value, key)) // 如果设置了match函数,使用match的
{
listReleaseIterator(iter);
return node;
}
}
// 没有设置match
else
{
// 直接对比指针
if (key == node->value)
{
listReleaseIterator(iter);
// 找到
return node;
}
}
listIndex
返回链表指定位置的节点。(index可以是负数,从后向前)
listRotate
将表尾节点取出,插到表头。
总结:
双端链表的经典实现。