(redis)adlist.h/adlist.c理解
2014-01-12 16:57
369 查看
版权最终解释权归Leonjhan所有,要引述麻烦添加下作者博客leonjhan,thanks~
/********************************** Part1:adlist.h *****************************************/
1.1 定义了一个双向的链表的节点listNode
1.2 定义链表的迭代器
1.3 定义一个链表
1.4 定义一些宏
1.5 定义一些函数处理原型
1.6 常量定义(设置迭代器方向)
接下来讲述下源文件的具体实现(这里主要挑一些代表性性质的代码讲述,大家可跟帖一起讨论下...)
/********************************** Part2:adlist.c *****************************************/
#include <stdlib.h>
#include "adlist.h"
#include "zmalloc.h" //作者自己实现的内存分配方式
//链表初始化释放操作................................................................................
2.1 链表的创建(内部一些数据的初始化)
2.2 链表的释放
//链表中节点操作..............................................................................
2.3 新建一个值为value的节点,并且置为链表的头节点
2.4 新建一个值为value的节点,并且置为链表的尾节点
2.5 向以前的old_node节点插入值为value的节点(插入方向根据after决定)
2.6 删除一个特定的节点
//迭代器操作(很精辟)..............................................................................
2.7 返回给定链表的一个迭代器,direction指定迭代的方向
2.9 将迭代器重置到表头
2.10 将迭代器重置到表尾
2.11 返回迭代器取得的一个节点值
//整个链表的处理过程..............................................................................
2.12 复制整个链表,成功时返回列表的副本,否则返回NULL
2.14 根据给定的索引,返回列表中对应的节点;正数:从0~开始,表头开始移动,负数:从-1~开始,表尾开始移动
2.15 将链表尾节点取出插入到头节点的前面
/********************************** 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--; }
//迭代器操作(很精辟)..............................................................................
2.7 返回给定链表的一个迭代器,direction指定迭代的方向
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; }
//整个链表的处理过程..............................................................................
2.12 复制整个链表,成功时返回列表的副本,否则返回NULL
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; }
相关文章推荐
- redis源码系列-数据结构(adlist/ziplist/dict)
- redis源码系列-数据结构(adlist/ziplist/dict)
- Redis adlist
- 安装redis出现cc adlist.o /bin/sh:1:cc:not found
- redis源码分析之数据结构(一)链表adlist.c
- redis源码解读之双向链表————adlist.h文件
- redis源码分析(adlist)
- Redis之2-双端链表(adlist.c,adlist.h)
- 【redis源码分析】双向链表---adlist
- Redis源码分析(adlist)
- 在ubuntu server 14 下,编译redis 出错: cc adlist.o /bin/sh:1:cc:not found
- Redis源码分析(二)——链表adlist
- Redis源码阅读笔记—adlist
- redis源码分析(9)redis源码链表学习总结 adlist.h adlist.c
- Redis-数据结构-链表-adlist.h/listNode
- Redis从基础命令到实战之列表类型(List)
- redis学习笔记之list类型
- redis命令解析之list类型
- 深入理解redis分布式锁和消息队列
- 深入理解Spring Redis的使用 (一)、Spring Redis基本使用