hello 大家好呀,今天向大家分享的是双链表增删查改接口的实现,如果哪里有什么不对的地方希望各位佬帮忙指正一下。
这次博主分享的是带头双向循环链表:
目录
- ListNode* ListNodeCreat(LTDataType x)
- {
- ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
- if (newnode)
- {
- newnode->data = x;
- newnode->next = NULL;
- newnode->prev = NULL;
- }
- return newnode;
- }
-
-
- ListNode* InitList(void)
- {
- ListNode* phead = ListNodeCreat(1);
- phead->next = phead;
- phead->prev = phead;
- return phead;
- }
链表的初始化我们将phead的prev与next都指向phead,这里的处理在后面有一些妙用,这里就先不说了,头结点这里是通过返回值实现的,当然,通过二级指针也可以,效果都差不多。头结点是不存储数据的,只是充当哨兵的作用。
尾插的具体代码:
- void ListPushBack(ListNode* phead, LTDataType x)
- {
- assert(phead);
- ListNode* tail = phead->prev;
- ListNode* newtail = ListNodeCreat(x);
- tail->next = newtail;
- newtail->prev = tail;
- newtail->next = phead;
- phead->prev = newtail;
-
- //ListInsert(phead, x);
- }
尾插的实现很简单,都能够看懂。在这里我们就可以看见将phead的prev与next都指向phead的好处了,就算phead后面一个结点都没有依然能够处理,这样写代码就很简练了。
头插的具体代码:
- void ListPushFront(ListNode* phead, LTDataType x)
- {
- assert(phead);
- ListNode* next = phead->next;
- ListNode* newnode = ListNodeCreat(x);
- phead->next = newnode;
- newnode->prev = phead;
- newnode->next = next;
- next->prev = newnode;
-
- //ListInsert(phead->next, x);
- }
头插的实现也比较简单,其实把图画好就能够解决问题,这里当头结点后面一个结点都没有也能够处理。
来看看效果:

尾删和头删对于双链表来说也比较简单,这里就放在一起写了:
- void ListPopBack(ListNode* phead)
- {
- assert(phead);
- ListNode* tail = phead->prev;
- ListNode* prev = tail->prev;
- prev->next = phead;
- phead->prev = prev;
- free(tail);
-
- //ListErase(phead->prev);
- }
-
- void ListPopFront(ListNode* phead)
- {
- assert(phead);
- ListNode* next = phead->next->next;
- free(phead->next);
- phead->next = next;
- next->prev = phead;
-
- //ListErase(phead->next);
-
- }
按部就班的写,注意不要写漏了就ok了。
效果:

查找的具体代码:
- ListNode* ListFind(ListNode* phead, LTDataType x)
- {
- assert(phead);
- ListNode* cur = phead->next;
- while (cur != phead)
- {
- if (cur->data == x)
- {
- return cur;
- }
- else
- {
- cur = cur->next;
- }
- }
- return NULL;
- }
与单链表一样,这个也可以改变数据:

查插的具体代码:
- void ListInsert(ListNode* pos, LTDataType x)
- {
- assert(pos);
- ListNode* prev = pos->prev;
- ListNode* newnode = ListNodeCreat(x);
- prev->next = newnode;
- newnode->prev = prev;
- newnode->next = pos;
- pos->prev = newnode;
- }
这里是在pos位前面插入数据,实现起来也比较简单。
查删的具体代码:
- void ListErase(ListNode* pos)
- {
- assert(pos);
- ListNode* prev = pos->prev;
- ListNode* next = pos->next;
- prev->next = next;
- next->prev = prev;
- free(pos);
- }
有了查删和查插后我们不难发现,头插和尾插都可以用查插实现,头删和尾删都可以用查删实现。
头插在 phead->next前插入,尾插在phead前插入,头删位置为phead->next,尾删位置为phead->prev.
在上面实现代码的时候注释掉的就是这种方法。
- void ListDestroy(ListNode* phead)
- {
- ListNode* cur = phead;
- ListNode* next = phead->next;
- while (cur->next!=phead)
- {
- free(cur);
- cur = next;
-
- next = next->next;
- }
-
- }
释放链表与单链表差不多,比较容易理解。
好了,今天的分享就到这里了,如果该文对你有帮助的话能不能3连支持一下博主呢?
