双向链表访问节点的前一个和后一个节点的效率非常高,并且freeRTOS中也是使用的双向循环链表,自己实现一个含有头结点的双向循环链表,链表操作包括初始化和头添加、尾添加 、删除等操作。
头节点结构如下:lenght表示list节点个数,刚开始头节点的下一个和前一个节点都是指向自己。
有数据的list示意图如下
需要注意的是,无论删除还是增加节点,都需要调整4个指针位置,删除的时候需要保存后一个节点。下面是测试
#include <stdio.h>
#include <stdlib.h>
typedef struct list
{
int data;
struct list *next;
struct list *prev;
}LIST;
typedef struct head //表示头结点,
{
int lengh;
LIST head;
}HEAD;
// 生成一个节点
LIST *node_new(int data)
{
LIST *node = (LIST *)calloc(1,sizeof(LIST));
if(NULL == node)
{
return NULL;
}
node->data = data;
node->next = NULL;
node->prev = NULL;
return node;
}
//释放节点
void free_node(LIST *node)
{
free(node);
}
//节点插入,prev me next 之间
void node_insert(LIST *prev, LIST *me, LIST *next)
{
prev->next = me;
me->next = next;
me->prev = prev;
next->prev = me;
}
//节点移除
void node_move(LIST *me)
{
me->prev->next = me->next;
me->next->prev = me->prev;
}
//双向链表初始化
HEAD *list_init(void)
{
HEAD *node_head = (HEAD *)calloc(1, sizeof(HEAD));
if(NULL == node_head)
{
return NULL;
}
LIST *node = &node_head->head;//指向自己
node->prev = node;
node->next = node;
node_head->lengh =0;
return node_head;
}
//销毁双向链表,只是留下头结VOID
void list_destory(HEAD *head)
{
if(head == NULL)
{
return;
}
LIST *dummy = &head->head;
while (dummy->next != NULL)
{
LIST *node = dummy->next;
node_move(node);
free_node(node);
head->lengh--;
}
}
// 获取第一个节点
LIST * get_first_node(HEAD *head)
{
if(head->lengh == 0)
{
return NULL;
}
return head->head.next;
}
// 获取第一个节点
LIST * get_last_node(HEAD *head)
{
if(head->lengh == 0)
{
return NULL;
}
return head->head.prev;
}
// 获取第n个节点
LIST * get_node(HEAD *head, int num)
{
if(NULL ==head)
{
return NULL;
}
LIST *node = &head->head;
for(int i= 0; i < num; i++)
{
node =node->next;
}
return node;
}
int add_node_to_list_head(HEAD *head, int data)
{
//创建节点
LIST *new_node = NULL;
new_node = node_new(data);
if(new_node == NULL)
{
return -1;
}
head->lengh++;
// 保存添加前的首节点
LIST *temp_next = head->head.next;
// 先处理新节点左边指针
head->head.next = new_node;
new_node->prev = &head->head;
//再处理新节点的右边指针
new_node->next = temp_next;
temp_next->prev = new_node;
return 0;
}
int add_node_to_list_tail(HEAD *head, int data)
{
//创建节点
LIST *new_node = NULL;
new_node = node_new(data);
if(new_node == NULL)
{
return -1;
}
printf("new_node%p\n",new_node);
head->lengh++;
//先找到插入前最后一个节点
LIST *last_node = &head->head;
printf("last_node%p\n",last_node);
// 插入前最后节点的next为新的节点
while(last_node->next != &head->head)//找到最后一个节点
{
last_node = last_node->next;
}
last_node->next = new_node;
new_node->prev = last_node;
head->head.prev = new_node;
new_node->next = &head->head;
return 0;
}
int delate_node_from_list(HEAD *head, int data)
{
if(NULL == head)
{
return -1;
}
//如果list为NULL返回
if(head->head.next == NULL)
{
printf("list is null");
return -1;
}
LIST *node = head->head.next;
while(node->data != data )
{
if(&head->head == node)//循环结束
{
printf("can not find this node\n");
return -1;
}
node = node->next;
}
//找到目标node 先保存目标node的下一个 和前一个
LIST *last_node = node->next;
LIST *befor_node = node->prev;
befor_node->next = last_node;
last_node->prev = befor_node;
free_node(node);
return 0;
}
int parse_list(HEAD *head)
{
if(NULL == head)
{
return -1;
}
LIST *list_head = &head->head;
LIST *tmp_node = list_head->next;
while(tmp_node != list_head)
{
printf("data:%d\n",tmp_node->data);
tmp_node = tmp_node->next;
}
return 0;
}
int main()
{
HEAD *list_head = list_init();
#if 0
add_node_to_list_head(list_head, 10);
add_node_to_list_head(list_head, 11);
add_node_to_list_head(list_head, 12);
parse_list(list_head);
printf("okokokok\n");
#endif
add_node_to_list_tail(list_head, 10);
add_node_to_list_tail(list_head, 11);
parse_list(list_head);
delate_node_from_list(list_head, 10);
delate_node_from_list(list_head, 11);
parse_list(list_head);
return 0;
}
代码