这里写自定义目录标题
带头双向循环链表
与单链表的区别

代码的实现
接口
ListNode* ListCreate();
ListNode* BuyListNode(ListNode* pHead);
void ListDestory(ListNode* pHead);
void ListPrint(ListNode* pHead);
void ListPushBack(ListNode* pHead, LTDataType x);
void ListPopBack(ListNode* pHead);
void ListPushFront(ListNode* pHead, LTDataType x);
void ListPopFront(ListNode* pHead);
ListNode* ListFind(ListNode* pHead, LTDataType x);
void ListInsert(ListNode* pos, LTDataType x);
void ListErase(ListNode* pos);
节点的构造
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;
struct ListNode* prev;
}ListNode;
初始化链表
ListNode* ListCreate()
{
ListNode* plist = (ListNode*)malloc(sizeof(ListNode));
if (plist == NULL)
{
perror("ListCreat fail:");
exit(-1);
}
plist->next = plist;
plist->prev = plist;
return plist;
}
开辟节点
ListNode* BuyListNode(LTDataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
perror("creatnode fail:");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
销毁链表
void ListDestory(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead;
pHead->prev->next = NULL;
while (cur!=NULL)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
return;
}
打印链表
void ListPrint(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
printf("%d->", cur->data);
cur = cur->next;
}printf("NULL\n");
return;
}
尾插链表
void ListPushBack(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* newnode = BuyListNode(x);
ListNode* tail=pHead->prev;
tail->next = newnode;
newnode->prev = tail;
pHead->prev = newnode;
newnode->next = pHead;
}
尾删链表
void ListPopBack(ListNode* pHead)
{
assert(pHead);
if (pHead->prev == pHead)
return;
ListNode* tail = pHead->prev;
ListNode* tailprev = tail->prev;
free(tail);
tailprev->next = pHead;
pHead->prev = tailprev;
return;
}
头插链表
void ListPushFront(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* newnode = BuyListNode(x);
ListNode* next = pHead->next;
pHead->next = newnode;
newnode->prev = pHead;
newnode->next = next;
next->prev = newnode;
return;
}
头删链表
void ListPopFront(ListNode* pHead)
{
assert(pHead);
if (pHead->next == pHead)
return;
ListNode* next = pHead->next;
ListNode* nextNext = next->next;
free(next);
pHead->next = nextNext;
nextNext->prev = pHead;
return;
}
查找链表
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
链表pos位置的删除
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* next = pos->next;
free(pos);
prev->next = next;
next->prev = prev;
return;
}
总结
- 我们在实现的时候可以看出其实带头双向循环链表实现起来并不难,而且在双向循环特点的加持下,在一些方面显得格外方便。
- 但我们仍要熟练掌握带头双向循环链表的结构和实现方式,因为这是一种特别且方便的结构,且用处十分强大。