普通链表:
我们经常使用的普通链表是每个节点的next指针指向下一个节点的首地址:
具体代码实现如下:
struct link
{
int data;
struct link* next;
}
普通链表的缺点:
- 一条链表上的所有节点的数据类型需要完全一致
- 对某条链表的操作如插入,删除等只能对这种类型的链表进行操作,如果链表的类型换了,就要重新再封装出一套一样的操作,泛化能力差;
侵入式链表:
侵入式链表的节点的链接成员指向的是下一个节点的链接成员:
节点结构如下:
typedef struct list_structure
{
struct list_structure* next;
}ListObj;
typedef struct
{
int data;
ListObj list;
} Node;
侵入式链表的优点:
- 节点类型无需一致,只需要包含
ListObj
成员即可 - 泛化能力强,所有链表的操作方式均可统一;
如何访问侵入式链表中的节点元素?首先要掌握两个内容:
学会这两个内容就能明白是如何对节点进行操作的了。
完整代码:
头文件:
#ifndef _LIST_H
#define _LIST_H
#define offset_of(type, member) (unsigned long) &((type*)0)->member
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offset_of(type,member) );})
typedef struct list_structure
{
struct list_structure* next;
struct list_structure* prev;
}ListObj;
#define LIST_HEAD_INIT(name) {&(name), &(name)}
#define LIST_HEAD(name) ListObj name = LIST_HEAD_INIT(name)
#define list_entry(node, type, member) \
container_of(node, type, member)
#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)
void list_init(ListObj* list);
void list_insert_after(ListObj* list, ListObj* node);
void list_insert_before(ListObj* list, ListObj* node);
void list_remove(ListObj* node);
int list_isempty(const ListObj* list);
unsigned int list_len(const ListObj* list);
#endif
源文件:
#include "link_list.h"
void list_init(ListObj* list)
{
list->next = list->prev = list;
}
void list_insert_after(ListObj* list, ListObj* node)
{
list->next->prev = node;
node->next = list->next;
list->next = node;
node->prev = list;
}
void list_insert_before(ListObj* list, ListObj* node)
{
list->prev->next = node;
node->prev = list->prev;
list->prev = node;
node->next = list;
}
void list_remove(ListObj* node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
node->next = node->prev = node;
}
int list_isempty(const ListObj* list)
{
return list->next == list;
}
unsigned int list_len(const ListObj* list)
{
unsigned int len = 0;
const ListObj* p = list;
while (p->next != list)
{
p = p->next;
len++;
}
return len;
}