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

数据结构(3)线性表-链表-单链表

我们学习过顺序表时,一旦对头部或中间的数据进行处理,由于物理结构的连续性,为了不覆盖,都得移,就导致时间复杂度为O(n),还有一个潜在的问题就是扩容,假如我们扩容前是100个大小的元素空间,一旦扩容以后(我们就说二倍的扩),那就是200,但我们实际上就只存105个元素,那不就有95个元素所对应的空间被浪费了吗?怎样才能解决这样的问题呢?

带着疑问,来学习线性表的其中之一,链表。

一、链表

链表是物理存储结构上非连续的线性表,数据元素的逻辑顺序是通过链表中的指针来实现的。

按照指针方向链表分为单向链表,双向列表和循环链表。

按内存管理的话还是静态链表和动态链表

二、单链表

本次就进行单链表的学习。

1.单链表概述

单链表一般作Single List

单链表是什么东西呢?

单链表就好像是火车一样,火车的每个单位是车厢,车头是动力,车厢与车厢之间存在有结构连接。

为什么要这么对比呢?

单链表的基本单位就是结点,结点与结点之间由指针连接起来,这是静态的看;火车在淡旺季可以选择加车厢和减车厢,而我们的单链表对应的操作就是增加或者删除结点。

单链表属于链表,根据指针的方向取名单链表,单链表结点间的指针方向是只有一个的。

我们在申请顺序表的大小的时候用的是realloc,第一个参数是需要修改的内存的地址,第二个参数是改为的内存空间的大小,这个内存空间我们申请的时候直接是一整块全部申请下来,但是对于单链表则不同,如上面画的图,我们每次申请都仅仅申请一个结点,任意取出来逻辑上相邻的两个结点:

现在视角落在存储了整型2的这个结点上,这个结点存储了两个东西,一个是数据,一个是下一个结点的地址,由此我们的单链表的结点就是一个结构体变量,一个是存储的数据,一个是结点结构体类型的指针(因为通过这个指针访问下一个结点时,还是一个结点结构体,所以必须是结点结构体类型的指针变量)。

2.链表的性质

由这个简略图给出链表的通用特性:

①链表在逻辑上是连续的,物理空间上不一定连续

②结点一般是在堆上申请的

③从堆上申请的空间不一定连续

了解即可。

3.单链表结点结构的创建

非常清晰了,直接给出来:

为了单链表存储数据类型的可修改性,一个typedef,为了后续与结点这个结构体操作的简便性,再来一个typedef,这点在顺序表中已经见过了,不多解释。

不管是先前的图片还是后续的创建,都展示出了结点的两个属性,一般存放数据的被称作数据域,存放下一个结点地址的叫做指针域。

4.单链表的打印

有了单链表的结点,如果要实现我们所画的图片的效果应该是这样的:

为每一个结点创建内存空间,并且赋值,实际上发现,我们逻辑上的1,2,3,4是通过指针来实现的。

如果对于这样的一个链表,我们该如何实现遍历打印呢?

通过plist开始访问链表的数据,进去打印该结点的数据,并且将指针该为下一个结点的地址,最终下一个结点的next指针为空则遍历完成。

进去就打印,并且跳到下一个链表结点里,如果不为空则继续打印,为空说明已经遍历到尾,可以停止。

当然,其实可以把assert换一下,因为如果链表为空,直接打印个NULL,也可以:

5.单链表的插入结点操作

①单链表的尾插

先想尾插的参数,肯定得把单链表的地址传过去吧,然后你插什么总得告诉我吧。

所以就俩参数,一个是单链表的地址(如上面的plist),还有想要插入的元素是什么。

进去第一件事可不是去插入,就像顺序表插入一样,你总得看看有没有地方让你插入吧,类比过来,就得先生成个结点,这个结点专门用来存放本次插入的值,指针的话由于尾插,所以肯定是NULL。

有了这个结点以后就得把它像连接火车车厢一样接上去,很显然,需要先找到链表尾,其实我们打印的时候用的while循环结束后,指针已经到了单链表的尾了,所以拿过来即可,找到尾以后把原来的尾的指针从NULL变成新创建的结点的地址即可。

思路有了,代码表达:

逢开辟必检查。

而链表的插入分为空链表的尾插和非空链表的尾插,至于为什么,先往下看:

非空:

拿着链表地址,遍历到最后,把创建的新结点地址赋给尾结点即可。

