作者:旧梦拾遗186
专栏:数据结构成长日记
文章来源地址https://www.toymoban.com/news/detail-514000.html
前言:
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。
现在我们来通过代码实现带头双向循环链表,结构上虽然是链表最复杂的,但是并没有我们想象的那么困难,恰恰相反,其代码实现比较简单
带头双向链表样例:
代码实现
List.h
#pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h> typedef int LTDataType; typedef struct ListNode { struct ListNode* next; struct ListNode* prev; LTDataType data; }LTNode; LTNode* ListInit(); void ListPrint(LTNode* phead); void ListPushBack(LTNode* phead, LTDataType x); void ListPushFront(LTNode* phead, LTDataType x); void ListPopBack(LTNode* phead); void ListPopFront(LTNode* phead); bool ListEmpty(LTNode*phead); size_t ListSize(LTNode*phead); LTNode* ListFind(LTNode* phead,LTDataType x); //在pos之前插入 void ListInsert(LTNode* pos, LTDataType x); //删除pos位置 void ListErase(LTNode* pos); void ListDestory(LTNode* phead);
List.c
#include "List.h" LTNode* ListInit() { LTNode* guard = (LTNode*)malloc(sizeof(LTNode)); if (guard == NULL) { perror("malloc fail"); exit(-1); } guard->next = guard; guard->prev = guard; return guard; } LTNode* BuyListNode(LTDataType x) { LTNode* node = (LTNode*)malloc(sizeof(LTNode)); if (node == NULL) { perror("malloc fail"); exit(-1); } node->next = NULL; node->prev = NULL; node->data = x; return node; } void ListPrint(LTNode* phead) { assert(phead); printf("phead<=>"); LTNode* cur = phead->next; while (cur != phead) { printf("%d<=>", cur->data); cur = cur->next; } printf("\n"); } void ListPushBack(LTNode* phead, LTDataType x) { assert(phead); LTNode* newnode = BuyListNode(x); LTNode* tail = phead->prev; tail->next = newnode; newnode->prev = tail; newnode->next = phead; phead->prev = newnode; } void ListPushFront(LTNode* phead, LTDataType x) { assert(phead); LTNode* newnode = BuyListNode(x); //考虑先后顺序 /*newnode->next = phead->next; phead->next->prev = newnode; phead->next = newnode; newnode->prev = phead;*/ //记录下一位,就不用考虑顺序 LTNode* first = phead->next; phead->next = newnode; newnode->prev = phead; newnode->next = first; first->prev = newnode; } void ListPopBack(LTNode* phead) { assert(phead); assert(!ListEmpty(phead)); LTNode* tail = phead->prev; LTNode* prev = tail->prev; prev->next = phead; phead->prev = prev; free(tail); tail = NULL; } void ListPopFront(LTNode* phead) { assert(phead); assert(!ListEmpty(phead)); LTNode* first = phead->next; LTNode* second = first->next; phead->next = second; second->prev = phead; free(first); first = NULL; } bool ListEmpty(LTNode* phead) { assert(phead); return phead->next == phead; } size_t ListSize(LTNode*phead) { assert(phead); size_t n = 0; LTNode* cur = phead->next; while (cur != phead) { ++n; cur = cur->next; } return n; } LTNode* ListFind(LTNode* phead, int x) { assert(phead); size_t n = 0; LTNode* cur = phead->next; while (cur != phead) { if (cur->data == x) { return cur; } } return NULL; } //在pos之前插入 void ListInsert(LTNode* pos, LTDataType x) { assert(pos); LTNode* prev = pos->prev; LTNode* newnode = BuyListNode(x); prev->next = newnode; newnode->prev = prev; newnode->next = pos; pos->prev = newnode; } //删除pos位置 void ListErase(LTNode* pos) { assert(pos); LTNode* prev = pos->prev; LTNode* next = pos->next; prev->next = next; next->prev = prev; free(pos); } //可以传二级,内部置空 //一级指针外部置空 void ListDestory(LTNode* phead) { assert(phead); LTNode* cur = phead->next; while (cur != phead) { LTNode* next = cur->next; free(cur); cur = next; } free(phead); }
test.c
#include "List.h" //测试尾插、头插、尾删、打印 void TestList1() { LTNode* plist = ListInit(); ListPushBack(plist, 1); ListPushBack(plist, 2); ListPushBack(plist, 3); ListPushBack(plist, 4); ListPrint(plist); ListPushFront(plist, 10); ListPushFront(plist, 20); ListPushFront(plist, 30); ListPushFront(plist, 40); ListPrint(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPrint(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPrint(plist); ListPopBack(plist); ListPrint(plist); } //测试头删、销毁 void TestList2() { LTNode* plist = ListInit(); ListPushBack(plist, 1); ListPushBack(plist, 2); ListPushBack(plist, 3); ListPushBack(plist, 4); ListPrint(plist); ListPopFront(plist); ListPopFront(plist); ListPrint(plist); ListPopFront(plist); ListPopFront(plist); ListPrint(plist); ListDestory(plist); plist = NULL; } int main() { //TestList1(); TestList2(); return 0; }
总结:
结语:
链表的学习结束啦!!!同学们要时常复习和刷题啊,我也写了好多链表的习题博客,同学们可以来访问啦。
文章来源:https://www.toymoban.com/news/detail-514000.html
到了这里,关于【数据结构与算法】双向链表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!