链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表)
上篇文章简述讲解了链表的基本概念并且实现了无头单向不循环链表:链接未来:深入理解链表数据结构(一.c语言实现无头单向非循环链表)-CSDN博客
那今天接着给大家带来带头双向循环链表的实现:
文章目录
- 一.项目文件规划
- 二.基本结构及功能一览(DoubleList.h)
- 结构体定义
- 接口功能一览
- 三.各功能接口具体实现
- 1.创建节点
- 2.初始化
- 3.打印
- 4.尾插
- 5.尾删
- 6.头插
- 7.头删
- 8.查找
- 9.插入pos前
- 10.删除pos位置
- 11.销毁
- 四.利用插入和删除改变“两插两删”(快速写出链表)
一.项目文件规划
- 头文件DoubleList.h:用来基础准备(常量定义,typedef),链表表的基本框架,函数的声明
- 源文件DoubleList.h:用来各种功能函数的具体实现
- 源文件test.c:用来测试功能是否有问题,进行基本功能的使用
二.基本结构及功能一览(DoubleList.h)
结构体定义
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int LTDataType;typedef struct ListNode
{struct ListNode* next;//下一个节点struct ListNode* prev;//上一个节点LTDataType val;//数据
}LTNode;
接口功能一览
LTNode* LTInit();//初始化
void LTPrint(LTNode* phead);//打印数据void LTPushBack(LTNode* phead, LTDataType x);//尾插
void LTPopBack(LTNode* phead);//尾删
void LTPushFront(LTNode* phead, LTDataType x);//头插
void LTPopFront(LTNode* phead);//头删LTNode* LTFind(LTNode* phead, LTDataType x);//查找
void LTInsert(LTNode* pos, LTDataType x);//在pos前插入
void LTErase(LTNode* pos);//删除posvoid LTDestroy(LTNode* phead);//销毁
三.各功能接口具体实现
1.创建节点
因为后面尾插,头插,插入,初始化都要用到创建新节点,所以抽出来作为一个函数
LTNode* CreateLTNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//动态开辟if (newnode == NULL){perror("malloc");return -1;}newnode->val = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}
2.初始化
1.第一种:返回动态开辟的地址(不会销毁)
LTNode* LTInit()
{LTNode* a =CreateLTNode(-1);a->next = a;//一开始一个节点时,下一个和上一个都指向自己a->prev = a;//return a;
}
2.第二种:传入二级指针(要直接改变头节点的值)
void LTInit(LTNode** pphead)
{*pphead = CreateLTNode(-1);(*pphead)->next = *pphead;(*pphead)->prev = *pphead;
}
这两种皆可
3.打印
void LTPrint(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;//头结点数据无效,不需要打印while (cur != phead){printf("%d ", cur->val);cur = cur->next;}printf("\n");
}
4.尾插
void LTPushBack(LTNode* phead, LTDataType x)//无有效节点也适用
{assert(phead);LTNode* newnode = CreateLTNode(x);LTNode* tail = phead->prev;// phead tail newnode 位置展示newnode->next = phead;phead->prev = newnode;newnode->prev = tail;tail->next = newnode;
}
5.尾删
void LTPopBack(LTNode* phead)//只有一个有效节点也适用
{assert(phead);LTNode* tail = phead->prev;LTNode* pretail = tail->prev;// phead pretail tail 位置展示free(tail);tail = NULL;phead->prev = pretail;pretail->next = phead;
}
6.头插
void LTPushFront(LTNode* phead, LTDataType x)//无有效节点也适用
{assert(phead);LTNode* newnode = CreateLTNode(x);//phead newnode firest tail 位置展示newnode->next = phead->next;phead->next->prev = newnode;newnode->prev = phead;phead->next = newnode;
}
7.头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);//只有哨兵位时不能删LTNode* first = phead->next;LTNode* second = first->next;//phead first second tail 位置展示free(first);first = NULL;phead->next = second;second->prev = phead;
}
8.查找
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);assert(phead->next != phead);//只有哨兵位时没必要查LTNode* cur = phead->next;while (cur != phead){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}
9.插入pos前
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = CreateLTNode(x);LTNode* pre = pos->prev;//pre newnode pos tail 位置展示pre->next = newnode;newnode->prev = pre;newnode->next = pos;pos->prev = newnode;
}
- 将前一个节点
pre
的next
指针指向新节点newnode
- 将新节点
newnode
的prev
指针指向前一个节点pre
- 将新节点
newnode
的next
指针指向指定节点pos
- 将指定节点
pos
的prev
指针指向新节点newnode
10.删除pos位置
void LTErase(LTNode* pos)
{assert(pos);LTNode* pre = pos->prev;LTNode* next = pos->next;//pre pos next tail 位置展示pre->next = next;next->prev = pre;free(pos);pos = NULL;
}
11.销毁
因为每个节点时malloc动态开辟出来的,要把每个节点都依次销毁
void LTDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur->next != phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);phead = NULL;
}
四.利用插入和删除改变“两插两删”(快速写出链表)
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTInsert(phead, x);//尾插就是在phead前插入
}void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTErase(phead->prev);
}void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTInsert(phead->next, x);//头插就是插入到phead的下一个
}void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTErase(phead->next);
}
那这次就先到这里啦!两种常见的链表都已经实现完毕,接下来大概率是栈和队列了,感谢大家支持
相关文章:

