版权最终解释权归Leonjhan所有,要引述麻烦添加下作者博客leonjhan,thanks~
/********************************** Part1:adlist.h *****************************************/
#ifndef __ADLIST_H__
#define __ADLIST_H__
1.1 定义了一个双向的链表的节点listNode
typedef struct listNode{
struct listNode *prev; //前序节点
struct listNode *next; //后继节点
void *value; //节点值(注意采用的数据类型)
}listNode;
1.2 定义链表的迭代器
typedef struct listIter{
listNode *next; //下一个节点
int direction; //方向
}listIter;
1.3 定义一个链表
typedef struct list{
listNode *head; //头节点
listNode *tail; //尾节点
unsigned long len; //节点个数
void *(*dup)(void *ptr); //复制ptr内容函数
void (*free)(void *ptr); //释放ptr值函数
int (*match)(void *ptr,void *key); //匹配ptr和key内容的函数
}list;
1.4 定义一些宏
#define listLength(l) ((l)->len) //返回链表的节点数
#define listFirst(l) ((l)->head) //返回链表的头节点
#define listLast(l) ((l)->tail) //返回链表的尾节点
#define listPrevNode(n) ((n)->prev) //返回节点n的前继节点
#define listNextNode(n) ((n)->next) //返回节点n的后继节点
#define listNodeValue(n) ((n)->value) //返回节点n的值
//采用list中的处理方法设置外部调用的方法
#define listSetDupMethod(l,m) ((l)->dup = (m)) //设置复制方法
#define listSetFreeMethod(l,m) ((l)->free = (m)) //设置释放方法
#define listSetMatchMethod(l,m) ((l)->match = (m)) //设置匹配方法
#define listGetDupMethod(l) ((l)->dup) //得到复制方法
#define listGetFree(l) ((l)->free) //得到释放方法
#define listGetMatchMethod(l) ((l)->match) //得到匹配方法
1.5 定义一些函数处理原型
list *listCreate(void); //创造一个双向链表
void listRelease(list *list); //释放链表
list *listAddNodeHead(list *list, void *value); //给链表添加一个头节点
list *listAddNodeTail(list *list, void *value); //给链表添加一个尾节点
list *listInsertNode(list *list, listNode *old_node, void *value, int after); //给旧节点按照after的设置向前向后添加一个节点
void listDelNode(list *list, listNode *node); //删除节点
listIter *listGetIterator(list *list, int direction); //得到链表的迭代器
listNode *listNext(listIter *iter); //返回链表下一个节点
void listReleaseIterator(listIter *iter); //释放链表迭代器
list *listDup(list *orig); //复制一个双向链表
listNode *listSearchKey(list *list, void *key); //搜索节点的值
listNode *listIndex(list *list, long index); //返回索引对应的节点
void listRewind(list *list, listIter *li); //将迭代器指针重新设置为链表头节点
void listRewindTail(list *list, listIter *li); //将迭代器指针重新设置为链表尾节点
void listRotate(list *list); //将尾节点取出插入到头节点(旋转的链表)
1.6 常量定义(设置迭代器方向)
#define AL_START_HEAD 0
#define AL_START_TAIL 1
接下来讲述下源文件的具体实现(这里主要挑一些代表性性质的代码讲述,大家可跟帖一起讨论下...)
/********************************** Part2:adlist.c *****************************************/
#include <stdlib.h>
#include "adlist.h"
#include "zmalloc.h" //作者自己实现的内存分配方式
//链表初始化释放操作................................................................................
2.1 链表的创建(内部一些数据的初始化)
list *listCreate(void)
{
struct list *list;
if((list = zmalloc(sizeof(*list))) == NULL)
return NULL;
list->head = list->tail = NULL;
list->len = 0;
list->dup = NULL;
list->free = NULL;
list->match = NULL;
}
2.2 链表的释放
void listRelease(list *list)
{
unsigned long len;
listNode *current,*next;
current = list->head;
len = list->len;
while(len--){
next = current->next;
//先用自带的方法释放节点的值,然后再释放当前这个节点
if(list->free) list->free(current->value);
zfree(current);
current = next;
}
zfree(list);
}
//链表中节点操作..............................................................................
2.3 新建一个值为value的节点,并且置为链表的头节点
list *listAddNodeHead(list *list,void *value)
{
listNode *node;
if((node = zmalloc(sizeof(*node))) == NULL)
return NULL;
node->value = value;
//考虑加入新节点链表为空的情况
if(list->len == 0){
list->head = list->tail = node;
node ->prev = node->next = NULL;
}else{
node->prev = NULL;
node->next = list->head;
list->head->prev = node;
list->head = node;
}
list->len++;
return list;
}
2.4 新建一个值为value的节点,并且置为链表的尾节点
list *listAddNodeTail(list *list,void *value)
{
listNode *node;
if((node = zmalloc(sizeof(*node))) == NULL)
return NULL;
node->value = value;
if(list->len == 0){
list->head = list->tail = node;
node->prev = node ->next = NULL;
}else{
node->prev = list->tail; //注意加入一个新节点,先把这个节点设置好,然后再更改原来链表中需要改动的节点值
node->next = NULL;
list->tail->next = node;
list->tail = node;
}
list->len++;
return list;
}
2.5 向以前的old_node节点插入值为value的节点(插入方向根据after决定)
list *listInsertNode(list *list,listNode *old_node,void *value,int after)
{
listNode *node;
if((node = zmalloc(sizeof(*node))) == NULL)
return NULL;
node->value = value;
//after>0指示:插入到旧节点之后
if(after){
node->prev = old_node;
node->next = old_node->next;
//注意特殊情况:当前在尾节点之后插入一个节点
if(list->tail == old_node){
list->tail = node;
}
}else{
node->prev = old_node->prev;
node->next = old_node;
//注意特殊情况:当前在头节点之前插入一个节点
if(list->head == old_node){
list->head = node;
}
}
//更新当前插入节点的前继和后继节点的指针
if(node->prev != NULL){
node->prev->next = node;
}
if(node->next != NULL){
node->next->prev = node;
}
list->len++;
return list;
}
2.6 删除一个特定的节点
void listDelNode(list *list,listNode *node)
{
//分别处理这个节点的前继和后继节点
if(node->prev)
node->prev->next = node->next;
else
list->head = node-:next;
if(node->next)
node->next->prev = node->prev;
else
list->tail = node->prev;
//如果有自己定义的释放节点数据的方法就调用
if(list->free) list->free(node->value)
zfree(node);
list->len--;
}
//迭代器操作(很精辟)..............................................................................
listIter *listGetIterator(list *list,int direction)
{
listIter *iter;
if((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
//根据direction指定的方向将迭代器置于表头或表尾
if(direction == AL_START_HEAD)
iter->next = list->head;
else
iter->next = list->tail;
iter->direction = direciton;
return iter;
}
2.8 释放指定的迭代器
void listReleaseIterator(listIter *iter)
{
zfree(iter);
}
2.9 将迭代器重置到表头
void listRewind(list *list,listIter *li)
{
li->next = list->head; //这里是next指向表头
li->direction = AL_START_HEAD;
}
2.10 将迭代器重置到表尾
void listRewindTail(list *list,listIter *li)
{
li->next = list->tail; //注意这里是next指向表尾
li->direciton = AL_START_TAIL;
}
2.11 返回迭代器取得的一个节点值
listNode *listNext(listIter *iter)
{
//后面的操作都是针对iter的next指针进行操作的
listNode *current = iter->next;
if(current != NULL){
if(iter->direction == AL_START_HEAD)
iter->next = current->next;
else
iter->next = current->prev;
}
return current;
}
//整个链表的处理过程..............................................................................
list *listDup(list *orig)
{
list *copy;
listIter *iter;
listNode *node;
//创建一个空的链表
if((copy == listCreate()) == NULL)
return NULL;
//给链表赋予对应的数值
copy->dup = orig->dup;
copy->free = orig->free;
copy->match = orig->match;
iter = listGetIterator(orig,AL_START_HEAD);
while((node = listNext(iter)) != NULL){
void *value;
//如果存在自定义的赋值方法,就采用自定义的方法
if(copy->dup){
value = copy->dup(node->value);
if(value == NULL){
listRelease(copy);
listReleaseIterator(iter);
return NULL;
}
}else
value = node->value;
//将新加入的节点放到链表的末尾
if(listAddNodeTail(copy,value) == NULL){
listRelease(copy);
listReleaseIterator(iter);
return NULL;
}
}
listReleaseIterator(iter);
return copy;
}
2.13 在链表中查找和key匹配的节点
listNode *listSearchKey(list *list,void *key)
{
listIter *iter;
listNode *node;
iter = listGetIterator(list,AL_START_HEAD);
while((node = listNext(iter)) != NULL){
//使用自定义的匹配器进行匹配
if(list->match){
if(list->match(node->value,key) != NULL){
listReleaseIterator(iter);
return node;
}
}else{
if(key == node->value){
listReleaseIterator(iter);
return node;
}
}
}
//前面代码没有返回(也就是没找到)
listReleaseIterator(iter);
return NULL;
}
2.14 根据给定的索引,返回列表中对应的节点;正数:从0~开始,表头开始移动,负数:从-1~开始,表尾开始移动
listNode *listIndex(list *list,long index)
{
listNode *n;
if(index < 0){
index = (-index)-1;
n = list->tail;
while(index-- && n) n= n->prev;
}else{
n = list->head;
while(index-- && n) n = n->next;
}
return n;
}
2.15 将链表尾节点取出插入到头节点的前面
void listRotate(list *list)
{
listNode *tail = list->tail;
//如果链表少于1个元素,直接返回
if(listLength(list) <= 1) return;
//取出之前的尾节点
list->tail = tail->prev;
list->tail->next = NULL;
//将它插入到头节点前面
list->head->prev = tail;
tail->prev = NULL;
tail->next = list->head;
list->head = tail;
}