但是如果是空链表呢:

你非空确实传过来地址,我顺着地址修改值就行,但是如果是空的链表呢?你传过来的是什么,是NULL,那你再修改,对实际的链表根本就是无济于事啊。所以为了对真正的链表的里面的值进行修改,我们不能传值了,只能传过来这个空链表的指针的地址(为了通过这个地址去修改这个指针)

地址的地址,或者说一级指针的地址应该用二级指针来承接,所以形参写的时候应该是二级指针,修改为:

其中,链表不为空需要遍历到链表尾部的地址,因为后续需要用这个地址去修改NULL,这样的话到尾结点就该停,而尾结点与其他结点的不同就是下一个结点的地址为空。

测试代码如下:

说明确实插入了。

当然,还得防范一下传过来的指针,毕竟plist可以为空(即链表为空),但是pplist存的可是链表的地址的啊,这玩意为空算哪门子事:

加个assert防范一下。

②单链表的头插

还是有了经验以后,参数还是pplist,并且分开链表为空和链表不为空的情况:

首先还是不为空:

让plist指向我们的newnode,newnode指向我们的第一个结点,这样的话赋值就得先把plist的值赋给newnod->next了,然后再把plist的值修改了:

而且发现,如果链表为空,plist为NULL,赋过去,newnode地址给plist,也没毛病。

调试完毕,没啥问题

6.单链表的删除结点操作

①单链表的尾删

释放最后一块空间,并将尾结点的前一个结点的next指针改成NULL。

这就要求你必须找到两个位置的指针,一个是ptail,一个是ptail前的prev,我们以这样的思路来想办法遍历,示意图:

ptail开始指向第一个元素,prev由于必须在ptail前,此时应该为空;

进入检测以后看看这个结点是不是尾结点,是的话就该停止遍历了,即判断条件为ptail->next != NULL。

问题就在于循环体如何实现ptail往后走的同时来让prev在ptail前,很简单,可以说是keep up with:

如果不是尾结点的话,prev先站到现在ptail的位置,因为下一步就是后移,这样出了循环就是一个在前一个在后的效果,如:

当然不能忘了释放空间和防范野指针:

最后三条解释一下,prev->next = NULL确实是修改了链表的实际结构,因为prev是尾结点前那个结点的地址,顺着地址肯定能修改成功实际的链表;有了尾结点地址,free不用多解释;重点在于ptail = NULL,它可不是真的把尾结点指针置空了,或者说它即使置空也不影响实际链表中的地址还存在(如果存了的话),只是free以后习惯置空,作用是防止在函数内部再被调用。

画图解释:

正如我们插入操作的时候需要防范链表是不是空链表一样,对应过来就是,我们删除的恰好就是唯一的一个结点,即第一个结点,代码思路还行不行得通:

就盯着这个看,很明显,上来就是NULL,这么一搞,prev直接就是随机值。

所以如果只有一个结点的话,直接free并且赋plist为空即可(当然,在函数里是*pplist)。

完善:

测试:

两端代码都成功。

②单链表的头删

头删其实没什么可多说的,把plist修改为原plist->next,再对原plist的空间释放即可:

测试代码:

没啥好讲的,连图都不用画,空想一下就能想出来。

7.单链表的查找操作

参数:你想查哪个链表,地址给我,你想查链表里哪个元素,元素也给我,所以就俩参数,而且不会对链表的结构产生改变,传值即;上面都没说返回值的事,因为不管是打印还是对链表结构的改变,不需要返回什么,但是查找,你找到了给我个地址让我知道啊,找不到你总得告诉我找不到吧。

查找我写了两个版本:
第一个版本是这样的:

最开始实际上我写的是:

while (phead->data != x)
{
    phead = phead->next;
}

if(phead == NULL)

        return NULL;

else

        return phead;

思路就是,要是这个结点的值不是我要的值,就往死里给我遍历,跳出循环以后有俩情况,一个就是为空了都,那说明找完都没找到,直接返回NULL就行;一个就是找到了,跳出循环即可。

问题有俩,一个是遍历到尾了,phead就是NULL,再解引用去判断data与x相等不相等就不礼貌了,再来就是其实我写的if-else语句其实就是return phead的意思,(我刚开始就意识到了if-else的化简,丝毫没有发现第一个问题,最后代码报错检查了检查才发现)

