C语言实现双向链表

C语言实现双向链表

1. 抽象数据类型定义

定义链表节点结构,链表结构,链表迭代器结构,链表迭代器方向枚举

/*
 * list_t node struct.
 */
typedef struct list_node {
  struct list_node *prev;
  struct list_node *next;
  void *val;
} list_node_t;

/*
 * list_t struct.
 */
typedef struct {
  list_node_t *head;
  list_node_t *tail;
  unsigned int len;
  void (*free)(void *val);
  int (*match)(void *a, void *b);
} list_t;

/*
 * list_t iterator struct.
 */
typedef struct {
  list_node_t *next;
  list_direction_t direction;
} list_iterator_t;

/*
 * list_t iterator direction.
 */
typedef enum {
    LIST_HEAD,
    LIST_TAIL
} list_direction_t;

2. API设计

双向链表对外提供接口,节点元素创建,链表创建/销毁,插入元素,删除元素,查找元素,迭代器创建/销毁

#ifndef LIST_H
#define LIST_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>

#ifndef LIST_MALLOC
#define LIST_MALLOC malloc
#endif

#ifndef LIST_FREE
#define LIST_FREE free
#endif

list_node_t* list_node_new(void *val);
    
list_t* list_new();

list_node_t* list_rpush(list_t *self, list_node_t *node);

list_node_t* list_lpush(list_t *self, list_node_t *node);

list_node_t* list_find(list_t *self, void *val);

list_node_t* list_at(list_t *self, int index);

list_node_t* list_rpop(list_t *self);

list_node_t* list_lpop(list_t *self);

void list_remove(list_t *self, list_node_t *node);

void list_destroy(list_t *self);

list_iterator_t* list_iterator_new(list_t *list, list_direction_t direction);

list_iterator_t* list_iterator_new_from_node(list_node_t *node, list_direction_t direction);

list_node_t* list_iterator_next(list_iterator_t *self);

void list_iterator_destroy(list_iterator_t *self);

#ifdef __cplusplus
}
#endif

#endif /* LIST_H */

3. 接口实现

3.1 节点元素创建
list_node_t* list_node_new(void *val) {
	list_node_t *self;
	if (!(self = LIST_MALLOC(sizeof(list_node_t))))
		return NULL;
	self->prev = NULL;
	self->next = NULL;
	self->val = val;
	return self;
}
3.2 链表创建/销毁
//链表的创建
list_t *list_new() {
    list_t *self = NULL;
    if (!(self = LIST_MALLOC(sizeof(list_t))))
        return NULL;
    self->head = NULL;
    self->tail = NULL;
    self->free = NULL;
    self->match = NULL;
    self->len = 0;
    return self;
}

//链表的销毁
void list_destroy(list_t *self) {
    if (!self)
        return;
    unsigned int len = self->len;
    list_node_t *next = NULL;
    list_node_t *curr = self->head;

    while (len--) {
        next = curr->next;
        if (self->free) self->free(curr->val);
        LIST_FREE(curr);
        curr = next;
    }

    LIST_FREE(self);s
}
3.3 插入元素
  • 链表尾部插入元素
  • 链表头部插入元素
//链表尾部插入元素
list_node_t* list_rpush(list_t *self, list_node_t *node) {
    if (!node)  return NULL;
    if (self->len) {
        node->prev = self->tail;
        node->next = NULL;
        self->tail->next = node;
        self->tail = node;
    } else {
        self->head = self->tail = node;
        node->prev = node->next = NULL;
    }

    ++self->len;
    return node;
}

//链表头部插入元素
list_node_t* list_lpush(list_t *self, list_node_t *node) {
    if (!node || !self) return NULL;
    if (self->len) {
        node->next = self->head;
        node->prev = NULL;
        self->head->prev = node;
        self->head = node;
    } else {
        self->head = self->tail = node;
        node->prev = node->next = NULL;
    }

    ++self->len;
    return node;
}
3.4 删除元素
  • 尾部删除
  • 头部删除
  • 删除链表中的给定节点
//尾部删除
list_node_t* list_rpop(list_t *self) {
    if (!self)
        return NULL;
    if (!self->len) return NULL;
    list_node_t *node = self->tail;

    if (--self->len) {
        (self->tail = node->prev)->next = NULL;
    } else {
        self->tail = self->head = NULL;
    }

    node->next = node->prev = NULL;
    return node;
}

//头部删除
list_node_t* list_lpop(list_t *self) {
    if (!self)
        return NULL;
    if (!self->len) return NULL;
    list_node_t *node = self->head;

    if (--self->len) {
        (self->head = node->next)->prev = NULL;
    } else {
        self->head = self->tail = NULL;
    }

    node->next = node->prev = NULL;
    return node;
}

