当前位置: 首页 > news >正文

追梦之旅【数据结构篇】——详解C语言动态实现带头结点的双向循环链表结构

详解C语言动态实现带头结点的双向循环链表结构~😎

  • 前言🙌
  • 预备小知识💞
    • 链表的概念及结构🙌
  • 预备小知识💞
    • 链表的概念及结构🙌
    • 带头结点的双向循环链表结构🙌
  • 整体实现内容分析💞
  • 1.头文件编码实现🙌
  • 2.代码功能实现🙌
    • 1)这是生成新节点函数实现。😊
    • 2)生成带头结点的空链表函数实现。😊
    • 3)删除链表函数实现。😊
    • 4)顺序输出链表函数实现。😊
    • 5)尾插函数实现。😊
    • 6)头插函数实现。😊
    • 7)头删函数实现。😊
    • 8)尾删函数的实现。😊
    • 9)查找函数实现。😊
    • 10)pos位置之前插入x的函数实现。😊
    • 11)删除pos位置的值的函数实现。😊
    • 12)逆序输出的函数实现。😊
    • 13)判空函数实现。😊
  • 3.测试文件源码分享:🙌
  • 总结撒花💞

追梦之旅,你我同行

   
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
在这里插入图片描述

前言🙌

    哈喽各位友友们😊,我今天又学到了很多有趣的知识现在迫不及待的想和大家分享一下!😘我仅已此文,手把手带领大家学习C语言动态实现实现带头结点的双向循环链表结构~ 用代码来实现一个带头结点的双向循环链表结构,完成增删查改,顺序输出和逆序输出,判空的功能。都是精华内容,可不要错过哟!!!😍😍😍

预备小知识💞

链表的概念及结构🙌

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

预备小知识💞

链表的概念及结构🙌

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

在这里插入图片描述

带头结点的双向循环链表结构🙌

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

整体实现内容分析💞

首先在头文件先定义结构体和各个功能函数的声明,并把有关的头文件包含上去。各个函数如何实现的,已在实验步骤描述清楚,这里就不在赘述了,主要是对各个函数的实现,用到malloc动态开辟新节点的空间,用assert断言确保指针有效,通过画图来帮助理清代码实现的思路,指针的指向如何,要考虑哪些情况。然后再测试代码中,将上述代码都进行测试,显示结果。

1.头文件编码实现🙌

12、	#pragma once
3、	#include <stdio.h>
4、	#include <stdlib.h>
5、	#include <assert.h>
6、	#include <stdbool.h>
78typedef int LTDataType;
9// 带头双向循环链表结构体
10typedef struct ListNode
11{
12struct ListNode* next;
13struct ListNode* prev;
14、		LTDataType data;
15}ListNode;
16、	ListNode* ListInit();//链表初始化
17void ListDestory(ListNode* phead);//删除链表
18void ListPrintFront(ListNode* phead);//链表顺序输出
19void ListPrintBack(ListNode* phead);//链表逆序输出
20void ListPushBack(ListNode* phead, LTDataType x);//尾插
21void ListPushFront(ListNode* phead, LTDataType x);//头插
22void ListPopFront(ListNode* phead);//头删
23void ListPopBack(ListNode* phead);//尾删
24、	ListNode* ListFind(ListNode* phead, LTDataType x);//查找
25void ListInsert(ListNode* pos, LTDataType x);// pos位置之前插入x
26void ListErase(ListNode* pos);// 删除pos位置的值
27、	bool ListEmpty(ListNode* phead);判空函数

2.代码功能实现🙌

1)这是生成新节点函数实现。😊

代码实现思路详解:

//用malloc动态开辟新节点的空间,把数值赋值给新节点
//,newnode的next和prev指针指向空。

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

2)生成带头结点的空链表函数实现。😊

代码实现思路详解:

//2)生成带头结点的空链表,将头结点的指针都指向自己即可。

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

3)删除链表函数实现。😊

代码实现思路详解:

//3)先用assert断言以下确保phead指针不为空,生成cur指针先指向第一个结点位置。用while循环执行删表:在定义一个next指针指向cur的下一个结点,free掉cur指向的结点,cur移动到next位置。最后删除头结点即可
//


void ListDestory(ListNode* phead)//删除链表
{assert(phead);ListNode* cur = phead->next;while (cur != phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);phead = NULL;
}

4)顺序输出链表函数实现。😊

代码实现思路详解:

//4)顺序输出链表。先assert断言确保指针有效。定义一个指向链表首结点的指针,打印完一个,cur到下一个节点知道cur回到phead为止。

void ListPrintFront(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}

5)尾插函数实现。😊

代码实现思路详解:

//5)尾插函数。先assert确保指针有效性,定义tail指针指向最后一个节点,然后生成新节点然后通过指针将tail指向的节点与新生成的节点相连,新生成的节点与哨兵位头结点相连


void ListPushBack(ListNode* phead, LTDataType x)
{assert(phead);ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;
}

6)头插函数实现。😊

代码实现思路详解:

//6)头插函数实现。先assert断言一下确保传入进来的指针有效。定义一个指向首节点的指针然后生成一个新节点,让新节点与头结点相连,让新节点的next指针指向原来首节点,原来首节点的prev指向新节点让新节点位于原来首节点的前面从而实现头插。

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

7)头删函数实现。😊

代码实现思路详解:

//7)头删函数实现。assert确保传入指针有效和确保头结点不要被删掉。定义first指针指向链表首节点,second指向first下一个。然后让头结点与second指针指向的节点相连,然后free掉first指向的节点。


void ListPopFront(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListNode* first = phead->next;ListNode* second = first->next;phead->next = second;second->prev = phead;free(first);first = NULL;}

8)尾删函数的实现。😊

代码实现思路详解:

//8)尾删函数的实现。头删函数实现。assert确保传入指针有效和确保头结点不要被删掉。定义tail函数指向尾节点,定义prev指针指向tail的前一个节点,让prev指向的那个节点与头结点相连,然后删掉tail指向的尾节点,实现尾删。

void ListPopBack(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListNode* tail = phead->prev;ListNode* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;}

9)查找函数实现。😊

代码实现思路详解:

//9)查找函数,先assert断言确保传入指针有效性,定义一个cur指向首节点,然后利用while遍历链表,找到的话就返回指针。找不到则返回空。

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;
}

10)pos位置之前插入x的函数实现。😊

代码实现思路详解:

// 10)pos位置之前插入x。定义一个prev指针指向pos指向的前一个节点,然后新生成一个节点,通过指针相连方式将新生成的节点放到pos与prev的中间。

void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* prev = pos->prev;ListNode* newnode = BuyListNode(x);// prev newnode posprev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}

11)删除pos位置的值的函数实现。😊

代码实现思路详解:

// 11)删除pos位置的值。定义一个prev指针指向pos前一个节点,定义一个next指向pos后一个节点,然后让这两个节点相连,删掉pos指向的节点。

void ListErase(ListNode* pos)
{assert(pos);ListNode* prev = pos->prev;ListNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);
}

12)逆序输出的函数实现。😊

代码实现思路详解:

//12)逆序输出函数实现。定义一个phead指针指向尾节点,从后往前遍历链表,直到cur走到头结点为止。

void ListPrintBack(ListNode* phead)
{assert(phead);ListNode* cur = phead->prev;while (cur != phead){printf("%d ", cur->data);cur = cur->prev;}printf("\n");
}

13)判空函数实现。😊

代码实现思路详解:

//13)判空函数实现,只要phead的前指针指向自己,则认为这链表为空链表。