第一次检查修改为:

while (phead->data != x)
{
    phead = phead->next;
}

        return phead;

然后发现空指针解引用问题:

while (phead->data != x && phead != NULL)
{
    phead = phead->next;
}

        return phead;

加上了还给我整事,后来想了想,这就是当时学逻辑运算符的短路问题,如果遍历完都找不到你先解引用才去检验是不是空,这样代码当然还是会报错,所以还得:

while (phead != NULL && phead->data != x)
{
    phead = phead->next;
}

        return phead;

才没毛病。

第二个版本是这样的:

while循环疯狂遍历,每次遍历到的结点去检测一下data,如果遍历完都没找到,直接返回NULL。

这个版本写出来其实是因为想放弃第一个版本了,但是又因为自己不服气,就有了上面的修改过程。

8.单链表指定位置的插入和删除操作

①指定位置之前插入数据

指定位置的插入和删除,肯定是在某个特定的值前才进行,所以链表在这种情况下不会为空

这点意味着要在3这个结点前插结点,创建新结点就不说了,来看指针怎么变,这种情况下传的肯定是链表中某个节点的地址,这样看来的话newnode->next不成问题,但是前面一个结点的next指针可就炸缸了啊,因为你给我的是3的指针,给了这个我往后遍历顺着走就行,往前遍历可就得想想办法了,还是得写一循环遍历,当该指针next为3这个结点就停手,给目标节点起名pos,给目标节点前一个结点起名prev(取自previous)。

准备工作:

准备好结点,准备好要改变的值以后,就是赋值

最后:

但有一特例,如果指定位置前是链表的头呢:

这个时候的prev->next永远不会是pos,就会无休止的找下去,这样的话会导致出错,干脆如果plist==pos,直接调头插去,懒得再写逻辑了,反正也跟写头插一样:

测试代码:

不管头插还是中间的插入都没啥大毛病。

②指定位置之后插入数据

注意参数即可,因为链表的结点的成员是一个data,一个next指针,所以往后插根本不需要指定位置的前一结点的地址,也就不需要链表的头结点地址。

先按照正常元素往中间插的思路写:

newnode->next指向pos->next,pos->next指向newnode即可,一定要注意顺序。

newnode->next = pos ->next;

pos->next = newnode;

pos->next = newnode;

newnode ->next= pos ->next;

真按照下面的干了,直接炸了,因为pos->next直接被你用newnode覆盖了,导致第二句代码newnode->next指的还是newnode自己。

直接写出来就行,但是插入还得小心点(空就不用考虑了,肯定是查找后的指针,不可能为空,即有pos就不用验空),想想第一个结点插入,由于是之后,那跟找中间的插也没啥区别;想想尾结点插入:

对着代码看,也没啥毛病。

测试一下:

没犯啥毛病,成功了。

③删除指定位置的结点

一个遍历到pos前,一个赋值改指针指向,一个释放:

然后就是看看首或者尾会不会出幺蛾子:

上来就发现了,我们的逻辑是prev->next是不是pos,根本无法检测pos刚好为头的情况,所以还是写个if-else去头删:

尾结点没炸。

测试:

④删除指定位置后的结点

还是说,指定位置后可以直接通过pos找到,就不需要传plist了。

不想写那么多next就将要删去的结点的地址存到del里,方便自己看以及方便改指针和释放:

这么写增加代码可读性。

想想头尾会不会出啥问题,头的话头后删,跟我们从中间找一个结点删效果一样;尾结点后面没结点,想了想指定位置后结点删去不能有尾结点,所以加到assert里:

测试:

9.单链表的销毁

销毁单链表就把头结点的地址传过来。

很明显,如果直接free掉plist那么后面的结点全部都丢了,所以在free结点前记录下一个结点,直到下一个结点为NULL再停止:

三、对比顺序表和单链表

刚刚学完,可谓是手感火热,顺序表和单链表都有插入和删除操作。

其中顺序表的头插头删由于其空间的连续性,所以必须先将已有元素后移,才能插入,后移就会用一个循环,时间复杂度是O(n);

顺序表的尾插尾删,不需要移动数据,所以也不需要循环,插就一句根据地址赋值的事,尾删更简单,直接size--即可。时间复杂度是O(1)

单链表的头插头删,头插由于不需要将其他元素后移,直接针对链表头结点所给指针改变一下next指针;头删就先改头结点指向地址,再free即可。