链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表)
上篇文章简述讲解了链表的基本概念并且实现了无头单向不循环链表:链接未来:深入理解链表数据结构(一.c语言实现无头单向非循环链表)-CSDN博客 那今天接着给大家带来带头双向循环链表的实现: 文章目录 一.项目文件规划…...
论文笔记 | Nature 2023 FunSearch:利用大语言模型在数学科学领域探索新的发现
文章目录 一、前言二、主要内容三、总结🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 科学中有许多难以解决的问题,这些问题难以获得确切解答,但却相对容易进行验证。在数学和计算机科学领域,这类问题被称为 NP 完全优化问题(NP-complete optimization pr…...
JavaScript 对象和 JSON 字符串的区别
JavaScript 对象和 JSON 字符串是两种不同的数据表示形式,它们有以下区别: 语法格式:JavaScript 对象是 JavaScript 语言中的一种数据类型,使用花括号 {} 包裹,属性和值之间使用冒号 : 分隔,并且使用逗号 …...
基于 Flink SQL 和 Paimon 构建流式湖仓新方案
目录 1. 数据分析架构演进 2. Apache Paimon 3. Flink + Paimon 流式湖仓 Consumer 机制 Changelog 生成编辑...

MFC静态链接+libtiff静态链接提示LNK2005和LNK4098
编译报错 1>msvcrt.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_infoAAEABV0Z) 已经在 libcmtd.lib(typinfo.obj) 中定义 1>msvcrt.lib(ti_inst.obj) : error LNK2005: "pr…...

桶装水送水小程序:提升服务质量的利器
随着移动互联网的发展,越来越多的消费者通过手机在线购物和订购商品。如果你是一名桶装水供应商,想要拓展线上业务,那么开发一个桶装水微信小程序将是一个明智的选择。本文将指导你从零开始开发一个桶装水微信小程序,让你轻松完成…...
深度学习在训练什么,什么是模型
深度学习是机器学习的一个分支,它主要通过使用称为神经网络的复杂结构来学习数据的表征。在深度学习中,"训练"和"模型"是两个核心概念。 训练 在深度学习中,"训练"是指用数据来训练一个神经网络。这个过程涉…...
Andorid 使用bp或者mk编译C文件生成so
在Aosp源码里编译C文件生成so 使用mk编译 文件夹列表 CMkDemo/Android.mk CMkDemo/cpp/SerialPort.c CMkDemo/cpp/SerialPort.hAndroid.mk 内容如下 LOCAL_PATH: $(call my-dir) include $(CLEAR_VARS)LOCAL_MODULE_TAGS : optional# All of the source files that we will…...

只更新软件,座椅为何能获得加热功能?——一文读懂OTA
2020年,特斯拉发布过一次OTA更新,车主可以通过这次系统更新获得座椅加热功能。当时,这则新闻震惊了车圈和所有车主,彼时的大家还没有把汽车当作可以“升级”的智能设备。 如今3年过去了,车主对各家车企的OTA升级早已见…...