//给定链表头指针和节点指针,删除节点
void list_remove(list_t *self, list_node_t *node) {
    node->prev
        ? (node->prev->next = node->next)
        : (self->head = node->next);

    node->next
        ? (node->next->prev = node->prev)
        : (self->tail = node->prev);

    if (self->free) self->free(node->val);

    LIST_FREE(node);
    --self->len;
}
3.5 迭代器创建/销毁
//迭代器创建
//Param: 给定链表指针
//        迭代器方向
list_iterator_t* list_iterator_new(list_t *list, list_direction_t direction) {
  list_node_t *node = direction == LIST_HEAD
    ? list->head
    : list->tail;
  return list_iterator_new_from_node(node, direction);
}

//迭代器创建
//Param: 链表节点指针
//        迭代器方向
list_iterator_t* list_iterator_new_from_node(list_node_t *node, list_direction_t direction) {
    list_iterator_t *self;
    if (!(self = LIST_MALLOC(sizeof(list_iterator_t))))
        return NULL;
    self->next = node;
    self->direction = direction;
    return self;
}

//寻找下一个节点
list_node_t* list_iterator_next(list_iterator_t *self) {
    list_node_t *curr = self->next;
    if (curr) {
        self->next = self->direction == LIST_HEAD
            ? curr->next
            : curr->prev;
    }
    return curr;
}

//销毁迭代器
void list_iterator_destroy(list_iterator_t *self) {
    LIST_FREE(self);
    self = NULL;
}
3.6 查找元素
  • 通过给定的内容查找链表中的节点
  • 查找链表中给定下标的节点
//通过给定的内容查找链表中的节点
list_node_t* list_find(list_t *self, void *val) {
    list_iterator_t *it = list_iterator_new(self, LIST_HEAD);
    list_node_t *node;

    while ((node = list_iterator_next(it))) {
        if (self->match) {
            if (self->match(val, node->val)) {
                list_iterator_destroy(it);
                return node;
            }
        } else {
            if (val == node->val) {
                list_iterator_destroy(it);
                return node;
            }
        }
    }

    list_iterator_destroy(it);
    return NULL;
}

//查找链表中给定下标的节点
list_node_t* list_at(list_t *self, int index) {
    list_direction_t direction = LIST_HEAD;

    if (index < 0) {
        direction = LIST_TAIL;
        index = ~index;
    }

    if ((unsigned)index < self->len) {
        list_iterator_t *it = list_iterator_new(self, direction);
        list_node_t *node = list_iterator_next(it);
        while (index--) node = list_iterator_next(it);
        list_iterator_destroy(it);
        return node;
    }

    return NULL;
}

4. 测试

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list.h"

