1.双向链表
1.1双向链表的节点定义

cs
//节点存放数据的类型
typedef int datatype;
/* 节点类型 */
typedef struct node
{
datatype data; //存放数据空间
struct node *ppre; //存放前一个节点地址
struct node *pnext; //存放下一个节点地址
}linknode;
1.2双向链表的创建
申请节点空间,对pnext和ppre赋值为NULL, 返回空白节点地址。
cs
linknode *create_empty_linklist(void)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return NULL;
}
ptmpnode->ppre = NULL;
ptmpnode->pnext = NULL;
return ptmpnode;
}
1.3双向链表头插法
1)申请节点
2)存放数据
3)pnext赋值为phead->pnext
4)ppre赋值为phead的地址
5)phead->pnext赋值为新申请节点地址
6)如果有后一个节点,需要让后一个节点的ppre指向该节点

cs
//双向链表头插
void insert_head_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return;
}
ptmpnode->data = tmpdata;
ptmpnode->pnext = phead->pnext;
ptmpnode->ppre = phead;
phead->pnext = ptmpnode;
if (ptmpnode->pnext != NULL)
{
ptmpnode->pnext->ppre = ptmpnode;
}
return;
}
1.4双向链表的销毁
与单向链表相同
cs
void destroy_linklist(linknode **pphead)//销毁需要传递二级指针,因为要将外部指针指向空
{
linknode *pfreenode = NULL;
linknode *ptmpnode = NULL;
ptmpnode = *pphead;
pfreenode = *pphead;
while(ptmpnode != NULL)
{
ptmpnode = ptmpnode->pnext;
free(pfreenode);
pfreenode = ptmpnode;
}
*pphead = NULL;
}

1.5双向链表的遍历
与单向链表无异
cs
void show_linklist(linknode *phead)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != NULL)//判断下一个节点是不是空
{
printf("%d ", ptmpnode->data);
ptmpnode = ptmpnode->pnext;
}
printf("\n");
return;
}

1.6双向链表的查找
与单向链表相同
cs
//数返回链表中第一个指定元素节点的地址
void find_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
linknode *pprenode = NULL;
pprenode = phead;
ptmpnode = pprenode->pnext;
while (ptmpnode != NULL)
{
if (ptmpnode->data == tmpdata)
{
printf("%p\n",&pprenode->pnext);
break;
}
else
{
ptmpnode = ptmpnode->pnext;
pprenode = pprenode->pnext;
}
}
return;
}

1.7双向链表的修改
与双向链表一致
cs
//将链表中指定元素的值更新为新值
void update_linklist(linknode *phead, datatype olddata, datatype newdata)
{
linknode *ptmpnode = NULL;
ptmpnode = phead;
while (ptmpnode != NULL)
{
if (ptmpnode->data == olddata)
{
ptmpnode->data = newdata;
}
ptmpnode = ptmpnode->pnext;
}
return;
}

1.8双向链表的删除

cs
//删除链表中所有的某一指定元素
void delete_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
linknode *pfreenode;
ptmpnode = phead->pnext;
while (ptmpnode != NULL)
{
if (ptmpnode->data == tmpdata)
{
ptmpnode->ppre->pnext = ptmpnode->pnext;
if(ptmpnode->pnext!=NULL)
{
ptmpnode->pnext->ppre=ptmpnode->ppre;
}
pfreenode = ptmpnode;
ptmpnode = ptmpnode->pnext;
free(pfreenode);
}
else
{
ptmpnode = ptmpnode->pnext;
}
}
return;
}

1.9双向链表的尾插法
1)申请节点
2)将节点的pnext赋值为NULL
3)找到链表最后一个节点
4)将节点的ppre赋值为最后一个节点地址
5)将最后一个节点的pnext赋值为新申请节点
cs
int insert_tail_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
linknode *plastnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return -1;
}
plastnode = phead;
while (plastnode->pnext != NULL)
{
plastnode = plastnode->pnext;
}
ptmpnode->data = tmpdata;
ptmpnode->pnext = NULL;
ptmpnode->ppre = plastnode;
plastnode->pnext = ptmpnode;
return 0;
}
2.循环链表
2.1循环链表的创建
cs
// 创建空链表
linknode *create_empty_linklist(void)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return NULL;
}
ptmpnode->pnext = ptmpnode->ppre = ptmpnode;
return ptmpnode;
}
2.2循环链表头插法
原理图解:

cs
//头插法
void insert_head_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));//申请节点
if (NULL == ptmpnode)
{
perror("fail to malloc");
return;
}
ptmpnode->data = tmpdata;//存放数据
ptmpnode->pnext = phead->pnext;
ptmpnode->ppre = phead;
phead->pnext = ptmpnode;
ptmpnode->pnext->ppre = ptmpnode;
return;
}
2.3循环链表尾插法
原理图解:

cs
//尾插法
void insert_tail_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return;
}
ptmpnode->data = tmpdata;
ptmpnode->pnext = phead;
ptmpnode->ppre = phead->ppre;
phead->ppre->pnext = ptmpnode;
phead->ppre = ptmpnode;
return;
}
2.4循环链表的遍历
++与单向和双向链表不同,其ptmpnod在所有需要遍历的使用场景中,其判定条件均由(ptmpnode!=null)变为了(ptmpnode != phead);++
cs
void show_linklist(linknode *phead)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
printf("%d ", ptmpnode->data);
ptmpnode = ptmpnode->pnext;
}
printf("\n");
return;
}

2.5循环链表元素的查找
与单向链表相同,仅循环判断条件改变
cs
// 链表的查找
linknode *find_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
if (ptmpnode->data == tmpdata)
{
return ptmpnode;
}
ptmpnode = ptmpnode->pnext;
}
return NULL;
}
2.6循环链表元素修改
与单向链表相同,仅循环判断条件改变
cs
// 链表的修改
int update_linklist(linknode *phead, datatype olddata, datatype newdata)
{
linknode *ptmpnode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
if (ptmpnode->data == olddata)
{
ptmpnode->data = newdata;
}
ptmpnode = ptmpnode->pnext;
}
return 0;
}
2.7循环链表元素的删除
与单向链表相同,仅循环判断条件改变
cs
// 链表节点的删除
int delete_linklist(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
linknode *pfreenode = NULL;
ptmpnode = phead->pnext;
while (ptmpnode != phead)
{
if (ptmpnode->data == tmpdata)
{
ptmpnode->ppre->pnext = ptmpnode->pnext;
ptmpnode->pnext->ppre = ptmpnode->ppre;
pfreenode = ptmpnode;
ptmpnode = ptmpnode->pnext;
free(pfreenode);
}
else
{
ptmpnode = ptmpnode->pnext;
}
}
return 0;
}
2.8循环链表的销毁
与单向链表相同,仅循环判断条件改变
cs
// 链表的销毁
int destroy_linklist(linknode **pphead)
{
linknode *ptmpnode = NULL;
linknode *pfreenode = NULL;
ptmpnode = (*pphead)->pnext;
pfreenode = ptmpnode;
while (ptmpnode != *pphead)
{
ptmpnode = ptmpnode->pnext;
free(pfreenode);
pfreenode = ptmpnode;
}
free(*pphead);
*pphead = NULL;
return 0;
}
3.内核链表
参考list.h中关于内核链表的常见操作:
cs
/*
*/
Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
#ifndef _LLIST_H
#define _LLIST_H
/* 内核链表中的节点类型 */
struct list_head {
struct list_head *next;
struct list_head *prev;
};
/* 初始化空白头结点 */
#define INIT_LIST_HEAD(head) do {
\
(head)->next = (head)->prev = head; \
} while (0)
/* 头插法 */
static inline void
list_add (struct list_head *new, struct list_head *head)
{
new->prev = head;
new->next = head->next;
new->prev->next = new;
new->next->prev = new;
}
/* 尾插法 */
static inline void
list_add_tail (struct list_head *new, struct list_head *head)
{
new->next = head;
new->prev = head->prev;
new->prev->next = new;
new->next->prev = new;
}
/* 按指定顺序插入 */
/* This function will insert the element to the list in a order.
Order will be based on the compare function provided as a input.
If element to be inserted in ascending order compare should return:
0: if both the arguments are equal
>0: if first argument is greater than second argument
<0: if first argument is less than second argument */
static inline void
list_add_order (struct list_head *new, struct list_head *head,
int (*compare)(struct list_head *, struct list_head *))
{
struct list_head *pos = head->prev;
while ( pos != head ) {
if (compare(new, pos) >= 0)
break;
/* Iterate the list in the reverse order. This will
have
better efficiency if the elements are inserted in
the
ascending order */
pos = pos->prev;
}
list_add (new, pos);
}
/* 将节点移出所属的链表 */
static inline void
list_del (struct list_head *old)
{
old->prev->next = old->next;
old->next->prev = old->prev;
old->next = (void *)0xbabebabe;
old->prev = (void *)0xcafecafe;
}
/* 将节点移出所属的链表,并初始化 */
static inline void
list_del_init (struct list_head *old)
{
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
old->prev->next = old->next;
old->next->prev = old->prev;
old->next = old;
old->prev = old;
}
/* 将节点移动到另一个链表的头部 */
static inline void
list_move (struct list_head *list, struct list_head *head)
{
list_del (list);
list_add (list, head);
}
/* 将节点移动到另一个链表的尾部 */
static inline void
list_move_tail (struct list_head *list, struct list_head *head)
{
list_del (list);
list_add_tail (list, head);
}
/* 判断链表是否为空 */
static inline int
list_empty (struct list_head *head)
{
return (head->next == head);
}
/* 将list链表所有元素拼到head链表的前面 */
static inline void
__list_splice (struct list_head *list, struct list_head *head)
{
(list->prev)->next = (head->next);
(head->next)->prev = (list->prev);
(head)->next = (list->next);
(list->next)->prev = (head);
}
/* 将list链表所有元素拼到head链表的前面 */
static inline void
list_splice (struct list_head *list, struct list_head *head)
{
if (list_empty (list))
return;
__list_splice (list, head);
}
/* 将list链表所有元素拼到head链表的前面,并初始化list头结点 */
/* Splice moves @list to the head of the list at @head. */
static inline void
list_splice_init (struct list_head *list, struct list_head *head)
{
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
if (list_empty (list))
return;
__list_splice (list, head);
INIT_LIST_HEAD (list);
}
/* 将list链表所有元素追加到head链表的后面 */
static inline void
__list_append (struct list_head *list, struct list_head *head)
{
(head->prev)->next = (list->next);
(list->next)->prev = (head->prev);
(head->prev) = (list->prev);
(list->prev)->next = head;
}
/* 将list链表所有元素追加到head链表的后面 */
static inline void
list_append (struct list_head *list, struct list_head *head)
{
if (list_empty (list))
return;
__list_append (list, head);
}
/* 将list链表所有元素追加到head链表的后面,并初始化list */
/* Append moves @list to the end of @head */
static inline void
list_append_init (struct list_head *list, struct list_head *head)
{
if (list_empty (list))
return;
__list_append (list, head);
INIT_LIST_HEAD (list);
}
/* 判断当前节点是否为最后一个节点 */
static inline int
list_is_last (struct list_head *list, struct list_head *head)
{
return (list->next == head);
}
/* 判断链表是否只有一个节点 */
static inline int
list_is_singular(struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
/* 将旧节点用新节点替换 */
/**
* list_replace - replace old entry by new one
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
/* 将旧节点用新节点替换,并初始化旧节点 */
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/* 内核链表左旋 */
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void list_rotate_left (struct list_head *head)
{
struct list_head *first;
if (!list_empty (head)) {
first = head->next;
list_move_tail (first, head);
}
}
/* 根据链表节点地址找到数据元素首地址 */
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/* 找到第一个数据元素地址 */
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/* 找到最后一个数据元素地址 */
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/* 找到下一个数据元素地址 */
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, typeof(*(pos)), member)
/* 找到上一个数据元素地址 */
#define list_prev_entry(pos, member) \
list_entry((pos)->member.prev, typeof(*(pos)), member)
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/* 遍历链表节点元素地址 */
#define list_for_each(pos, head)
\
for (pos = (head)->next; pos != (head); pos = pos->next)
/* 遍历所有数据元素首地址 */
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/* 遍历所有数据元素首地址(可以在遍历过程中修改数据元素指针) */
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/* 倒着遍历所有数据元素首地址 */
#define list_for_each_entry_reverse(pos, head, member)
\
for (pos = list_entry((head)->prev, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/* 倒着遍历所有数据元素首地址(可以在遍历过程中修改数据元素指针) */
#define list_for_each_entry_safe_reverse(pos, n, head, member)
\
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* This list implementation has some advantages, but one disadvantage:
you
* can't use NULL to check whether you're at the head or tail. Thus,
the
* address of the head has to be an argument for these macros.
*/
/* 获得下一个数据元素空间首地址,如果没有返回NULL */
#define list_next(ptr, head, type, member) \
(((ptr)->member.next == head) ? NULL \
: list_entry((ptr)->member.next, type,
member))
/* 获得上一个数据元素空间首地址,如果没有返回NULL */
#define list_prev(ptr, head, type, member) \
(((ptr)->member.prev == head) ? NULL \
: list_entry((ptr)->member.prev, type,
member))
#endif /* _LLIST_H */