单链表的尾插尾删,最影响时间复杂度的就是while循环去找尾结点的指针ptail,导致时间复杂度为O(n)。

我们现在就学了这两种数据结构,已经可以看出来,没有哪一种数据结构就能一招鲜吃遍天,各有各的优点,你尾部频繁的增删改,那就用顺序表,头部频繁增删改那就单链表。

解释这个就是为了解释我最开始所说的,学习各种各样的数据结构,是为了算法里选择最优的数据结构。

另外,单链表由于每个结点都是在堆区申请独立的空间,所以不会存在内存浪费的情况,这种优势是针对顺序表来说的,因为在顺序表里有一开辟内存的函数叫CheckCapacity,二倍扩容空间如果不用,那就会浪费。

相关文章:

数据结构(3)线性表-链表-单链表

我们学习过顺序表时,一旦对头部或中间的数据进行处理,由于物理结构的连续性,为了不覆盖,都得移,就导致时间复杂度为O(n),还有一个潜在的问题就是扩容,假如我们扩容前是10…...

Python 中的 typing.ClassVar 详解

一、ClassVar 的定义和基本用途 ClassVar 是 typing 模块中提供的一种特殊类型,用于在类型注解中标记类变量(静态变量)。根据官方文档,使用 ClassVar[…] 注释的属性表示该属性只在类层面使用,不应在实例上赋值 例如&…...

主流数据库运维故障排查卡片式速查表与视觉图谱

主流数据库运维故障排查卡片式速查表与视觉图谱 本文件将主文档内容转化为模块化卡片结构,并补充数据库结构图、排查路径图、锁机制对比等视觉图谱,以便在演示、教学或现场排障中快速引用。 📌 故障卡片速查:连接失败 数据库检查…...

Unity:延迟执行函数:Invoke()

目录 Unity 中的 Invoke() 方法详解 什么是 Invoke()? 基本使用方法 使用要点 延伸功能 ❗️Invoke 的局限与注意事项 在Unity中,延迟执行函数是游戏逻辑中常见的需求,比如: 延迟切换场景 延迟播放音效或动画 给玩家时间…...

医学影像系统性能优化与调试技术:深度剖析与实践指南

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C、C#等开发语言,熟悉Java常用开…...

【HTML5学习笔记1】html标签(上)

web标准(重点) w3c 构成:结构、表现、行为,结构样式行为相分离 结构:网页元素整理分类 html 表现:外观css 行为:交互 javascript html标签 1.html语法规范 1) 所有标签都在…...

SearchIndexablesProvider

实现的 provider 根据索引添加文档可知,该 provider 需要继承自 frameworks/base/core/java/android/provider/SearchIndexablesProvider.java 类,并且添加权限 android.permission.READ_SEARCH_INDEXABLES。过滤 Settings 代码,可以轻易找到…...

《k-means 散点图可视化》实验报告

一,实验目的 本次实验旨在通过Python编程实现k - means算法的散点图可视化。学习者将编写代码,深入理解聚类分析基本原理与k - means算法实现流程,掌握数据聚类及可视化方法,以直观展示聚类结果。 二,实验原理 k-mea…...

数学复习笔记 12

前言 现在做一下例题和练习题。矩阵的秩和线性相关。另外还要复盘前面高数的部分的内容。奥,之前矩阵的例题和练习题,也没有做完,行列式的例题和练习题也没有做完。累加起来了。以后还是得学一个知识点就做一个部分的内容,日拱一…...

Web-CSS入门

WEB前端,三部分:HTML部分、CSS部分、Javascript部分。 1.HTML部分:主要负责网页的结构层 2.CSS部分:主要负责网页的样式层 3.JS部分:主要负责网页的行为层 **基本概念** 层叠样式表,Cascading Style Sh…...

Qt/C++编写音视频实时通话程序/画中画/设备热插拔/支持本地摄像头和桌面

一、前言 近期有客户提需求,需要在嵌入式板子上和电脑之间音视频通话,要求用Qt开发,可以用第三方的编解码组件,能少用就尽量少用,以便后期移植起来方便。如果换成5年前的知识储备,估计会采用纯网络通信收发…...

Ubuntu快速安装Python3.11及多版本管理

之前文章和大家分享过,将会出一篇专栏(从电脑装ubuntu系统,到安装ubuntu的常用基础软件:jdk、python、node、nginx、maven、supervisor、minio、docker、git、mysql、redis、postgresql、mq、ollama等),目前…...

Qt功能区:Ribbon使用

Ribbon使用 1. Ribbon功能区介绍1.1 样式 2. 基本功能区设置2.1 安装动态库(推荐)2.2 在MainWindow中使用Ribbon2.3 在QWidget中使用SARibbonBar2.4 创建Category和Pannel2.5 ContextCategory 上下文标签创建 2.6 ApplicationButton2.7 QuickAccessBar和…...

【学习心得】Jupyter 如何在conda的base环境中其他虚拟环境内核

如果你在conda的base环境运行了jupyter lab打开了一个ipynb文本,此时选择的内核是base虚拟环境的Python内核,如果我想切换成其他conda虚拟环境来运行这个文件该怎么办?下面我们试着还原一下问题,并且解决问题。 【注】 这个问题出…...

在微创手术中使用Kinova轻型机械臂进行多视图图像采集和3D重建

在微创手术中,Kinova轻型机械臂通过其灵活的运动控制和高精度的操作能力,支持多视图图像采集和3D重建。这种技术通过机械臂搭载的光学系统实现精准的多角度扫描,为医疗团队提供清晰且详细的解剖结构模型。其核心在于结合先进的传感器配置与重…...

[Java][Leetcode middle] 238. 除自身以外数组的乘积

第一个想法是: 想求出所有元素乘积,然后除以i对应的元素本书;这个想法是完全错误的: nums[I] 可能有0题目要求了不能用除法 第二个想法是: 其实写之前就知道会超时,但是我什么都做不到啊! 双…...

【leetcode】144. 二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3] 解释: 示例 2: 输入:root [1,2,3,4,5,null,8,null,null,6,7,9] 输出&#xff1a…...

SpringBoot常用注解详解

文章目录 1. 前言2. 核心注解2.1 SpringBootApplication2.2 Configuration2.3 EnableAutoConfiguration2.4 ComponentScan2.5 Bean2.6 Autowired2.7 Qualifier2.8 Primary2.9 Value2.10 PropertySource2.11 ConfigurationProperties2.12 Profile 3. Web开发相关注解3.1 Control…...

中文分词与数据可视化02

jieba 库简介 jieba(结巴分词)是一个高效的中文分词工具,广泛用于中文自然语言处理(NLP)任务。它支持以下功能: 分词:将句子切分为独立的词语。 自定义词典:添加专业词汇或新词&am…...

SSH主机密钥验证失败:全面解决方案与技术手册

一、问题本质与安全机制解析 SSH(Secure Shell)的主机密钥验证是安全通信的核心机制,当出现"Host key verification failed"错误时,表明客户端检测到服务器身份异常。这种设计可有效防范中间人攻击(Man-in-the-Middle),其工作原理…...

buuctf Crypto-鸡藕椒盐味1

1.题目: 公司食堂最新出了一种小吃,叫鸡藕椒盐味汉堡,售价八块钱,为了促销,上面有一个验证码,输入后可以再换取一个汉堡。但是问题是每个验证码几乎都有错误,而且打印的时候倒了一下。小明买到了一个汉堡&a…...

真题卷001——算法备赛

蓝桥杯2024年C/CB组国赛卷 1.合法密码 问题描述 小蓝正在开发自己的OJ网站。他要求用户的密码必须符合一下条件: 长度大于等于8小于等于16必须包含至少一个数字字符和至少一个符号字符 请计算一下字符串,有多少个子串可以当作合法密码。字符串为&am…...

基于MCP的桥梁设计规范智能解析与校审系统构建实践

引言 在腾讯云开发者社区中,有多种MCP工具可以用于本系统的开发和优化中,以下是一些潜在的应用场景: ‌PDF解析工具‌:如pdfplumber等,可以用于规范文件的预处理,提取文本和图像信息。‌自然语言处理工具…...

matlab与python问题解析

Python requests乱码的五种解决办法 Python requests乱码的五种解决办法_requests.get乱码-CSDN博客 requests库post请求参数data、json和files的使用 requests库post请求参数data、json和files的使用_requests post data-CSDN博客 如何在浏览器中查看POST请求提交的数据内…...

【分布式锁通关指南 10】源码剖析redisson之MultiLock的实现

