1つ:リンクリストとリンクリストノードの実現
1:各リンクリストノードは、adlist.h / listNode構造を使用して以下を表します。
typedef struct listNode {
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
} listNode;
次の図に示すように、複数のlistNodeは、前のポインタと次のポインタを介して両端のリンクリストを形成できます。
複数のlistNode構造がリンクリストを形成できますが、adlist.h / listを使用してリンクリストを保持する場合は操作が便利です。
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関数は、リンクリストノードによって保存された値を解放するために使用されます。
- 一致関数は、ノードによって保存された値が別の入力の値と等しいかどうかを比較するために使用されます。
次の図は、リスト構造と3つのlistNode構造で構成されるリンクリストです。
2:Redisリンクリスト実装の特徴
- ダブルエンド:リンクリストノードにはprevとnextポインターがあり、ノードのpre-nodeとpost-nodeを取得する複雑さはO(1)です。
- 非サイクリック:ヘッドノードの前のポインターとテールの次のポインターはNULLを指し、リンクリストへのアクセスはNULLで終了します。
- ヘッドポインタとテールポインタの場合:リスト構造のヘッドポインタとテールポインタを介して、リンクリストのヘッドノードとテールノードを取得するプログラムの複雑さはo(1)です。
- リンクリスト長カウンター:プログラムはリスト構造のlen属性値を取得してノード数を取得するため、リンクリスト内のノード数を取得する複雑さは0(1)です。
- ポリモーフィズム:リンクリストノードはvoid *ポインターを使用してノード値を格納し、タイプ固有の関数はdup、freeを介してノード値に設定でき、リスト構造の3つの属性に一致するため、リンクリストは次のことができます。さまざまなタイプの値を格納するために使用されます。
3:リンクリストとリンクリストノードのAPI
- listCreate関数は次のように実装されます。
/* Create a new list. The created list can be freed with
* AlFreeList(), but private value of every node need to be freed
* by the user before to call AlFreeList().
*
* On error, NULL is returned. Otherwise the pointer to the new list. */
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;
return list;
}
- listSetDupMethod関数は次のように実装されます。
#define listSetDupMethod(l,m) ((l)->dup = (m))
- listFirst関数は次のように実装されます。
#define listFirst(l) ((l)->head)