说明
双向链表作为链表数据结构的一种,使用广泛且方便,特别是在操作系统内核的任务调度中。
用C语言实现一般的双向链表比较简单。如下:
typedef struct LIST{
struct LIST *next;
struct LIST *previous;
int32_t Data;
} LIST;
inline void ListInit(LIST *list_head)
{
list_head->next = list_head;
list_head->previous = list_head;
}
inline void List_BehindInsert(LIST *head, LIST *element)
{//insert after head
element->previous = head;
element->next = head->next;
head->next->previous = element;
head->next = element;
}
inline void List_ForeInsert(LIST *head, LIST *element)
{//insert before head
element->previous = head->previous;
element->next = head;
head->previous->next = element;
head->previous = element;
}
inline void list_delete(LIST *element)
{
element->previous->next = element->next;
element->next->previous = element->previous;
}
我们分析发现,这种链表每个节点会存储前节点地址、后节点地址、当前节点数据。因此这样构造出的双向链表只能用来存放int32_t类型数据,如果我们想存放float类型数据,就需要重新定义结构体为:
typedef struct LIST{
struct LIST *next;
struct LIST *previous;
float Data;
} LIST;
并且无法在一个链表中同时存放float数据和int32_t数据,比如第一个节点存放int32_t,第二个节点存放float,第三个节点存放结构体…
实现
因此,可以采用下面代码来实现指向结构体的链表,或者说是可以存放不同数据的链表:
#define ListEntry(Node, Type, Member) ((Type *)((uint8_t *)(Node) - (uint32_t)(&((Type *)0)->Member)))
//上面宏定义功能:根据结构体中存在的链表节点的地址找到链表节点所在的结构体
typedef struct LIST
{
struct LIST *next;
struct LIST *previous;
} LIST;
inline void list_init(LIST *list_head)
{
list_head->next = list_head;
list_head->previous = list_head;
}
inline void List_BehindInsert(LIST *head, LIST *element)
{//insert after head
element->previous = head;
element->next = head->next;
head->next->previous = element;
head->next = element;
}
inline void List_ForeInsert(LIST *head, LIST *element)
{//insert before head
element->previous = head->previous;
element->next = head;
head->previous->next = element;
head->previous = element;
}
inline void list_delete(LIST *element)
{
element->previous->next = element->next;
element->next->previous = element->previous;
}
typedef struct
{
int16_t temp1;
LIST MyList;
}Point_INT16;
typedef struct
{
float temp1;
LIST MyList;
}Point_float;
void main(void)
{
Point_INT16 FirstNode;
Point_float SecondNode;
LIST StartPoint;
FirstNode.temp1 = 520;
SecondNode.temp1 = 521.1314000;
cout.precision(7);
list_init(&StartPoint);
List_BehindInsert(&StartPoint,&SecondNode.MyList);
List_BehindInsert(&StartPoint,&FirstNode.MyList);
cout<<"第一个节点内容"<<ListEntry(StartPoint.next,Point_INT16,MyList)->temp1<<endl;
cout<<"第二个节点内容"<<ListEntry(StartPoint.next->next,Point_float,MyList)->temp1<<endl;
cout<<"循环3个节点内容"<<ListEntry(StartPoint.next->next->next->next,Point_INT16,MyList)->temp1<<endl;
cout<<"循环4个节点内容"<<ListEntry(StartPoint.next->next->next->next->next,Point_float,MyList)->temp1<<endl;
}
执行结果如下: