用C语言实现一个链表(四)
用C语言实现一个链表(四)
在上期内容中,我们探讨了实现一个双向循环链表的准备工作以及一些功能——创建新结点,初始化头结点,尾插数据,尾删数据,遍历的代码,上期内容留下了一个判断是否存在有效数据的函数,本期内容,我们会将其补充完整并且继续讨论其他一些功能的代码实现。
一、双向循环链表的实现(代码+分析)
1.头部插入数据
头部插入数据相对轻松,只要理解指针的链接关系即可,结合画图理解会比较轻松,如图:
代码如下:
void DCLLPushFront(DCLLNode* phead, DataType x)//这里只需要一级指针即可,因为改变的是结构体里面的内容,而不是改变结构
{assert(phead);DCLLNode* newnode = CreateDCLLNode(x);//创建一个新结点newnode->next = phead->next;//新结点的next指向头结点的下一个结点phead->next->prev = newnode;//原来头结点的下一个结点的prev指向新结点phead->next = newnode;//头结点的next指向新结点newnode->prev = phead;//新结点的prev指向头结点
}
2.判断是否存在有效数据
函数用来判断是双向循环链表是否为空。
存在有效数据就返回0(不为空),不存在有效数据就返回1(为空),代码如下:
bool DCLLisEmpty(DCLLNode* phead)
{assert(phead);return phead->next == phead;//如果phead的next还是phead,就说明双向循环链表只有一个头结点,并没有存入了数据的新结点
}
3.头部删除数据
结合图示理解:
代码如下:
void DCLLPopFront(DCLLNode* phead)
{assert(phead);assert(!DCLLisEmpty(phead));DCLLNode* front = phead->next;phead->next = phead->next->next;phead->next->prev = phead;free(front);front = NULL;
}
4.特定位置寻找
寻找就是遍历,要注意的还是循环条件的控制,代码如下:
DCLLNode* DCLLFind(DCLLNode* phead, DataType x)
{assert(phead);DCLLNode* cur = phead->next;//可以移动的指针指向第一个存储有效数据的结点while (cur != phead)//循环条件的控制和遍历相同{if (cur->data == x){return cur;//找到了,就返回对应结点的地址}cur = cur->next;}return NULL;//找不到就返回一个空指针
}
5.特定位置插入数据
结合图示理解:
代码如下:
void DCLLInsert(DCLLNode* pos, DataType x)//在特定位置插入数据,需要提供对应的地址和数据
{assert(pos);DCLLNode* newnode = CreateDCLLNode(x);//创建新结点DCLLNode* prev = pos->prev;//这里是在特定位置的前面插入prev->next = newnode;//特定位置的前一个结点的next指向新结点newnode->prev = prev;//新结点的prev指向的就是特定位置的前一个结点newnode->next = pos;//新结点的next指向特定位置的结点pos->prev = newnode;//特定位置结点的prev指向新结点
}
6.特定位置删除
结合图示理解:
代码如下:
void DCLLErase(DCLLNode* pos)//在特定位置删除,需要提供特定位置的地址
{assert(pos);pos->prev->next = pos->next;//删除的是特定位置本身,它的前一个结点的next指向特定位置的后一个结点pos->next->prev = pos->prev;//后一个结点的prev指向特定位置的前一个结点free(pos);//释放特定位置的空间pos = NULL;
}
7.双向循环链表的销毁
和单链表一样,在销毁每一个结点时,要注意保存下一个结点的地址,代码如下:
void DCLLDestroy(DCLLNode* phead)
{assert(phead);DCLLNode* cur = phead->next;while (cur != phead){DCLLNode* next = cur->next;free(cur);cur = next;}free(phead);phead = NULL;
}
8.运行测试
代码如下:
int main()
{DCLLNode* plist = DCLLInit();//初始化头结点DCLLPushBack(plist, 1);//尾插数据DCLLPushBack(plist, 2);DCLLPushBack(plist, 3);DCLLPushBack(plist, 4);DCLLPushBack(plist, 5);DCLLPushBack(plist, 6);DCLLPushBack(plist, 7);DCLLPrint(plist);//遍历DCLLPushFront(plist, 1);//头插数据DCLLPushFront(plist, 2);DCLLPushFront(plist, 3);DCLLPushFront(plist, 4);DCLLPushFront(plist, 5);DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLNode* ret = DCLLFind(plist, 4);//寻找数据域为4的结点,返回它的地址DCLLInsert(ret, 9);//在4前面插入9DCLLPrint(plist);//遍历DCLLErase(ret);//删除数据域为4的这一结点DCLLPrint(plist);//遍历DCLLDestroy(plist);//销毁return 0;
}
运行结果如图:
二、使用头文件——将声明与定义分离
1.头文件——DCLL.h
在双向循环链表中,我们为了实现它的基本功能,写了很多的函数,如果我们将结构体,函数的声明,函数的定义,以及函数的调用测试写在同一个源文件中,会大大降低代码的可读性和可维护性;因此,我们可以将结构体以及一些函数的声明放在头文件DCLL.h中,代码如图:
2.源文件——DCLL.c
在源文件DCLL.c中,我们存放函数具体实现的代码,在第一行应加上 #include"DCLL.h",代码如下:
#include"DCLL .h"DCLLNode* CreateDCLLNode(DataType x)
{DCLLNode* node = (DCLLNode*)malloc(sizeof(DCLLNode));//创建一个新结点if (node == NULL)//判断动态内存开辟是否成功{perror("malloc fail");return NULL;}node->data = x;//对新结点 的数据域赋值node->next = NULL;//对新结点的指针域赋值node->prev = NULL;//对新结点的指针域赋值return node;//返回的是一个指针,指向新创建的节点
}DCLLNode* DCLLInit()
{DCLLNode* phead = CreateDCLLNode(-1);phead->next = phead;//当还没有开始插入新结点时,头结点的next指向的是头结点本身phead->prev = phead;//当还没有开始插入新结点时,头结点的prev指向的也是头结点本身return phead;//返回的是头结点的地址
}void DCLLPrint(DCLLNode* phead)
{assert(phead);DCLLNode* cur = phead->next;printf("<=head=>");while (cur!=phead)//最后一个结点的特点就是它的next指向的是头结点,因此指针指向头结点是就说明双向循环链表遍历结束了{printf("%d<=>", cur->data);cur = cur->next;//cur向后移动,指向下一个结点}printf("\n");
}void DCLLPushBack(DCLLNode* phead, DataType x)//这里只需要一级指针即可,因为改变的是结构体里面的内容,而不是改变结构体指针
{assert(phead);DCLLNode* newnode = CreateDCLLNode(x);//创建一个新结点DCLLNode* tail = phead->prev;//头结点的prev指针就是指向的尾部结点tail->next = newnode;//尾结点的next指向插入的新结点newnode->prev = tail;//新结点的prev指向的是尾结点(双向链接)newnode->next = phead;//新结点的next就是接上了头结点phead->prev = newnode;//而头结点的prev又连上了尾结点(新结点)
}bool DCLLisEmpty(DCLLNode* phead)
{assert(phead);return phead->next == phead;//如果phead的next还是phead,就说明双向循环链表只有一个头结点,并没有存入了数据的新结点
}void DCLLPopBack(DCLLNode* phead)
{assert(phead);assert(!DCLLisEmpty(phead));//双向循环链表有数据才能删除数据DCLLNode* tail = phead->prev;//新建一个DCLLNode型结构体指针,指向尾结点DCLLNode* tailprev = tail->prev;//新建一个DCLLNode型结构体指针,指向尾结点的前一个结点tailprev->next = phead;//尾结点的前一个结点不再指向尾结点,而是指向头结点phead->prev = tailprev;//头结点的prev指向为现在的尾结点free(tail);//释放刚才尾结点的空间tail = NULL;
}void DCLLPushFront(DCLLNode* phead, DataType x)//这里只需要一级指针即可,因为改变的是结构体里面的内容,而不是改变结构
{assert(phead);DCLLNode* newnode = CreateDCLLNode(x);//创建一个新结点newnode->next = phead->next;//新结点的next指向头结点的下一个结点phead->next->prev = newnode;//原来头结点的下一个结点的prev指向新结点phead->next = newnode;//头结点的next指向新结点newnode->prev = phead;//新结点的prev指向头结点
}void DCLLPopFront(DCLLNode* phead)
{assert(phead);assert(!DCLLisEmpty(phead));DCLLNode* front = phead->next;phead->next = phead->next->next;phead->next->prev = phead;free(front);front = NULL;
}DCLLNode* DCLLFind(DCLLNode* phead, DataType x)
{assert(phead);DCLLNode* cur = phead->next;//可以移动的指针指向第一个存储有效数据的结点while (cur != phead)//循环条件的控制和遍历相同{if (cur->data == x){return cur;//找到了,就返回对应结点的地址}cur = cur->next;}return NULL;//找不到就返回一个空指针
}void DCLLInsert(DCLLNode* pos, DataType x)//在特定位置插入数据,需要提供对应的地址和数据
{assert(pos);DCLLNode* newnode = CreateDCLLNode(x);//创建新结点DCLLNode* prev = pos->prev;//这里是在特定位置的前面插入prev->next = newnode;//特定位置的前一个结点的next指向新结点newnode->prev = prev;//新结点的prev指向的就是特定位置的前一个结点newnode->next = pos;//新结点的next指向特定位置的结点pos->prev = newnode;//特定位置结点的prev指向新结点
}void DCLLErase(DCLLNode* pos)//在特定位置删除,需要提供特定位置的地址
{assert(pos);pos->prev->next = pos->next;//删除的是特定位置本身,它的前一个结点的next指向特定位置的后一个结点pos->next->prev = pos->prev;//后一个结点的prev指向特定位置的前一个结点free(pos);//释放特定位置的空间pos = NULL;
}void DCLLDestroy(DCLLNode* phead)
{assert(phead);DCLLNode* cur = phead->next;while (cur != phead){DCLLNode* next = cur->next;free(cur);cur = next;}free(phead);phead = NULL;
}
3.源文件——Test.c
在源文件Test.c中调用双向循环链表的功能函数,完成测试,当然第一行还是得写上 #include"DCLL.h" 。在这里,我们将上期和这期的内容结合在一起,写了两个测试函数 void Test_one()和void Test_two(),代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include"DCLL .h"void Test_one()
{DCLLNode* plist = DCLLInit();//初始化头结点DCLLPushBack(plist, 1);//尾插数据DCLLPushBack(plist, 2);DCLLPushBack(plist, 3);DCLLPushBack(plist, 4);DCLLPushBack(plist, 5);DCLLPrint(plist);//遍历DCLLPopBack(plist);//尾删数据DCLLPrint(plist);//遍历DCLLPopBack(plist);//尾删数据DCLLPrint(plist);//遍历DCLLPopBack(plist);//尾删数据DCLLPrint(plist);//遍历DCLLPopBack(plist);//尾删数据DCLLPrint(plist);//遍历DCLLPopBack(plist);//尾删数据DCLLPrint(plist);//遍历
}void Test_two()
{DCLLNode* plist = DCLLInit();//初始化头结点DCLLPushBack(plist, 1);//尾插数据DCLLPushBack(plist, 2);DCLLPushBack(plist, 3);DCLLPushBack(plist, 4);DCLLPushBack(plist, 5);DCLLPushBack(plist, 6);DCLLPushBack(plist, 7);DCLLPrint(plist);//遍历DCLLPushFront(plist, 1);//头插数据DCLLPushFront(plist, 2);DCLLPushFront(plist, 3);DCLLPushFront(plist, 4);DCLLPushFront(plist, 5);DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLPopFront(plist);//头删数据DCLLPrint(plist);//遍历DCLLNode* ret = DCLLFind(plist, 4);//寻找数据域为4的结点,返回它的地址DCLLInsert(ret, 9);//在4前面插入9DCLLPrint(plist);//遍历DCLLErase(ret);//删除数据域为4的这一结点DCLLPrint(plist);//遍历DCLLDestroy(plist);//销毁
}int main()
{Test_one();Test_two();return 0;
}
三、本期总结+下期预告
本期内容书接上回,完成了带头双向循环链表的C语言实现,下期将为大家带来栈和队列的内容!
感谢大家的关注,我们下期再见!
相关文章:
用C语言实现一个链表(四)
用C语言实现一个链表(四) 在上期内容中,我们探讨了实现一个双向循环链表的准备工作以及一些功能——创建新结点,初始化头结点,尾插数据,尾删数据,遍历的代码,上期内容留下了一个判断…...
【我的 PWN 学习手札】House of Kiwi
House of Kiwi 之前我们利用IO_FILE一般是通过劫持vtable来实现的, House of Kiwi虽然不是通过劫持vtable来实现,但实质上是劫持vtable指向的全局的_IO_file_jumps_表来实现的。注意:对于某些版本的glibc,_IO_file_jumps_并不可写…...
象棋笔记-实战记录
文章目录 实战没发现杀招2024-06-16 实战又漏杀了,尴尬,炮震五子,3路炮有下底的机会,本来是绝杀,没算明白,以为窝心马和象都能看住这个点。。。2024-07-06 实战有进炮串打的机会,又错过了&#…...
RabbitMQ系列(六)基本概念之Routing Key
在 RabbitMQ 中,Routing Key(路由键) 是用于将消息从交换机(Exchange)路由到指定队列(Queue)的关键参数。其核心作用是通过特定规则匹配绑定关系,确保消息被正确分发。以下是其核心机…...
企业微信里可以使用的企业内刊制作工具,FLBOOK
如何让员工及时了解公司动态、行业资讯、学习专业知识,并有效沉淀企业文化?一份高质量的企业内刊是不可或缺的。现在让我来教你该怎么制作企业内刊吧 1.登录与上传 访问FLBOOK官网,注册账号后上传排版好的文档 2.选择模板 FLBOOK提供了丰富的…...
JAVA笔记【一】
现实 (抽象) 类 (创建) 对象 特点: 1.面向对象 2.跨平台 3.安全性 4.多线程 java程序基本结构 1. java源代码文件实际是普通的文本文件,源代码文件必须是.java扩展名,且必须小写 2. …...
Mybatis做批量操作
前面我们将动态标签foreach的时候,做过批量操作,但是foreach只能处理记录数不多的批量操作,数据量大了后,先不说效率,能不能成功操作都是问题,所以这里讲一讲Mybatis正确的批量操作方法: 在获取…...
C/C++动静态库的制作与原理 -- 静态库,动态库,目标文件,ELF文件,动态链接,静态链接
目录 1. 什么是库 2. 静态库 2.1 静态库的制作 2.2 静态库的使用 3. 动态库 3.1 动态库的制作 3.2 动态库的使用 4. 目标文件 5. ELF文件 6. ELF从形成到加载轮廓 6.1 ELF形成可执行 7.2 ELF可执行文件加载 7. 理解链接和加载 7.1 静态链接 7.2 ELF加载与进程地…...
Java 并发编程之synchronized
一、前言 在并发编程中,多个线程访问同一个共享资源时,我们必须考虑如何维护数据的原子性。在JDK1.5之前,Java是依靠Synchronized关键字实现锁功能来做到这点的。Synchronized是JVM实现的一种内置锁,锁的获取和释放是由JVM隐式实…...
Windows 11【1001问】查看Windows 11 版本的18种方法
随着技术的飞速发展,操作系统作为连接硬件与软件的核心桥梁,其版本管理和更新变得尤为重要。对于用户而言,了解自己设备上运行的具体Windows 11版本不仅有助于优化系统性能,还能确保安全性和兼容性。然而,不同场景和需…...
python 元组tuple
元组:有序不可变列表 (相当于只读的list) 注意:元组里的普通元素不可以修改,但是元组里的list可以修改 index(元素) 查找某个元素,有的话返回下标,没有的话报错 count(元素) 统计某元素在元组中出现的次数 len(元组) 统计元组内的元素个数 #定义元组,元组支持嵌套 t1("…...
485 多路信号采集,校验干扰问题
在RS-485总线中同时采集多路信号时,若某一路出现CRC校验失败,通常由总线冲突、信号干扰或硬件设计缺陷引起。以下是具体影响分析和解决方案: 一、多路信号同时采集的影响 1. 总线冲突风险 现象:多路信号同时发送时,485总线(半双工)无法区分信号,导致数据叠加损坏。 后…...
【Eureka 缓存机制】
今天简单介绍一下Eureka server 的缓存机制吧✌️✌️✌️ 一、先来个小剧场:服务发现的"拖延症" 想象你是个外卖小哥(客户端),每次接单都要打电话问调度中心(Eureka Server):“现在…...
MySQL并发知识(面试高频)
mysql并发事务解决 不同隔离级别下,mysql解决并发事务的方式不同。主要由锁机制和MVCC(多版本并发控制)机制来解决并发事务问题。 1. mysql中的锁有哪些? 表级锁: 场景:表级锁适用于需要对整个表进行操作的情况,例如…...
Git GitHub基础
git是什么? Git是一个分布式版本控制系统,用于管理源代码的变更。它允许多个开发者在同一个项目上协作,同时跟踪每个修改的历史记录。 关键词: 分布式版本控制软件 软件 安装到我们电脑上的一个工具 版本控制 例如论文&…...
Rabbit MQ 高频面试题【刷题系列】
文章目录 一、公司生产环境用的什么消息中间件?二、Kafka、ActiveMQ、RabbitMQ、RocketMQ有什么优缺点?三、解耦、异步、削峰是什么?四、消息队列有什么缺点?五、RabbitMQ一般用在什么场景?六、简单说RabbitMQ有哪些角…...
Ubantu22.04系统docker部署Open WebUI+Ollama【教程】
Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 AI 平台,旨在完全离线运行。它支持各种 LLM 运行器,如 Ollama 和 OpenAI 兼容的 API,并内置了 RAG 推理引擎,使其成为强大的 AI 部署解决方案。 1.docker拉取镜像 &#x…...
知识图谱科研文献推荐系统vue+django+Neo4j的知识图谱
文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站,有好处! 📑 编号:D030 📑 vuedjangoneo4jmysql 前后端分离架构、图数据库 📑 文献知识图谱&#…...
我的世界开发模组的心得体会
最头疼的问题 本人也是小白,也就跟着ai学学怎么开发模组,不会的上网搜搜,但是目前最令我头疼的就是运行rundata和runcilent时的模块冲突,解决办法就是使用以下的build.gradle代码,不要接受人工智能的建议,…...
HTML:自闭合标签简单介绍
1. 什么是自结束标签? 定义:自结束标签(Self-closing Tag)是指 不需要单独结束标签 的 HTML 标签,它们通过自身的语法结构闭合。语法形式: 在 HTML5 中:直接写作 <tag>,例如 …...
Oracle性能调优(一):时间模型统计
Oracle性能调优(一):时间模型统计 时间模型统计视图时间模型统计指标时间模型统计视图 📖 DB Time的含义: DB Time表示前台会话在数据库调用中所花费的总时间,它是衡量数据库实例总负载的一个重要指标。DB Time是从实例启动时开始累计测量的,其计算方法是将所有前台会话…...
MacBook Pro使用FFmpeg捕获摄像头与麦克风推流音视频
FFmpeg查看macos系统音视频设备列表 ffmpeg -f avfoundation -list_devices true -i "" 使用摄像头及麦克风同时推送音频及视频流: ffmpeg -f avfoundation -pixel_format yuyv422 -framerate 30 -i "0:1" -c:v libx264 -preset ultrafast -b:v 1000k -…...
【构建工具】Gradle Kotlin DSL中的大小写陷阱:BuildConfigField
在Android开发当中,BuildConfig是一个非常有用的功能,它允许我们在构建过程中定义常量,并在运行时使用它们。But!!当我们从传统的Groovy DSL迁移到Kotlin DSL时或者被Android Studio坑的时候,有一些细微的差…...
Linux网络 TCP全连接队列与tcpdump抓包
TCP全连接队列 在 Linux 网络中,TCP 全连接队列(也称为 Accept 队列)是一个重要的概念,用于管理已经完成三次握手,即已经处于 established 状态但尚未被应用程序通过 accept( ) 函数处理的 TCP 连接,避免因…...
ChatGPT与DeepSeek:开源与闭源的AI模型之争
目录 一、模型架构与技术原理 二、性能能力与应用场景 三、用户体验与部署灵活性 四、成本与商业模式 五、未来展望与市场影响 六、总结 随着人工智能技术的飞速发展,ChatGPT和DeepSeek作为两大领先的AI语言模型,成为了行业内外关注的焦点。它们在…...
泛微Ecode新增Button调用服务器中的JSP页面里的方法
前言 前端Ecode调用 后端接口编写 JSP文件方法 总结 前言 因为我们是从之前E8版本升级到E9的,所以会有一些接口是通过jsp文件来实现前后端调用的,这里介绍的就是如果你有接口是写在jsp文件里面调用的,但是你又想在Ecode中调用的对应的接…...
知识图谱+智能问诊预诊系统vue+django+neo4j架构、带问诊历史
文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站,有好处! 🤍编号:D032 🤍智能问答:智能问答自诊、预诊功能,同时可以保存问答历史 &…...
redis repl_backlog_first_byte_offset 这个字段的作用
repl_backlog_first_byte_offset 是 Redis 复制积压缓冲区(Replication Backlog)中的一个关键字段,其作用是 标识积压缓冲区中第一个字节对应的全局复制偏移量。 通俗解释 当主从节点断开重连时,Redis 需要通过复制积压缓冲区&am…...
第49天:Web开发-JavaEE应用SpringBoot栈模版注入ThymeleafFreemarkerVelocity
#知识点 1、安全开发-JavaEE-开发框架-SpringBoot&路由&传参 2、安全开发-JavaEE-模版引擎-Thymeleaf&Freemarker&Velocity 一、开发框架-SpringBoot 参考:https://springdoc.cn/spring-boot/ 访问SpringBoot创建的网站 1、路由映射 RequestMapping…...
python数据容器切片
从一个序列中取出一个子序列 序列[起始位置:结束位置:步长] 起始位置和结束位置 省略,表示从头取到尾 步长省略表示1 步长负数,表示从后往前取 步长-1 等同于将序列反转了...
GCM模式在IPSec中的应用
本文详细介绍使用GCM模式加密的IPSec数据包的组成部分及验证方法。 关联RFC-4106 The Use of Galois/Counter Mode (GCM) in IPsec Encapsulating Security Payload (ESP) GCM数据包格式:此处采用ESP封装(未加密)数据包。用于介绍数据包的详…...
Zynq移植canopen协议站canfestival+控制电机运动
一、 内容介绍 从零开始,在ZYNQ开发板上移植cnafestival,并最终控制电机运动。主要分别五部分 1. Vivado导出硬件XSA文件 2. 创建vitis工程,并移植Canfestival 3. 对象字典工具的安装及使用 4. 开发板通过SDO报文配置电机PDO参数 5. 开发板通…...
弱监督语义分割学习计划(2)-使用CoT进行Open Vocabulary Label简单实现类激活图
零: 项目说明 是这样的一个事情,经过与deepseek的一番讨论和交流,DeepSeek为我设计了一个30天高强度学习计划,重点聚焦弱监督/无监督语义分割在野外场景的应用,结合理论与实践,并最终导向可落地的开源项目。目前开始了…...
TCP/IP 5层协议簇:网络层(IP数据包的格式、路由器原理)
目录 1. TCP/IP 5层协议簇 2. IP 三层包头协议 3. 路由器原理 4. 交换机和路由的对比 1. TCP/IP 5层协议簇 如下: 2. IP 三层包头协议 数据包如下:IP包头不是固定的,每一个数字是一个bit 其中数据部分是上层的内容,IP包头最…...
ISP 常见流程
1.sensor输出:一般为raw-OBpedestal。加pedestal避免减OB出现负值,同时保证信号超过ADC最小电压阈值,使信号落在ADC正常工作范围。 2. pedestal correction:移除sensor加的基底,确保后续处理信号起点正确。 3. Linea…...
Mybatis调用存储过程
在mysql数据库中创建一个存储过程: DELIMITER $$ CREATEPROCEDURE mybatisdemo1.pgetallusers(IN sid INT,IN eid INT)BEGINSELECT * FROM sb_users WHERE id>sid AND id<eid;END$$ DELIMITER ;在Mapper接口里创建方法,和普通的查询数据方法没区别…...
uniapp 系统学习,从入门到实战(六)—— 样式与布局
全篇大概 4700 字(含代码),建议阅读时间 30min 📚 目录 Flex 布局在 UniApp 中的应用响应式设计与适配多端使用 SCSS 提升样式开发效率实战案例演示总结 1. Flex 布局在 UniApp 中的应用 1.1 基础布局实现 通过 display: flex 快速构建弹性容器&#…...
微服务学习(1):RabbitMQ的安装与简单应用
目录 RabbitMQ是什么 为什么要使用RabbitMQ RabbitMQ的安装 RabbitMQ架构及其对应概念 队列的主要作用 交换机的主要作用 RabbitMQ的应用 通过控制面板操作(实现收发消息) RabbitMQ是什么 RabbitMQ是一个开源的消息队列软件(消息代理…...
【Spring】Spring AOP原理
目录 前言 代理模式 静态代理 优缺点 动态代理 JDK动态代理 工作原理 JDK动态原理实现关键步骤 CGLib动态代理 CGLIB动态代理实现关键步骤 总结 前言 在上一篇中,我们讲解了什么是AOP,以及Spring AOP是如何使用的,那么本篇我们就…...
CentOS vs Ubuntu - 常用命令深度对比及最佳实践指南20250302
CentOS vs Ubuntu - 常用命令深度对比及最佳实践指南 引言 在 Linux 服务器操作系统领域,CentOS 和 Ubuntu 是广泛采用的发行版。它们在命令集、默认工具链及生态系统方面各有特点。本文深入剖析 CentOS 与 Ubuntu 在常用命令层面的异同,并结合实践案例…...
【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter27-工作者线程
二十七、工作者线程 工作者线程 前端开发者常说:“JavaScript 是单线程的。”这种说法虽然有些简单,但描述了 JavaScript 在浏览器中的一般行为。因此,作为帮助 Web 开发人员理解 JavaScript 的教学工具,它非常有用。单线程就意味…...
微信小程序 - 页面跳转(wx.navigateTo、wx.redirectTo、wx.switchTab、wx.reLaunch)
API 跳转 1、wx.navigateTo (1)基本介绍 功能:保留当前页面,跳转到应用内的某个页面,使用该方法跳转后可以通过返回按钮返回到原页面 使用场景:适用于需要保留当前页面状态,后续还需返回的情…...
vscode使用豆包MARSCode----集成doubao1.5 DeepSeekR1 DeepseekV3模型的ai编程插件
引入扩展 打开VSCode扩展窗口,在搜索窗口搜索MarsCode,找到MarsCode 插件单击「install」,完成安装,登录即可使用MarsCode 编程助手。 主要功能 主要快捷键 / explain 解释项目代码,AI 返回的内容有结构分类&#…...
C 语言共用体:深入理解与实践】
目录 一、引言 二、共用体的定义和基本语法 三、共用体的使用 3.1 声明共用体变量 3.2 给共用体成员赋值 3.3 共用体的内存布局 四、共用体的应用场景 4.1 节省内存空间 4.2 处理不同类型的数据 五、共用体使用的注意事项 六、总结 一、引言 在 C 语言中,共…...
Cherry Studio + 火山引擎 构建个人AI智能知识库
🍉在信息化时代,个人知识库的构建对于提高工作效率、知识管理和信息提取尤为重要。尤其是当这些知识库能结合人工智能来智能化地整理、分类和管理数据时,效果更为显著。我最近尝试通过 Cherry Studio 和 火山引擎 来搭建个人智能知识库&#…...
曹操智行构建国内首个全域自研闭环智驾生态
2月28日,曹操出行举办曹操智行自动驾驶平台上线仪式,宣布已成功构建国内首个“F立方”全域自研闭环智驾生态,同时在苏杭两地开启Robotaxi运营试点,并投放搭载吉利最新智驾系统的车辆。 此次试点运营,标志着曹操出行在…...
在 ASP.NET Core 中压缩并减少图像的文件大小
示例代码:https://download.csdn.net/download/hefeng_aspnet/90294127 在当今的数字时代,图像是 Web 应用程序和用户体验不可或缺的一部分。但是,处理大型图像文件可能会导致网页加载缓慢和更高的存储费用。为了解决这个问题,在…...
58、深度学习-自学之路-自己搭建深度学习框架-19、RNN神经网络梯度消失和爆炸的原因(从公式推导方向来说明),通过RNN的前向传播和反向传播公式来理解。
一、RNN神经网络的前向传播图如下: 时间步 t1: x₁ → (W_x) → [RNN Cell] → h₁ → (W_y) → y₁ ↑ (W_h) h₀ (初始隐藏状态) 时间步 t2: x₂ → (W_x) → [RNN Cell] → h₂ → (W_y) → y₂ ↑ (W_h) h₁ 时间…...
【Qt-信号与槽】connect函数的用法
🏠个人主页:Yui_ 🍑操作环境:Qt Creator 🚀所属专栏:Qt 文章目录 1.信号和槽的概念1.1 信号的本质1.2 槽的本质1.3 补充说明2. 信号和槽的使用2.1 connect函数介绍2.2 connect函数的简单使用2.2.1 图形化方…...
sql深入学习
文章目录 前言知识学习注释的两种形式字符型注入万能密码 布尔盲注报错注入堆叠注入时间盲注二次注入 小技巧 前言 这次学习建立在对数据库有基本的认识,了解基础的增删改查语句,数字型注入和字符型注入的基础上,进一步深入学习知识…...