文章目录
前言
这里讨论的是带头双向链表
1. 双向链表的初始化
ListNode* BuyLTNode(LTDataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
perror("malloc fail");
return NULL;
}
newnode->prev = NULL;
newnode->next = NULL;
newnode->data = x;
return newnode;
}
ListNode* ListCreate()
{
ListNode* pHead;
pHead = BuyLTNode(-1);
pHead->prev = pHead;
pHead->next = pHead;
return pHead;
}
- 返回值为ListNode*,用结构体指针接收,这个指针指向的就是双向链表的头节点
2.双向链表的打印
void ListPrint(ListNode* pHead)
{
assert(pHead);
printf("哨兵位<==>");
ListNode* cur = pHead;
cur = cur->next;
while (cur != pHead)
{
printf("%d<==>", cur->data);
cur = cur->next;
}
printf("\n");
}
3.双向链表的尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListInsert(pHead,x);
/*ListNode* tail = pHead->prev;
ListNode* newnode = BuyLTNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = pHead;
pHead->prev = newnode;*/
}
4.双向链表的尾删
void ListPopBack(ListNode* pHead)
{
assert(pHead);
assert(!ListEmpty(pHead));
/*ListNode* tail = pHead->prev;
ListNode* prevnode = tail->prev;
prevnode->next = pHead;
pHead->prev = prevnode;
free(tail);*/
ListErase(pHead->prev);
}
5.双向链表的判空
bool ListEmpty(ListNode* phead)
{
assert(phead);
return phead == phead->next;
}
6.双向链表的头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListInsert(pHead->next, x);
/*ListNode* nextnode = pHead->next;
ListNode* newnode = BuyLTNode(x);
pHead->next = newnode;
newnode->next = nextnode;
newnode->prev = pHead;
nextnode->prev = newnode;*/
}
7.双向链表的头删
void ListPopFront(ListNode* pHead)
{
assert(pHead);
assert(!ListEmpty(pHead));
/*ListNode* first = pHead->next;
ListNode* second = first->next;
second->prev = pHead;
pHead->next = second;
free(first);*/
ListErase(pHead->next);
}
8.双向链表的查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
if (cur->data == x)
{
return cur;
}
}
return NULL;
}
9.双向链表的删除
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prevnode = pos->prev;
ListNode* nextnode = pos->next;
prevnode->next = nextnode;
nextnode->prev = prevnode;
free(pos);
}
10.双向链表的销毁
void ListDestory(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
ListNode* del = cur;
cur = cur->next;
free(del);
}
free(pHead);
}
11.在pos节点(任意位置)之前插入
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* cur = pos;
ListNode* prevnode = pos->prev;
ListNode* next = pos;
ListNode* newnode = BuyLTNode(x);
prevnode->next = newnode;
newnode->prev = prevnode;
newnode->next = pos;
pos->prev = newnode;
}
- 我们发现,其实链表的头插头删,尾插尾删,可以用 ListInsert,ListErase来实现,这样大大提高了我们效率
- 并且不像单链表一样,部分函数的实现还需要分情况讨论,双向链表函数代码不需要分情况讨论