引言 本期我们将把目光聚焦在 Redisson 中另一个颇具代表性的分布式锁实现——MultiLock。它的核心思想是:一次性对多个独立的 RLock 进行加锁或解锁操作,只有当多个锁都成功加锁时才算真正完成锁的获取,一旦有任何一个失败,整体操…...

MySQL 8.0 OCP 1Z0-908 131-140题

Q131.You have upgraded the MySQL binaries from 5.7.28 to 8.0.18 by using an in-place upgrade. Examine the message sequence generated during the first start of MySQL 8.0.18: 。。。[System]。。。/usx/sbin/mysqld (mysqld 8.0.18-commercial) starting as process…...

实战解析MCP-使用本地的Qwen-2.5模型-AI协议的未来?

文章目录 目录 文章目录 前言 一、MCP是什么? 1.1MCP定义 1.2工作原理 二、为什么要MCP? 2.1 打破碎片化的困局 2.2 实时双向通信,提升交互效率 2.3 提高安全性与数据隐私保护 三、MCP 与 LangChain 的区别 3.1 目标定位不同 3.…...

从零开始学习three.js(20):three.js实现天气与时间动态效果(白天,黑夜,下雨,下雪)

基于Three.js的天气与时间动态效果实现 本文将通过代码解析,介绍如何使用Three.js实现动态天气(下雨、下雪)和时间(白天、黑夜)切换效果。完整代码基于一个交互式天气模拟项目,支持粒子密度、速度和环境亮…...

sqli-labs靶场23-28a关(过滤)

目录 less23(--过滤) less24(二次注入) less25(or过滤) less25a(or过滤) less26(--和空格过滤报错) less26a(--空格过滤盲注) …...

Sigmoid与Softmax:从二分类到多分类的深度解析

Sigmoid与Softmax:从二分类到多分类的深度解析 联系 函数性质:二者都是非线性函数 ,也都是指数归一化函数,可将输入值映射为0到1之间的实数 ,都能把输出转化成概率分布的形式,在神经网络中常作为激活函数使用。Softmax是Sigmoid的推广:从功能角度看,Softmax函数可视为…...

uni-app x正式支持鸿蒙原生应用开发

DCloud发布的HBuilderX 4.64正式版,支持编译uni-app x项目到鸿蒙平台,实现跨平台开发鸿蒙原生应用。至此,uni-app x 已经完成Android、iOS、鸿蒙、Web、微信小程序等主流平台全覆盖。 uni-app x,是下一代 uni-app,是一…...

【软件推荐——pdf2docx】

pdf2docx Open source Python library for converting PDF to DOCX. https://github.com/ArtifexSoftware/pdf2docx Install pip install pdf2docx使用 from pdf2docx import Converterpdf_file D:\my\c4611_sample_explain.pdf docx_file D:\my\c4611_sample_explain.d…...

HarmonyOS开发组件基础

个人简介 👨‍💻‍个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言&…...

JMeter 测试工具--组件--简单介绍

目录 ​编辑 一、测试计划(Test Plan) 二、线程组(Thread Group) 三、取样器(Sampler) 四、监听器(Listener) 五、逻辑控制器(Logic Controller) 六、断…...

ECPF 简介

ECPF(Embedded CPU Function,嵌入式CPU功能)是NVIDIA BlueField DPU特有的一种功能类型,和PF(Physical Function,物理功能)、VF(Virtual Function,虚拟功能)密…...

【Opencv】canny边缘检测提取中心坐标

采用opencv 对图像中的小球通过canny边缘检测的方式进行提取坐标 本文介绍了如何使用OpenCV对图像中的小球进行Canny边缘检测,并通过Zernike矩进行亚像素边缘检测,最终拟合椭圆以获取小球的精确坐标。首先,图像被转换为灰度图并进行高斯平滑…...

C#实现访问远程硬盘(附源码)

在现实场景中,我们经常用到远程桌面功能,而在某些场景下,我们需要使用类似的远程硬盘功能,这样能非常方便地操作对方电脑磁盘的目录、以及传送文件。那么,这样的远程硬盘功能要怎么实现了? 这次我们将给出…...

AI日报 · 2025年05月16日|Google DeepMind推出AlphaEvolve,能自主设计高级算法的编码代理

