目录
初始化
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode* prev;
struct ListNode* next;
LTDataType val;
}ListNode;
ListNode* ListInit()
{
ListNode* phead = BuyListNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
初始化的时候把哨兵位的上一个和下一个节点都与自己链接。
删除
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* posprev = pos->prev;
ListNode* posnext = pos->next;
free(pos);
posprev->next = posnext;
posnext->prev = posprev;
}
这里可以删除除了哨兵位头结点的任意位置(尾删,头删都可以直接调用这个函数只需要修改参数即可),因为是双向的所以操作比单链表简单的多
添加
void ListInsert(LTDataType x, ListNode* pos)
{
assert(pos);
ListNode* newnode = BuyListNode(x);
ListNode* posprev = pos->prev;
newnode->next = pos;
newnode->prev = posprev;
posprev->next = newnode;
pos->prev = newnode;
}
ListNode* BuyListNode(LTDataType x)
{
ListNode* newcode = (ListNode*)malloc(sizeof(ListNode));
if (newcode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
else
{
newcode->val = x;
newcode->next = NULL;
newcode->prev = NULL;
}
return newcode;
}
插入的时候创建新节点然后分别与上一个、下一个的头尾都链接起来即可
查找
ListNode* ListFind(LTDataType x, ListNode* plist)
{
assert(plist);
ListNode* cur = plist->next;
while (cur != plist)
{
if (cur->val == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
遍历找即可,需要注意的是结束条件是cur遍历到头结点
销毁
void ListDestory(ListNode* plist)
{
assert(plist);
ListNode* cur = plist->next;
while (cur != plist)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
}
总的来说双向带头循环链表结构复杂但是实现起来要比单链表简单的多,也好用得多。