標籤:開源項目 資料結構 源碼
Redis的Adlist實現了資料結構中的雙端鏈表,整個結構如下:
鏈表節點定義:
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;
其中的三個函數指標先不用管,後面遇到了再看具體是幹什麼的,另外還實現了一個迭代器,有點c++的味道在裡面
typedef struct listIter { listNode *next; int direction;} listIter;
鏈表三要素,建立,插入,和刪除
list *listCreate(void){ struct list *list; if ((list = malloc(sizeof(*list))) == NULL) return NULL; list->head = list->tail = NULL; list->len = 0; list->dup = NULL; list->free = NULL; list->match = NULL; return list;}
插入分為從頭部插入和尾部插入,原始碼實現頭部都有非常清晰的注釋,告訴這個函數的一些細節,作者很是用心:
list *listAddNodeHead(list *list, void *value){ listNode *node; if ((node = malloc(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;}
釋放記憶體
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); free(current); current = next; } free(list);}
迭代器的建立,以後可以效仿這種做法,迭代器分方向:
/* Returns a list iterator 'iter'. After the initialization every * call to listNext() will return the next element of the list. * * This function can't fail. */listIter *listGetIterator(list *list, int direction){ listIter *iter; if ((iter = malloc(sizeof(*iter))) == NULL) return NULL; if (direction == AL_START_HEAD) iter->next = list->head; else iter->next = list->tail; iter->direction = direction; return iter;}
Redis源碼-資料結構之Adlist雙端鏈表