在FreeBSD中有queue.h这样一个头文件(Linux也有),它定义了一系列的宏操作,实现了双向链表,双端队列和循环链表。
下面给出一些链表常用操作的例子:
#include<stdio.h>
#include<stdlib.h>
#include<sys/queue.h>
struct element{
int num;
/*LIST_ENTRY 创建了一个匿名结构体,这个结构体有两个成员,
分别为struct element* le_next;
struct element** le_prev;
即,elements的类型就是这个匿名的结构体,
使得element成为双向链表中的节点
*/
LIST_ENTRY(element) elements;
};
int main(void){
/*LIST_HEAD 会自动构建一个名为listh的结构体,
里面含有一个element指针 *lh_first
这里的name一般没有什么用处,但是尽量注意有多个链表时,name不要相同造成冲突。
*/
LIST_HEAD(listh,element) head;
struct element *n1,*np;
//链表使用前,需要初始化
LIST_INIT(&head);
n1 = (struct element*)malloc(sizeof(struct element));
n1->num = 1;
//各种插入方式
//插入到链表前端
/*
对于LIST_INSERT_HEAD为何需要用指针域作为参数,
因为指针域的名字是用户自己定义的,函数内部并不知道,
所以需要作为参数传入
*/
LIST_INSERT_HEAD(&head,n1,elements);
n1 = (struct element*)malloc(sizeof(struct element));
n1->num = 2;
//插入到某个节点之后,这里是插入到第一个节点之后
LIST_INSERT_AFTER(LIST_FIRST(&head),n1,elements);
n1 = (struct element*)malloc(sizeof(struct element));
n1->num=3;
//插入到某个节点之前
LIST_INSERT_BEFORE(LIST_FIRST(&head),n1,elements);
//遍历链表
//方法一
for(np=LIST_FIRST(&head);np!=NULL;np=LIST_NEXT(np,elements)){
printf("%d ",np->num);
}
//方法二(推荐)
LIST_FOREACH(np,&head,elements){
printf("%d ",np->num);
}
//方法三(最原始)
for(np=(head).lh_first;np!=NULL;np=np->elements.le_next){
printf("%d ",np->num);
}
//删除,释放链表
while(LIST_FIRST(&head)){
struct element* tmp = LIST_FIRST(&head);
LIST_REMOVE(tmp,elements);
free(tmp);
}
return 0;
}