EfficientDet:Scalable and Efficient Object Detection中文版 (BiFPN)
EfficientDet: Scalable and Efficient Object Detection EfficientDet:可扩展和高效的目标检测 摘要 模型效率在计算机视觉中变得越来越重要。本文系统地研究了用于目标检测的神经网络架构设计选择,并提出了几个关键的优化方法来提高效率。首先&…...

视频监控技术经历了哪些发展阶段?视频监控技术未来趋势展望
随着城市经济的发展和进步,视频监控也已经应用在人们衣食住行的方方面面,成为社会主体的一个重要组成部分。随着视频监控的重要性越来越凸显,大家对视频监控技术的发展也非常关注。今天我们来简单阐述一下,视频监控技术经历的几个…...

德人合科技 | 设计公司文件加密系统——天锐绿盾自动智能透明加密防泄密系统
设计公司文件加密系统——天锐绿盾自动智能透明加密防泄密系统 PC端访问地址: www.drhchina.com 一、背景介绍 设计公司通常涉及到大量的创意作品、设计方案、客户资料等重要文件,这些文件往往包含公司的核心价值和商业机密。因此,如何确保…...

类和对象(下篇)
再谈构造函数 构造函数体赋值 在之前的学习中我们知道,在创建一个对象时,我们的编译器就会自动调用构造函数将对象初始化,给对象中各个成员变量一个合适的初始值。 例如: class Date { public:Date(int year, int month, int d…...

华为鸿蒙(HarmonyOS):连接一切,智慧无限
华为鸿蒙是一款全场景、分布式操作系统,旨在构建一个真正统一的硬件生态系统。该操作系统于2019年8月首次发布,并被设计为可以应用于各种设备,包括智能手机、智能手表、智能电视、车载系统等多种智能设备。 推荐一套最新版的鸿蒙4.0开发教程 …...

劈窗算法反演地表温度
目录 摘要操作步骤提取热红外单波段提取NDVI同步像元分辨率与个数劈窗算法地表温度反演制图 摘要 主要使用HJ-2(环境减灾二号卫星)的IRS传感器的两个热红外波段,以及红波段与近红波段计算得到的NDVI,使用劈窗算法,得到…...

持续集成交付CICD:基于ArgoCD 的GitOps 自动化完成前端项目应用发布与回滚
目录 一、实验 1. 环境 2. K8S master节点部署Argo CD 3.基于ArgoCD 实现GitOps (同步部署文件) 4.基于ArgoCD 实现GitOps (同步HELM文件) 二、问题 1. ArgoCD 连接K8S集群状态为 Unknown 2.ArgoCD 创建application失败 …...

SSH无密登陆配置
1 SSH介绍 ssh命令用于远程登录到其他计算机,实现安全的远程管理。 基本语法: ssh 域名/IP地址 示例: (1)从hadoop100服务器上远程连接hadoop101服务器 [hadoophadoop100 ~]$ ssh hadoop101 如果出现如下内容 Ar…...

【bug日记】如何切换jdk版本,如何解决java和javac版本不一致
背景 今天在安装jenkins后,使用java运行war包的时候,提示jdk1.8版本太低,需要提高版本,所以就需要切换jdk版本 解决 在用户变量中,首先更改了JAVA_HOME的地址为17的目录,发现javac的版本改为17了&#x…...
【C语言】6-5 判断回文字符串 分数 20
6-5 判断回文字符串 分数 20 全屏浏览题目 切换布局 作者 C课程组 单位 浙江大学 本题要求编写函数,判断给定的一串字符是否为“回文”。所谓“回文”是指顺读和倒读都一样的字符串。如“XYZYX”和“xyzzyx”都是回文。 函数接口定义: bool palindr…...

STL中优先队列(堆)的详解
文章目录 priority_queue的基本介绍堆(heap)堆的概念与结构 priority_queue 的介绍与使用 priority_queue的基本介绍 这个priority_queue翻译成中文就是优先级队列,但其实我们很难去一眼看出他的意思到底是什么,他的逻辑结构实际上类似于数据结构中的堆…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...