0


数据结构-带头双向循环链表的基本实现(C语言,简单易懂,含全部代码)

链表的概念和结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

结构:实际中链表的结构非常多样,以下情况组合起来就有8种链表结构。

(1)单向、双向
(2)带头、不带头
(3)循环、非循环

本篇主要详解带头双向循环链表,结构如图:
在这里插入图片描述

带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。

链表的实现

首先在头文件中定义结构体和提供接口:

#pragmaonce#include<stdio.h>#include<stdlib.h>#include<assert.h>typedefint LTDataType;typedefstructListNode{structListNode* next;structListNode* prev;
    LTDataType data;}ListNode;voidListPrint(ListNode* phead);//打印链表

ListNode*BuyListNode(LTDataType x);//开辟新节点

ListNode*ListInit();//初始化哨兵位voidListPushBack(ListNode* phead, LTDataType x);//尾插,只要不改变头指针的内容,就不用传二级指针voidListPushFront(ListNode* phead, LTDataType x);//头插voidListPopBack(ListNode* phead);//尾删voidListPopFront(ListNode* phead);//头删

ListNode*ListFind(ListNode* phead, LTDataType x);//查找voidListInsert(ListNode* pos, LTDataType x);//pos位置前插voidListErase(ListNode* pos);//pos位置删除

其次在源文件中实现接口功能:
(1)链表打印

voidListPrint(ListNode* phead){
    ListNode* cur = phead;while(cur != phead){printf("%d", cur->data);
        cur = cur->next;//找到下一个节点}printf("\n");}

(2)开辟新节点

ListNode*BuyListNode(LTDataType x){
    ListNode* node =(ListNode*)malloc(sizeof(ListNode));
    node->next =NULL;
    node->prev =NULL;
    node->data = x;return node;}

(3)初始化哨兵位

ListNode*ListInit(){
    ListNode* phead =BuyListNode(0);
    phead->next = phead;
    phead->prev = phead;return phead;}

(4)尾插
带头双向循环链表的头插尾插非常方便,只需要找到头(phaed->next)和尾(phead->prev)并链接

voidListPushBack(ListNode* phead, LTDataType x){//无论是0个(只有哨兵位)还是多个节点都可以,与节点个数无关assert(phead);
    ListNode* tail = phead->prev;//找尾
    ListNode* newnode =BuyListNode(x);

    tail->next = newnode;
    newnode->prev = tail;
    newnode->next = phead;
    phead->prev = newnode;}

在这里插入图片描述
(5)头插

voidListPushFront(ListNode* phead, LTDataType x){assert(phead);
    ListNode* first = phead->next;
    ListNode* newnode =BuyListNode(x);//phead newnode first 
    phead->next = newnode;
    newnode->prev = phead;
    newnode->next = first;
    first->prev = newnode;}

在这里插入图片描述
(6)尾删

voidListPopBack(ListNode* phead){assert(phead);assert(phead->next != phead);
    ListNode* tail = phead->prev;
    ListNode* tailPrev = tail->prev;free(tail);

    tailPrev->next = phead;
    phead->prev = tailPrev;}

(7)头删

voidListPopFront(ListNode* phead){assert(phead);//没有节点assert(phead->next != phead);//只有phead

    ListNode* first = phead->next;
    ListNode* second = first->next;free(first);

    phead->next = second;
    second->prev = phead;}

(8)查找x

ListNode*ListFind(ListNode* phead, LTDataType x){assert(phead);
    ListNode* cur = phead->next;while(cur != phead){if(cur->data == x){return cur;}
        cur = cur->next;}returnNULL;}

(9)pos位置前插

voidListInsert(ListNode* pos, LTDataType x){assert(pos);

    ListNode* prev = pos->prev;
    ListNode* newnode =BuyListNode(x);
    prev->next = newnode;
    newnode->prev = prev;
    newnode->next = pos;
    pos->prev = newnode;}

(10)pos位置删除****

voidListErase(ListNode* pos){assert(pos);

    ListNode* prev = pos->prev;
    ListNode* next = pos->next;

    prev->next = next;
    next->prev = prev;free(pos);}

主函数的设计大家可以自由发挥,做个简单的测试功能调用函数或是创建菜单栏实现交互都可以。我水平有限,请朋友们谅解!写的不好的地方还请大佬们指出。最后,如果这篇文章对你有帮助,就点个赞或者收藏评论一下吧,谢谢大家支持😁。

下期预告——栈和队列详解!


本文转载自: https://blog.csdn.net/qq_43460230/article/details/124424450
版权归原作者 阿龙还在写代码 所有, 如有侵权,请联系我们删除。

“数据结构-带头双向循环链表的基本实现(C语言,简单易懂,含全部代码)”的评论:

还没有评论