#define test(fn) \
  puts("... " # fn ": \t CALL OK!"); \
  test_##fn();

static int freeProxyCalls = 0;

void freeProxy(void *val) {
  ++freeProxyCalls;
  free(val);
}

typedef struct {
  char *name;
} User;

static int User_equal(User *a, User *b) {
  return 0 == strcmp(a->name, b->name);
}

// Tests
static void test_list_node_new() {
  char *val = "some value";
  list_node_t *node = list_node_new(val);
  assert(node->val == val);
  free(node);
}

static void test_list_rpush() {
  // Setup
  list_t *list = list_new();
  list_node_t *a = list_node_new("a");
  list_node_t *b = list_node_new("b");
  list_node_t *c = list_node_new("c");

  // a b c
  list_rpush(list, a);
  list_rpush(list, b);
  list_rpush(list, c);

  // Assertions
  assert(a == list->head);
  assert(c == list->tail);
  assert(3 == list->len);
  assert(b == a->next);
  assert(NULL == a->prev);
  assert(c == b->next);
  assert(a == b->prev);
  assert(NULL == c->next);
  assert(b == c->prev);

  list_destroy(list);
}

static void test_list_lpush() {
  // Setup
  list_t *list = list_new();
  list_node_t *a = list_node_new("a");
  list_node_t *b = list_node_new("b");
  list_node_t *c = list_node_new("c");

  // c b a
  list_rpush(list, a);
  list_lpush(list, b);
  list_lpush(list, c);

  // Assertions
  assert(c == list->head);
  assert(a == list->tail);
  assert(3 == list->len);
  assert(NULL == a->next);
  assert(b == a->prev);
  assert(a == b->next);
  assert(c == b->prev);
  assert(b == c->next);
  assert(NULL == c->prev);

  list_destroy(list);
}

static void test_list_at() {
  // Setup
  list_t *list = list_new();
  list_node_t *a = list_node_new("a");
  list_node_t *b = list_node_new("b");
  list_node_t *c = list_node_new("c");

  // a b c
  list_rpush(list, a);
  list_rpush(list, b);
  list_rpush(list, c);

  // Assertions
  assert(a == list_at(list, 0));
  assert(b == list_at(list, 1));
  assert(c == list_at(list, 2));
  assert(NULL == list_at(list, 3));

  assert(c == list_at(list, -1));
  assert(b == list_at(list, -2));
  assert(a == list_at(list, -3));
  assert(NULL == list_at(list, -4));

  list_destroy(list);
}

static void test_list_destroy() {
  // Setup
  list_t *a = list_new();
  list_destroy(a);

  // a b c
  list_t *b = list_new();
  list_rpush(b, list_node_new("a"));
  list_rpush(b, list_node_new("b"));
  list_rpush(b, list_node_new("c"));
  list_destroy(b);

  // Assertions
  list_t *c = list_new();
  c->free = freeProxy;
  list_rpush(c, list_node_new(list_node_new("a")));
  list_rpush(c, list_node_new(list_node_new("b")));
  list_rpush(c, list_node_new(list_node_new("c")));
  list_destroy(c);
  assert(3 == freeProxyCalls);
}

static void test_list_find() {
  // Setup
  list_t *langs = list_new();
  list_node_t *js = list_rpush(langs, list_node_new("js"));
  list_node_t *ruby = list_rpush(langs, list_node_new("ruby"));

  list_t *users = list_new();
  users->match = User_equal;
  User userTJ = { "tj" };
  User userSimon = { "simon" };
  User userTaylor = { "taylor" };
  list_node_t *tj = list_rpush(users, list_node_new(&userTJ));
  list_node_t *simon = list_rpush(users, list_node_new(&userSimon));

  // Assertions
  list_node_t *a = list_find(langs, "js");
  list_node_t *b = list_find(langs, "ruby");
  list_node_t *c = list_find(langs, "foo");
  assert(js == a);
  assert(ruby == b);
  assert(NULL == c);

  list_destroy(langs);

  a = list_find(users, &userTJ);
  b = list_find(users, &userSimon);
  c = list_find(users, &userTaylor);
  assert(tj == a);
  assert(simon == b);
  assert(NULL == c);

  list_destroy(users);
}

static void test_list_remove() {
  // Setup
  list_t *list = list_new();
  list_node_t *a = list_rpush(list, list_node_new("a"));
  list_node_t *b = list_rpush(list, list_node_new("b"));
  list_node_t *c = list_rpush(list, list_node_new("c"));

  // Assertions
  assert(3 == list->len);

  list_remove(list, b);
  assert(2 == list->len);
  assert(a == list->head);
  assert(c == list->tail);
  assert(c == a->next);
  assert(NULL == a->prev);
  assert(NULL == c->next);
  assert(a == c->prev);

  list_remove(list, a);
  assert(1 == list->len);
  assert(c == list->head);
  assert(c == list->tail);
  assert(NULL == c->next);
  assert(NULL == c->prev);

  list_remove(list, c);
  assert(0 == list->len);
  assert(NULL == list->head);
  assert(NULL == list->tail);

  list_destroy(list);
}

static void test_list_rpop() {
  // Setup
  list_t *list = list_new();
  list_node_t *a = list_rpush(list, list_node_new("a"));
  list_node_t *b = list_rpush(list, list_node_new("b"));
  list_node_t *c = list_rpush(list, list_node_new("c"));

  // Assertions
  assert(3 == list->len);

  assert(c == list_rpop(list));
  assert(2 == list->len);
  assert(a == list->head);
  assert(b == list->tail);
  assert(a == b->prev);
  assert(NULL == list->tail->next && "new tail node next is not NULL");
  assert(NULL == c->prev && "detached node prev is not NULL");
  assert(NULL == c->next && "detached node next is not NULL");

  free(c);

  assert(b == list_rpop(list));
  assert(1 == list->len);
  assert(a == list->head);
  assert(a == list->tail);

  free(b);

  assert(a == list_rpop(list));
  assert(0 == list->len);
  assert(NULL == list->head);
  assert(NULL == list->tail);

  free(a);

  assert(NULL == list_rpop(list));
  assert(0 == list->len);

  list_destroy(list);
}

static void test_list_lpop() {
  // Setup
  list_t *list = list_new();
  list_node_t *a = list_rpush(list, list_node_new("a"));
  list_node_t *b = list_rpush(list, list_node_new("b"));
  list_node_t *c = list_rpush(list, list_node_new("c"));

  // Assertions
  assert(3 == list->len);

  assert(a == list_lpop(list));
  assert(2 == list->len);
  assert(b == list->head);
  assert(NULL == list->head->prev && "new head node prev is not NULL");
  assert(NULL == a->prev && "detached node prev is not NULL");
  assert(NULL == a->next && "detached node next is not NULL");

  free(a);

  assert(b == list_lpop(list));
  assert(1 == list->len);

  free(b);

  assert(c == list_lpop(list));
  assert(0 == list->len);
  assert(NULL == list->head);
  assert(NULL == list->tail);

  free(c);

  assert(NULL == list_lpop(list));
  assert(0 == list->len);

  list_destroy(list);
}

static void test_list_iterator_t() {
  // Setup
  list_t *list = list_new();
  list_node_t *tj = list_node_new("tj");
  list_node_t *taylor = list_node_new("taylor");
  list_node_t *simon = list_node_new("simon");

  // tj taylor simon
  list_rpush(list, tj);
  list_rpush(list, taylor);
  list_rpush(list, simon);

  // Assertions

  // From head
  list_iterator_t *it = list_iterator_new(list, LIST_HEAD);
  list_node_t *a = list_iterator_next(it);
  list_node_t *b = list_iterator_next(it);
  list_node_t *c = list_iterator_next(it);
  list_node_t *d = list_iterator_next(it);

  assert(a == tj);
  assert(b == taylor);
  assert(c == simon);
  assert(NULL == d);

  list_iterator_destroy(it);

  // From tail
  it = list_iterator_new(list, LIST_TAIL);
  list_node_t *a2 = list_iterator_next(it);
  list_node_t *b2 = list_iterator_next(it);
  list_node_t *c2 = list_iterator_next(it);
  list_node_t *d2 = list_iterator_next(it);

  assert(a2 == simon);
  assert(b2 == taylor);
  assert(c2 == tj);
  assert(NULL == d2);
  list_iterator_destroy(it);

  list_destroy(list);
}

int main(void){
  printf("\nlist_t: %ld\n", sizeof(list_t));
  printf("list_node_t: %ld\n", sizeof(list_node_t));
  printf("list_iterator_t: %ld\n\n", sizeof(list_iterator_t));
  test(list_node_new);
  test(list_rpush);
  test(list_lpush);
  test(list_find);
  test(list_at);
  test(list_remove);
  test(list_rpop);
  test(list_lpop);
  test(list_destroy);
  test(list_iterator_t);
  puts("... CALL END ...");
  return 0;
}

运行输出 :

list_t: 20
list_node_t: 12
list_iterator_t: 8

... list_node_new:      CALL OK!
... list_rpush:         CALL OK!
... list_lpush:         CALL OK!
... list_find:  CALL OK!
... list_at:    CALL OK!
... list_remove:        CALL OK!
... list_rpop:  CALL OK!
... list_lpop:  CALL OK!
... list_destroy:       CALL OK!
... list_iterator_t:    CALL OK!
... CALL END ...

二.内核链表 内核链表是一种链表,Linux内核中的链表都是用这种形式实现的 1.特性 内核链表是一种双向循环链表,内核链表的节点节点结构中只有指针域 使用内核链表的时候,将内核链表作为一个成员放入到一个结构体中使用 我们在链表中找到内核链表结构的地址,通过这个地址就可以找到外部大结构体的地址,通过大结构体就可以访问其中的成员 优势: 内核链表突破了保存数据的限制,可以用内核链表来保存任何数据(使用一种链表表示各种类型的数据,通用性很强) 内核链表中只有指针域,维护起来更加方便,效率更高 2.使用 内核链表在内核中已经被实现,我们只需要调用其接口直接使用即可 内核链表实现代码在内核源代码的list.h文件中 3.源代码分析 (1)节点结构: struct list_head { struct list_head *next, *prev;//前置指针 后置指针 }; (2)初始化 #define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) (3)插入 //从头部插入 static inline void list_add(struct list_head *new, struct list_head *head)//传入要插入的节点和要插入的链表 { __list_add(new, head, head->next); } //从尾部插入 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } (4)通过节点找到外部结构体的地址 //返回外部结构体的地址,第一个参数是节点地址,第二个参数是外部结构体的类型名,第三个参数是节点在外部结构体中的成员名 #define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) (5)遍历内核链表 //遍历内核链表 #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); \ pos = pos->next) //安全遍历内核链表 #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) C语言的双链表,可以增加。插入,删除,修改,销毁等函数接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Erice_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值