全球AI新闻日报 日期:2025年5月16日 目录 OpenAI与CoreWeave签署40亿美元新协议,GPT-4.1模型全面推出Google DeepMind推出AlphaEvolve,能自主设计高级算法的编码代理Anthropic律师因Claude模型虚构法律引用被迫道歉Meta推迟旗舰AI模型&quo…...

TCP/IP 知识体系

TCP/IP 知识体系 一、TCP/IP 定义 全称:Transmission Control Protocol/Internet Protocol(传输控制协议/网际协议)核心概念: 跨网络实现信息传输的协议簇(包含 TCP、IP、FTP、SMTP、UDP 等协议)因 TCP 和…...

记一次缓存填坑省市区级联获取的操作

先说缓存是什么? 缓存主要是解决高并发,大数据场景下,热点数据快速访问。缓存的原则首先保证数据的准确和最终数据一致,其次是距离用户越近越好,同步越及时越好。 再说我们遇到的场景: 接手项目后&#…...

【时空图神经网络 交通】相关模型2:STSGCN | 时空同步图卷积网络 | 空间相关性,时间相关性,空间-时间异质性

注:仅学习使用~ 前情提要: 【时空图神经网络 & 交通】相关模型1:STGCN | 完全卷积结构,高效的图卷积近似,瓶颈策略 | 时间门控卷积层:GLU(Gated Linear Unit),一种特殊的非线性门控单元目录 STSGCN-2020年1.1 背景1.2 模型1.2.1 问题背景:现有模型存在的问题1.2…...

uniapp实现在线pdf预览以及下载

uniapp实现在线pdf预览以及下载 在线预览 遇到的问题 后端返回一个url地址,我需要将在在页面中渲染出来。因为在浏览器栏上我输入url地址就可以直接预览pdf文件,因此直接的想法是通过web-view组件直接渲染。有什么问题呢?在h5端能够正常渲…...

【Rust闭包】rust语言闭包函数原理用法汇总与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

裸金属服务器和云服务器之间的差别

裸金属服务器能够直接在硬件上运行,不需要额外的虚化层,让每个应用程序或者是服务都能够在实际的硬件上运行,不需要和其他虚拟服务器来共享资源;而云服务器作为一种虚拟服务器,是通过虚拟化技术为企业提供一个独立的计…...

CentOS系统中升级Python 3.12.2版本

在CentOS系统中升级Python版本是一项常见的操作,尤其是在需要使用较新功能或满足某些软件依赖的情况下。以下是详细的步骤和注意事项,帮助您顺利完成Python版本的升级。 1. 升级Python版本前的准备 在开始升级之前,请确保以下几点&#xff1…...

win10-django项目与mysql的基本增删改查

以下都是在win10系统下,django项目的orm框架对本地mysql的表的操作 models.py----->即表对应的类所在的位置 在表里新增数据 1.引入表对应的在models.py中的类class 2.在views.py中使用函数:类名.objects.create(字段名值,字段名"值"。。。…...

图像处理:预览并绘制图像细节

前言 因为最近在搞毕业论文的事情,要做出一下图像细节对比图,所以我这里写了两个脚本,一个用于框选并同时预览图像放大细节,可显示并返回框选图像的坐标,另外一个是输入框选图像的坐标并将放大的细节放置在图像中&…...

针对面试-微服务篇

1.Spring Cloud 5大组件有哪些? 随着SpringCloudAlibba在国内兴起,我们项目中使用了一些阿里巴巴的组件 注册中心/配置中心 Nacos 负载均衡 Ribbon 服务调用 Feign 服务保护 sentinel 服务网关 Gateway 2. 我看你之前也用过nacos、你能说下nacos与eureka的区别?…...

SRS流媒体服务器(5)源码分析之RTMP握手

1.概述 学习 RTMP 握手逻辑前,需明确两个核心问题: rtmp协议连接流程阶段rtmp简单握手和复杂握手区别 具体可以学习往期博客: RTMP协议分析_rtmp与264的关系-CSDN博客 2.rtmp握手源码分析 2.1 握手入口 根据SRS流媒体服务器(4)可知&am…...

线程池(ThreadPoolExecutor)实现原理和源码细节是Java高并发面试和实战开发的重点

一、线程池核心流程图 ----------------- | 提交任务 | submit/execute -----------------|v ----------------- | 判断核心线程数 | < corePoolSize&#xff1f; -----------------|Yes |Nov v [创建新线程] -----------------| 队列是否满&a…...