若将双向链表结点作为相同或不同 C 复合类型的一员,然后将复合类型中的各链表结点关联成双向链表,从而间接将复合类型变量以双向链表方式进行了管理。
对于大部分双向链表结点的操作都比较高效——甚至不需要判断语句。在合适场景下如此使用双向链表结点,可算得上轻量优雅。
/**
* 根据结构体类型 type 中的名为 mn 成员的地址 ma 获取
* type 结构体类型变量的首地址。*/
#define DL_START_ADDR(ma, type, mn) \
((type *) (((char *)(ma)) - (((type *)0)->mn)))
typedef struct dlNode DL_NODE_S;
struct dlNode
{
struct dlNode *prev;
struct dlNode *next;
};
inline static void
dlInit(DL_NODE_S *head)
{
head->next = head->prev = head;
return ;
}
inline static void
dlAddNext(DL_NODE_S *cur, DL_NODE_S *add)
{
add->next = cur->next;
add->prev = cur;
cur->next->prev = add;
cur->next = add;
return ;
}
inline static void
dlAddPrev(DL_NODE_S *cur, DL_NODE_S *add)
{
add->next = cur;
add->prev = cur->prev;
cur->prev->next = add;
cur->prev = add;
return ;
}
inline static void
dlDel(DL_NODE_S *del)
{
del->next->prev = del->prev;
del->prev->next = del->next;
dlInit(del);
return ;
}
inline static int
dlIsEmpty(DL_NODE_S *head)
{
return head->next == head;
}
inline static void
dlMoveHead(DL_NODE_S *dst, DL_NODE_S *src)
{
if (dlIsEmpty(src)) return ;
dst->next->prev = src->prev;
src->prev->next = dst->next;
dst->next = src->next;
src->next->prev = dst;
dlInit(src);
return ;
}
inline static void
dlMoveTail(DL_NODE_S *dst, DL_NODE_S *src)
{
if (dlIsEmpty(src)) return ;
dst->prev->next = src->next;
src->next->prev = dst->prev;
dst->prev = src->prev;
src->prev->next = dst;
dlInit(src);
return ;
}
|