bool ListEmpty(ListNode* phead)
{assert(phead);if (phead->prev == phead){return 1;}return -1;

3.测试文件源码分享:🙌


#include "SlistNode.h"void TestList1()
{//创建带头节点的空双向链表ListNode* plist = ListInit();//判空int ret = ListEmpty(plist);if (ret == 1){printf("链表为空\n");}else{printf("链表不为空\n");}//尾插1,2,3,4,5ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPushBack(plist, 5);ListPrintFront(plist);//头插0,-1ListPushFront(plist, 0);ListPushFront(plist, -1);ListPrintFront(plist);//头删三个数据ListPopFront(plist);ListPopFront(plist);ListPopFront(plist);ListPrintFront(plist);//尾删一个数据ListPopBack(plist);ListPrintFront(plist);//判空int ret1 = ListEmpty(plist);if (ret1 == 1){printf("链表不为空\n");}else{printf("链表为空\n");}// 查找,附带着修改的作用ListNode* pos = ListFind(plist, 3);if (pos){pos->data *= 10;printf("找到了,并且节点的值乘以10\n");}else{printf("没有找到\n");}ListPrintFront(plist);//在pos前插入一个300ListInsert(pos, 300);ListPrintFront(plist);//删除pos位置的节点ListErase(pos);//顺序输出链表数据ListPrintFront(plist);//逆序输出链表数据ListPrintBack(plist);
//删除链表ListDestory(plist);}int main()
{TestList1();return 0;
}

程序功能测试结果图:
在这里插入图片描述

总结撒花💞

   本篇文章旨在分享详解C语言动态实现带头结点的双向循环链表结构。希望大家通过阅读此文有所收获实现带头结点的双向循环链表结构,相比于单链表结构更加复杂一点,它的成员相比单链表多了一个指针。本次实现难点在于对指针的运用和对多种情况的考虑。在实现前一定要通过画图的方式将思路和需要注意的情况想清楚然后再来尝试用代码进行实现。基本实现出双链表后可以思考能不能优化代码的问题。
   😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

相关文章:

追梦之旅【数据结构篇】——详解C语言动态实现带头结点的双向循环链表结构

详解C语言动态实现带头结点的双向循环链表结构~&#x1f60e;前言&#x1f64c;预备小知识&#x1f49e;链表的概念及结构&#x1f64c;预备小知识&#x1f49e;链表的概念及结构&#x1f64c;带头结点的双向循环链表结构&#x1f64c;整体实现内容分析&#x1f49e;1.头文件编…...

华为OD机试真题Python实现【水仙花数 2】真题+解题思路+代码(20222023)

水仙花数 2 题目 给定非空字符串 s,将该字符串分割成一些子串 使每个子串的 ASCII 码值的和均为水仙花数 若分割不成功则返回 0若分割成功且分割结果不唯一 则返回-1若分割成功且分割结果唯一 则返回分割后子串的数目 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机…...

【原创】java+swing+txt学生学籍管理系统设计与实现

今天我们来介绍如何使用javaswingtxt来开发一个学籍管理系统。对的&#xff0c;你没看错&#xff0c;我们今天不用mysql&#xff0c;我们使用txt这个文本来进行数据存储&#xff0c;主要考察对文件读写的操作。 功能分析&#xff1a; 我们系统不要求做的很复杂&#xff0c;只…...

GCN项目实战1-SimGNN

文章目录SimGNN&#xff1a;快速图相似度计算的神经网络方法1. 数据2. 模型2.1 python文件功能介绍2.2 重要函数和类的实现SimGNN&#xff1a;快速图相似度计算的神经网络方法 原论文名称&#xff1a;SimGNN: A Neural Network Approach to Fast Graph Similarity Computation…...

经过深思熟虑后的接口测试自动化的总结与思考

序近期看到阿里云性能测试 PTS 接口测试开启免费公测&#xff0c;本着以和大家交流如何实现高效的接口测试为出发点&#xff0c;本文包含了我在接口测试领域的一些方法和心得&#xff0c;希望大家一起讨论和分享&#xff0c;内容包括但不仅限于&#xff1a;服务端接口测试介绍接…...

电脑自带的录屏放在哪里了?轻松弄懂,看这篇文章就明白了

有很多小伙伴有这个疑问&#xff0c;电脑自带的录屏放在哪里了&#xff1f;其实&#xff0c;电脑自带的录屏工具并不是所有电脑都要&#xff0c;具体要看你的电脑品牌和操作系统&#xff0c;Windows系统和Mac系统的电脑都自带了录屏工具&#xff0c;下面跟着小编一起来看看吧。…...

华为OD机试真题Java实现【字符串分割】真题+解题思路+代码(20222023)

字符串分割 给定一个非空字符串S,其被N个‘-’分隔成N+1的子串,给定正整数K,要求除第一个子串外,其余的子串每K个字符组成新的子串,并用‘-’分隔。对于新组成的每一个子串,如果它含有的小写字母比大写字母多,则将这个子串的所有大写字母转换为小写字母;反之,如果它含…...

【数据库】Apache Doris : 一个开源 MPP 数据库的架构与实践

文章目录Doris 背景介绍一、Doris二、Doris 定位适用场景 & 案例介绍一、适用场景二、具体案例Doris 整体架构一、Doris 整体架构二、Doris 数据分布三、Doris 的使用方式Doris 关键技术一、数据可靠性二、易运维三、MySQL 兼容性四、支持 MPPDoris 数据模型一、Doris 数据…...

day49【代码随想录】动态规划之最长公共子序列、不相交的线、最大子序和、判断子序列

文章目录前言一、最长公共子序列&#xff08;力扣1143&#xff09;二、不相交的线&#xff08;力扣1035&#xff09;三、最大子序和&#xff08;力扣53&#xff09;四、判断子序列&#xff08;力扣392&#xff09;前言 1、最长公共子序列 2、不相交的线 3、最大子序和 4、判断…...

华为OD机试真题Python实现【字母消消乐】真题+解题思路+代码(20222023)

字母消消乐 题目 游戏规则: 输入一个只包含英文字母的字符串, 字符串中的两个字母如果相邻且相同,就可以消除。 在字符串上反复执行消除的动作, 直到无法继续消除为止,此时游戏结束。 输出最终得到的字符串长度。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试…...

程序中的日期使用问题-格式转化:SimpleDateFormat、org.apache.commons.lang3.time.DateUtils

前言 日期使用问题主要是格式转换的问题 场景&#xff1a;通过excel导入数据&#xff0c;其中一个字段为出生日期&#xff0c;需要对字段值进行合法性校验 博客地址&#xff1a;芒果橙的个人博客 【http://mangocheng.com】 一、个人浅谈日期 时间日期作为一个基础的标识和维度…...

C++——map和set的应用总结

目录1. 关联式容器2. 键值对3. 树形结构的关联式容器3.1 set3.1.1 set的介绍3.1.2 set的使用3.2 multiset3.2.1 multiset的介绍3.2.2 multiset的使用3.3 map3.3.1 map的介绍3.3.2 map的使用operator[]3.4 multimap3.4.1 multimap的介绍3.4.2 multimap的使用3.5 map和set在OJ中的…...

学习Python可以做什么工作?

一&#xff1a; 1、web开发&#xff1a;Python拥有非常完善与web服务器交互的库&#xff0c;大量的免费网页模板&#xff0c;相对于更具有优势&#xff0c;同时还具有非常优秀的Django框架&#xff0c;功能齐全。目前国内的豆瓣网、果壳网等&#xff0c;国外的Google、YouTube等…...

AWS攻略——Peering连接VPC

文章目录创建IP/CIDR不覆盖的VPC创建VPC创建子网创建密钥对创建EC2创建Peering接受Peering邀请修改各个VPC的路由表修改美东us-east-1 pulic subnet的路由修改悉尼ap-southeast-2路由测试知识点我们回顾下《AWS攻略——VPC初识》中的知识&#xff1a; 一个VPC只能设置在一个Re…...

程序员遇到人生低谷期怎么做?

每个人的一生都是起起伏伏的&#xff0c;你不会天天高潮&#xff0c;总会经历一段又一段的不如意&#xff0c;你怎么把握这一段段时间&#xff0c;如何掌控人生节奏&#xff0c;都源于对人生低谷期的回答。 尤其是2022年&#xff0c;程序员受到的冲击并不小&#xff0c;从年初…...

理解IM消息“可靠性”和“一致性”问题,以及解决方案探讨

试想如果一个IM连发出的消息都不知道对方到底能不能收到、发出的聊天内容对方看到的到底是不是“胡言乱语”&#xff08;严重乱序问题&#xff09;&#xff0c;这样的APP用户肯定不会让他在手机上过夜&#xff08;肯定第一时间卸载了&#xff09;&#xff0c;因为最基本的聊天逻…...

2021-08-29

服务器 主&#xff1a;172.17.0.2 master 备:172.17.0.3 slave1 lvs虚拟IP:172.17.0.100 #nginx下载地址 http://nginx.org/download/ 本地文件路径 1.dockerfile构建nginx FROM centos:7 ADD nginx-1.6.0.tar.gz /usr/local COPY nginx_install.sh /usr/local RUN sh …...

第八题、哈夫曼编码大全

题目&#xff1a; 哈夫曼编码大全 描述&#xff1a; 关于哈夫曼树的建立&#xff0c;编码&#xff0c;解码。 输入 第一行输入数字N&#xff0c;代表总共有多少个字符以及权值 第二第三行分别是一行字符串&#xff0c;以及每个字符对应的权值 接下来输入一个数M&#xff0c;表…...

linux集群技术(二)--keepalived(高可用集群)(二)

案例1--keepalived案例2--keepalived Lvs集群1.案例1--keepalived 1.1 环境 初识keepalived&#xff0c;实现web服务器的高可用集群。 Server1: 192.168.26.144 Server2: 192.168.26.169 VIP: 192.168.26.190 1.2 server1 创建etc下的…...

C# 控制台程序的开发和打包为一个exe文件

目录前言一、我的第一个C#控制台程序二、发布为一个exe文件前言 本文通过C#编写一个简单的示例计算器&#xff0c;来演示C#的使用和使用 Visual Studio 打包为一个 exe 文件。 一、我的第一个C#控制台程序 所谓控制台程序&#xff0c;就是没有界面&#xff0c;运行程序后只有…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...