数据结构与算法-线性表-单链表(Linked List)
1 线性表
1.2 单链表(Linked List)
顺序表在内存中是连续的进行存储,可以随机获取某个元素,但是在插入和删除元素的时候就非常不方便,需要移动很多相关的元素,链表就可以解决这个问题。
链表就是每个节点(Node)除了存储数据(书中称作数据域),还存储下一个节点的指针(书中称作指针域),此外还有一个头指向首元节点(第一个节点)。因为每个元素只有一个指针域,所以称为单链表(或者线性链表)。
赵钱孙李周吴郑王
这些姓氏在内存中用单链表存储的形式如下:
逻辑结构:
单链表的基本操作在王卓老师教程和书籍的基础上进行了增加了,另外因为在实际实现过程中,为了方便调试,顺序有做了一些修改,比如初始化单链表后,一般是要先插入一些结点,然后可以计算链表长度等,最后才进行销毁。这里实现的算法如下:
InitList(&L) // 初始化单链表
CreateListHead(&L, n) // 头插法创建单链表
CreateListTail(&L, n) // 尾插法创建单链表
GetElem(&L, i, &e) // 获取第i个结点,并用e返回
LocateELem(&L, &e) // 按值查找结点并返回位置,或者返回结点
ListInsert(&L, i, &e) // 插入结点,在 i-1 和 i 之间插入一个结点,新结点的位置就是 i
ListDelete(&L, i) // 删除结点,删除第 i 个结点
ListLength(&L) // 计算单链表表长度
ListEmpty(&L) // 判断单链表是否为空
ClearList(&L) // 清空单链表
DestroyList(&L) // 销毁单链表
在实现每个方法之前需要先定义单链表的节点:
// 声明 ElemType 的结构,链表中的每个结点存储的数据都是这个类型的。
// 这里为了简单方便,存储一个整数。在实际应用中,这里可以存储需要的数据。
typedef struct
{int x;
} ElemType;// 单链表的结点结构
typedef struct LNode
{ElemType data; // 结点数据,ElemType类型struct LNode *next; // 指向下一个结点的指针
} LNode, *LinkList; // LinkList 是指向 LNode 结构的指针类型,表示单链表的头结点指针
此外一些常量和顺序表类似:
// 声明一些常量
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0// Status 是函数返回值类型, 其值是函数结果状态代码。
typedef int Status;
// Boolean 定义布尔型,值就是 TRUE 和 FALSE。
typedef int Boolean;
1.2.1 初始化
单链表的初始化操作就是构造一个空的单链表。
【算法步骤】
- 生成新结点作为头结点,用头指针
L
指向头结点。 - 头结点的指针域置空。
【代码实现】
// 初始化链表
Status InitList(LinkList *L)
{*L = (LinkList)malloc(sizeof(LNode)); // 创建头节点if (*L == NULL){return OVERFLOW;}(*L)->next = NULL; // 初始化头节点的next指针为NULLreturn OK;
}
【算法分析】
非常容易看出,初始化算法的时间复杂度为 O(1)
。
1.2.2 头插法创建单链表
在初始化链表后,可以创建一些新结点插入到链表中,一种方法就是头插法,每次插入结点的时候,都放在头部,另外一种就是尾插法,每次插入的时候放在尾部。这节演示头插法,后面一节演示尾插法。
【算法步骤】
- 先初始化一个空链表。
- 根据要插入的结点数
n
,重复执行n
次(这里为了方便,每个结点的数据域为循环i
的值)。 - 生成新结点,将
i
值存入新结点的数据域中。 - 新结点的指针域指向头节点的指针域指向的结点。
- 头结点的指针域指向新结点。
【代码实现】
// 头插法创建单链表
Status CreateListHead(LinkList *L, int n)
{*L = (LinkList)malloc(sizeof(LNode)); // 初始化链表if (*L == NULL){return OVERFLOW;}(*L)->next = NULL; // 初始化头结点的next指针为NULLLNode *newNode; // 新结点指针for (int i = n; i > 0; i--){newNode = (LNode *)malloc(sizeof(LNode)); // 创建新结点if (newNode == NULL){return OVERFLOW;}newNode->data.x = i; // 设置新结点的数据newNode->next = (*L)->next; // 将新结点的next指针指向当前头结点的下一个结点(*L)->next = newNode; // 将头结点的next指针指向新结点}return OK;
}
因为是使用头插法,所以最后插入的元素在前面,因此这里使用 n ~ 1 的循环方式,保证链表存储的数据依次是 1 ~ n。
【算法分析】
创建多少个结点就要执行多少次创建新结点、插入到头部的操作,所以时间复杂度是 O(n)
。
[!NOTE]
其实这个方法可以结合初始化和插入结点的算法来做,这样代码会更加简洁,但是在视频教程中有提到这个,所以单独实现出来以供参考。
1.2.3 尾插法创建单链表
和头插法不同的地方就是新结点是插入在尾部。
【算法步骤】
- 先初始化一个空链表。
- 创建尾结点指针,一开始尾结点指向头节点。
- 根据要插入的结点数
n
,重复执行n
次(这里为了方便,每个结点的数据域为循环变量i
的值)。 - 生成新结点,将
i
值存入新结点的数据域中。 - 新结点的指针域设置为NULL,表示是最后一个结点。
- 尾结点的指针域指向新结点(就是将新结点接在尾结点之后)。
- 将新结点设置为尾结点,继续下一轮循环。
【代码实现】
// 尾插法创建单链表
Status CreateListTail(LinkList *L, int n)
{*L = (LinkList)malloc(sizeof(LNode)); // 创建头结点if (*L == NULL){return OVERFLOW;}(*L)->next = NULL; // 初始化头结点的next指针为NULL// 创建尾结点指针,一开始尾结点指向头节点。LNode *tailNode;tailNode = *L;LNode *newNode; // 新结点指针for (int i = 1; i <= n; i++){newNode = (LNode *)malloc(sizeof(LNode)); // 创建新结点if (newNode == NULL){return OVERFLOW;}newNode->data.x = i; // 设置新结点的数据newNode->next = NULL; // 将新结点的next指针设置为NULLtailNode->next = newNode; // 将当前尾结点的next指针指向新结点tailNode = newNode; // 更新尾结点为新结点}return OK;
}
【算法分析】
和头插法类似,时间复杂度是 O(n)
。
[!NOTE]
和头插法不太一样的一个点,就是要声明一个临时变量尾结点来记录每次插入的新结点。
1.2.4 获取第i个元素
和顺序表的随机存储方式,需要获取第i个元素,需要从头结点开始进行遍历,直到第 i
个元素。
【算法步骤】
- 通过头结点的
next
可以获取到首元结点,从首元结点开始遍历。 - 定义循环,计数变量
j
从1
开始到i
,每次循环获取当前结点的下一个结点(next
)。 - 如果当前结点(
current
)为NULL
,则可以退出,表明链表并没有第i
个元素。 - 验证当前结点(
current
)是否为NULL
,为空表示链表没有第i
个元素,不为空则可以取到对应的元素(data
)。
【代码实现】
// 获取第 i 个结点
Status GetElem(LinkList *L, int i, ElemType *e)
{if (i < 1) // i 值不合法return ERROR;LNode *current = (*L)->next; // 从头结点的下一个结点开始遍历int j = 1; // 计数器,从1开始while (current != NULL && j < i) // 遍历到第i个结点 并且 当前结点不为空{current = current->next; // 移动到下一个结点j++;}if (current == NULL || j > i)return ERROR;*e = current->data; // 获取第 i 个结点的数据return OK;
}
【算法分析】
该算法的基本操作是比较 j
和 i
并后移指针 current
, while
循环体中的语句频度与位置 i
有关。若 1≤i≤n
则频度为 i - 1
, 一定能取值成功;若 i>n
则频度为 n
, 取值失败。 因此最坏时间复杂度为 O(n)
。
为什么若 i>n
频率为 n
?这里可以具体分析循环体内执行的次数,假设 n = 2
,i = 4
:
j = 1
:while循环条件都满足,循环体代码执行,执行后current
指向第2个结点,j=2
。j = 2
:while循环条件都满足,循环体代码执行,执行后current
指向第3个结点,j=3
。j = 3
:while循环条件不满足(current
为NULL
了),所以退出循环。
总计执行2次。
假设每个位置上元素的取值概率相等, 即:
P i = 1 n P_i=\frac{1}{n} Pi=n1
则:
A S L = 1 n ∑ i = 1 n ( i − 1 ) = n − 1 2 ASL = \frac{1}{n}\sum_{i=1}^{n}(i-1) = \frac{n-1}{2} ASL=n1i=1∑n(i−1)=2n−1
由此可见, 单链表取值算法的平均时间复杂度为 O(n)
。
1.2.5 按值查找
按值查找有两种实现方法:按值查找结点并返回位置 和 按值查找结点并返回结点指针。书籍上只实现了后一种,视频教程两种都实现了。
【算法步骤】
按值查找结点并返回位置:
current
指向头结点的next
,即首元结点,从首元结点开始遍历,并定义计数器i
,即最后返回的位置。- 开始循环,循环条件为
current
不为NULL
。 - 如果循环条件满足,即
current
不为NULL
,则检验元素值是否和要查找的值相等,如果相等则返回i
值,否则current
置为下一个结点,并且将计数器i
加1
,继续下一轮循环。 - 如果
current
为NULL
,则可以退出,表明没有找到,最后返回0
。
按值查找结点并返回结点指针 这个算法思路和上面类似,就是返回的找到的结点指针,而不是位置。
【代码实现】
// 按值查找结点并返回位置
int LocateELem(LinkList *L, ElemType *e)
{LNode *current = (*L)->next; // 从头结点的下一个结点(首元结点)开始遍历int i = 1; // 计数器,从1开始while (current != NULL) // 遍历到链表末尾{if (current->data.x == e->x) // 找到匹配的结点return i;current = current->next; // 移动到下一个结点i++;}return 0; // 没有找到匹配的结点
}// 按值查找结点并返回结点指针
LNode *LocateELem2(LinkList *L, ElemType *e)
{LNode *current = (*L)->next; // 从头结点的下一个结点(首元结点)开始遍历while (current != NULL) // 遍历到链表末尾{if (current->data.x == e->x) // 找到匹配的结点return current;current = current->next; // 移动到下一个结点}return NULL; // 没有找到匹配的结点
}
【算法分析】
该算法的执行时间与待查找的值 e
相关, 其平均时间复杂度分析类似 获取第i
个元素 的算法,也是 O(n)
。
1.2.6 插入节点
将值为 e 的新结点插人到表的第 i
个结点的位置上, 单链表插入结点:
【算法步骤】
- 查找第
i - 1
个结点并由指针current
指向该结点。 - 生成一个新结点
*newNode
。 - 将新结点
*newNode
的数据域置为e
。 - 将新结点
*newNode
的指针域指向第i
个结点。 - 将
current
的指针域指向新结点*newNode
。
【代码实现】
// 插入结点,在 i-1 和 i 之间插入一个结点,新结点的位置就是 i
Status ListInsert(LinkList *L, int i, ElemType e)
{if (i < 1) // i 值不合法return ERROR;LNode *current = *L; // 从头结点开始遍历int j = 0; // 计数器,从0开始,0其实就是表示头结点while (current != NULL && j < i - 1) // 遍历到第i-1个结点 并且 当前结点不为空{current = current->next; // 移动到下一个结点j++;}if (current == NULL || j > i - 1)return ERROR;LNode *newNode = (LNode *)malloc(sizeof(LNode)); // 创建新结点if (newNode == NULL)return OVERFLOW;newNode->data = e; // 设置新结点的数据newNode->next = current->next; // 将新结点的next指针指向当前结点的下一个结点current->next = newNode; // 将当前结点的next指针指向新结点return OK;
}
【算法分析】
单链表的插入操作虽然不需要像顺序表的插入操作那样需要移动元素,但平均时间复杂度仍为 O(n)
。这是因为为了在第 i
个结点之前插入一个新结点,必须首先找到第 i - 1
个结点, 其时间复杂度与 获取第i
个元素算法 相同 ,为 O(n)
。
1.2.7 删除节点
删除单链表的第 i
个结点:
【算法步骤】
- 查找第
i - 1
个结点,由指针current
指向该结点。 - 临时保存待删除结点(第
i - 1
个结点的后继结点就是待删除结点)在temp
中,以备释放。 - 将结点
*current
的指针域指向temp
的直接后继结点。 - 释放结点
temp
的空间。
【代码实现】
// 删除结点,删除第 i 个结点
Status ListDelete(LinkList *L, int i)
{if (i < 1) // i 值不合法return ERROR;LNode *current = *L; // 从头结点开始遍历int j = 0; // 计数器,从0开始,0其实就是表示头结点while (current != NULL && j < i - 1) // 遍历到第i-1个结点 并且 当前结点不为空{current = current->next; // 移动到下一个结点j++;}if (current == NULL || current->next == NULL || j > i - 1)return ERROR;LNode *temp = current->next; // 要删除的结点current->next = temp->next; // 将当前结点的next指针指向要删除结点的下一个结点free(temp); // 释放要删除的结点内存return OK;
}
【算法分析】
类似于插入算法,删除算法时间复杂度亦为 O(n)
主要就是要寻找到第 i - 1
个元素。
1.2.8 求链表的表长
【算法步骤】
- 用指针
current
指向首元结点,初始化长度length为0
。 - 开始循环,循环条件为:
current不为NULL
。 - 如果
current不为NULL
,则current
指向current的后继结点
,并将length加1
。 - 如果
current为NULL
,则退出循环,此时length
就是单链表的长度,直接返回即可。
【代码实现】
// 计算单链表长度
int ListLength(LinkList *L)
{LNode *current = (*L)->next; // 从头结点的下一个结点开始遍历int length = 0; // 计数器,初始值为0while (current != NULL) // 遍历到链表末尾{current = current->next; // 移动到下一个结点length++;}return length;
}
【算法分析】
显然,因为要遍历一遍单链表,所以时间复杂度为 O(n)
。
1.2.9 判断空表
【算法步骤】
- 判断头节点指针域是否为空。
【代码实现】
// 判断单链表是否为空
Boolean ListEmpty(LinkList *L)
{if ((*L)->next == NULL)return TRUE;return FALSE;
}
【算法分析】
算法的时间复杂度为 O(1)
。
1.2.10 清空单链表
链表仍存在,但链表中无元素,成为空链表(头指针和头结点仍然在)。
【算法步骤】
- 用指针
current
指向首元结点,指针temp
用来临时指向后续不为空的结点。 - 开始循环,循环条件为:
current不为NULL
。 - 如果
current不为NULL
,则temp
指向该结点,而后current
指向current的后继结点
,随后释放temp
指向的结点内存。 - 如果
current为NULL
,则退出循环,此时所有结点清理完毕,链表头指针的后继结点设置为NULL
。
【代码实现】
// 清空单链表
Status ClearList(LinkList *L)
{LNode *current = (*L)->next; // 从头结点的下一个结点(首元结点)开始遍历LNode *temp; // 临时指针while (current != NULL) // 遍历到链表末尾{temp = current; // 保存当前结点current = current->next; // 移动到下一个结点free(temp); // 释放当前结点内存}(*L)->next = NULL; // 清空链表,头结点的next指针指向NULLreturn OK;
}
【算法分析】
因为要遍历一遍单链表,所以时间复杂度为 O(n)
。
1.2.11 销毁单链表
和清空单链表不同,除了清空所有结点,头指针和头结点也需要清理掉。
【算法步骤】
- 用指针
current
指向头结点,指针temp
用来临时指向后续不为空的结点。 - 开始循环,循环条件为:
current不为NULL
。 - 如果
current不为NULL
,则temp
指向该结点,而后current
指向current的后继结点
,随后释放temp
指向的结点内存。 - 如果
current为NULL
,则退出循环,此时所有结点(包含头结点)清理完毕,将单链表*L
设置为NULL
。
【代码实现】
// 销毁单链表
Status DestroyList(LinkList *L)
{LNode *current = (*L); // 从头结点开始遍历LNode *temp; // 临时指针while (current != NULL) // 遍历到链表末尾{temp = current; // 保存当前结点current = current->next; // 移动到下一个结点free(temp); // 释放当前结点内存}*L = NULL; // 清空链表,头结点指针置为NULLreturn OK;
}
【算法分析】
因为要遍历一遍单链表,所以时间复杂度为 O(n)
。
另外因为前面有了清空算法,可以在清空单链表的基础上,继续清理掉头结点就可以了。
// 销毁单链表
Status DestroyList(LinkList *L)
{ClearList(L); // 清空链表free(*L); // 释放头结点内存*L = NULL; // 将头结点指针置为NULLreturn OK;
}
相关文章:
数据结构与算法-线性表-单链表(Linked List)
1 线性表 1.2 单链表(Linked List) 顺序表在内存中是连续的进行存储,可以随机获取某个元素,但是在插入和删除元素的时候就非常不方便,需要移动很多相关的元素,链表就可以解决这个问题。 链表就是每个节点…...
Vue3学习(组合式API——生命周期函数基础)
目录 一、Vue3组合式API中的生命周期函数。 (1)各阶段生命周期涉及函数简单介绍。 <1>创建挂载阶段的生命周期函数。 <2>更新阶段的生命周期函数。 <3>卸载阶段的生命周期函数。 <4>错误处理的生命周期函数。 (2&…...
MySQL索引优化面试高频考点解析(附实战场景)
文章目录 当索引失效成为面试官的"送命题"(必看!)高频考点一:索引失效的七大死亡陷阱1. 隐式类型转换(血泪案例!)2. 函数操作毁所有 高频考点二:最左前缀原则的魔鬼细节组…...
三目云台20倍变焦智能监控技术
“三目云台20倍转动”通常指的是一种具备三目变焦功能和20倍光学变焦能力的云台摄像机。以下是对这一概念的详细解释: 一、三目变焦功能 三目云台摄像机通常配备“长、短、广”三组定焦镜头,每组镜头都有其独特的作用: 长焦镜头 ÿ…...
SQL注入---05--跨站注入
1 权限说明 select * from mysql.user; 这里的Y表示我前面的命令权限为root,n表示不支持root权限 导致结果: 如果为root的话,我就可操作这些命令并且可以进行跨数据库攻击,但是如果不是高权限root就无法执行这些操作 2 root权限…...
AAC 协议
1. ADTS(Audio Data Transport Stream)帧结构 在ADTS(Audio Data Transport Stream)帧结构中,“上面扩展28 bit”指的是ADTS固定头(adts_fixed_header())和ADTS可变头(adts_variable_header())各自包含的28位信息。 1.1 ADTS固定头(adts_fixed_header()) AAC 帧…...
HGDB企业版迁移到HGDB安全版
文章目录 环境文档用途详细信息 环境 系统平台:Linux x86-64 Red Hat Enterprise Linux 7 版本:4.5.8,6.0 文档用途 HGDB企业版数据库通过命令备份恢复,迁移到HGDB安全版中。 详细信息 1、环境介绍 1 IP 操作系统 cpux.x.65.10 …...
智慧化系统安全分析报告
智慧化系统的安全背景与现状 一、政策法规背景 (一)全球主要国家/地区政策对比 地区政策名称核心内容实施时间特点中国《生成式人工智能服务管理暂行办法》明确服务提供者责任,强调数据合法、隐私保护,禁止生成违法内容2023年8…...
概率相关问题
问题汇总 1. 贝叶斯定理(贝叶斯公式和全概率公式)2. 概率题2.1 随机发生器的概率为1/2 1. 贝叶斯定理(贝叶斯公式和全概率公式) 定义:在信息和条件有限的情况下,基于过去的数据,通过动态调整的…...
使用 GitDiagram 快速将 GitHub 仓库转换为交互式图表
前言 当面对 GitHub 上文件目录错综复杂的新项目,且你急需快速了解其系统设计或架构流程时,你可能会感到束手无策。今天大姚给大家分享一个开源利器 GitDiagram,它可以轻松将任何复杂的 GitHub 仓库转化为直观、交互式的图表,这对…...
AWS CloudHSM:金融级密钥安全管理实战,如何通过FIPS 140-2认证守护数据生命线?
数据泄露平均成本430万美元,加密漏洞成头号杀手!当《数据安全法》撞上金融科技合规,开发者如何用硬件安全模块(HSM)构建不可破解的密钥堡垒?本文揭秘AWS CloudHSM如何成为支付系统、电子病历、区块链的“数…...
自定义分区器-基础
什么是分区 在 Spark 里,弹性分布式数据集(RDD)是核心的数据抽象,它是不可变的、可分区的、里面的元素并行计算的集合。 在 Spark 中,分区是指将数据集按照一定的规则划分成多个较小的子集,每个子集可以独立…...
<C++> MFC自动关闭对话框(MessageBoxTimeout)
MFC自动关闭对话框(MessageBoxTimeout) 记录一下今天在界面开发中的解决方案。自动关闭对话框有两种方案: 1.使用定时器实现延迟关闭(DeepSeek方案) 提示框显示几秒后自动关闭,可以使用 SetTimer KillT…...
一个基于 Spring Boot 的实现,用于代理百度 AI 的 OCR 接口
一个基于 Spring Boot 的实现,用于代理百度 AI 的 OCR 接口 BaiduAIController.javaBaiduAIConfig.java在 application.yml 或 application.properties 中添加配置:application.yml同时,需要在Spring Boot应用中配置RestTemplate:…...
Python60日基础学习打卡D26
算圆形面积 错误代码 import mathdef calculate_circle_area(r):try:S math.pi * r**2except r<0:print("半径不能为负数")return S 正确代码 import mathdef calculate_circle_area(radius):try:if radius < 0:return 0return math.pi * radius…...
报销单业务笔记
文章目录 业务点业务点-对公对私业务点-多系统标志 特殊业务入参入参报文 出参出参报文中间的逻辑多对多关系 其他应该是整体成功还是可以部分成功这种多对多关多关系有没有优雅的判断方式 报销单是个通用场景,有通用逻辑,在此基础上进行适度定制&#x…...
小红书的评论区营销经验分享
在小红书等社交平台上采用“主账号提问小号解答”的营销策略,其核心作用是通过角色分工和场景化互动,降低用户对广告的抵触心理,同时提升内容的可信度和转化效率。以下是其底层逻辑和具体作用分析: 一、角色分工:制造…...
通义灵码 2.5.4 版【**编程智能体**】初体验
一、通义灵码安装 1.VSCode通义灵码插件安装 VSCode搜索lingma,出现Lingma-Alibaba,点击安装即可,安装完毕如下图所示。 可以看到右侧版本信息如下:alibaba-cloud.tongyi-lingma版本2.5.4上次更新时间2025-05-13, 11:02:16,安装…...
2025ICPC陕西省赛题解一
L. easy 每行选能选的最小的两个,注意处理奇数的情况。 #include <bits/stdc.h> #define x first #define y second #define int long longusing namespace std; typedef unsigned long long ULL ; typedef pair<int,int> PII ; typedef pair<lon…...
java方法的练习题
方法中对自定义类型的传递 package MethodParameter.MethodParameter03;public class MP03 {public static void main(String[] args) {Person p new Person();p.m_Age 100;p.m_Name "John";B b new B();b.test02(p);System.out.println(p.m_Age p.m_Name);} }…...
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle’ on ‘Window’: parameter 1 is not of type ‘Element’ 错误 在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle’ on ‘Window’: par…...
世界模型+大模型+自动驾驶 论文小汇总
最近看了一些论文,懒得一个个写博客了,直接汇总起来 文章目录 大模型VLM-ADVLM-E2EOpenDriveVLAFASIONAD:自适应反馈的类人自动驾驶中快速和慢速思维融合系统快系统慢系统快慢结合 世界模型End-to-End Driving with Online Trajectory Evalu…...
elementUI如何动态增减表单项
设置prop的字段::prop"configs.${i}.platform" <template><el-dialogtitle"编辑配置":close-on-click-modal"false":before-close"beforeClose":visible.sync"visible"v-if"visible"class&q…...
vite运行只能访问localhost解决办法
1、找到package.json的scripts方法 2、然后指定 vite --host即可...
msf安卓远控木马手动捆绑正常apk
生成的安卓木马捆绑到正常的apk的apk中可以增强隐蔽性,有一定的过毒效果 这篇文章来讲解如何通过手动注入来实现apk的捆绑 工具:mt管理器 首先我们要明白原理:木马的payload存在于其dex文件中,将木马的payload注入到正常apk中&…...
【YOLO 系列】基于YOLO的道路坑洞检测识别系统【python源码+Pyqt5界面+数据集+训练代码】
前言 在传统的道路维护和管理中,道路坑洞的检测通常依赖人工巡查,这种方式不仅效率低下,容易出现漏检和误检的情况,而且在复杂的路况和恶劣的天气条件下,检测人员的安全也难以保障。而基于 YOLO 的道路坑洞检测系统&a…...
以项目的方式学QT开发(一)——超详细讲解(120000多字详细讲解,涵盖qt大量知识)逐步更新!
以项目的方式学QT开发 以项目的方式学QT开发 P1 QT介绍 1.1 QT简介 1.2 QT安装 1.2.1 Windows QT安装 1.2.2 QT Creator 使用基本介绍 P2 C基础 2.1 命名空间 2.1.1 命名空间作用 2.1.2 自定义命名空间 2.2 从C语言快速入门 2.2.1 输入输出 2.2.2 基…...
大模型学习
ChatTempate,Completion Only,NEFTune,SFTTrainer 微调技术 (背景:预训练后的大模型只会根据上文,输出下文,但效果不好,要微调帮他更好理解) ChatTemplate 是一种用于定…...
print()函数详解:输出文字、变量与格式化
用ChatGPT做软件测试 “掌握输出,才能掌控信息;理解输出,才能洞悉程序运行的本质。” 当我们敲下人生第一个 Python 代码: print("Hello, World!")也许并未意识到,我们接触的是整个编程世界中最基础、却也最…...
RPC与SOAP的区别
一.RPC(远程过程调用)和SOAP(简单对象访问协议)均用于实现分布式系统中的远程通信,但两者在设计理念、协议实现及应用场景上存在显著差异。 二.对比 1.设计理念 2.协议规范 3.技术特性 4.典型应用场景 5.总结 三.总结…...
2025认证杯数学建模A题思路+代码+模型:小行星轨迹预测
2025认证杯数学建模A题思路代码模型,详细内容见文末名片 近地小行星( Near Earth Asteroids, NEAs )是轨道相对接近地球的小行 星,它的正式定义为椭圆轨道的近日距不大于 1.3 天文单位( AU )的小行星。 …...
Axure中继器高保真交互原型的核心元件
Axure作为一款强大的原型设计工具,中继器无疑是打造高保真交互原型的核心利器。今天,就让我们深入探讨一下Axure中继器的核心地位、操作难点,以及如何借助优秀案例来提升我们的中继器使用技能。 一、核心地位 中继器在Axure中的地位举足轻重…...
Java中Money类的使用及与BigDecimal的对比
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、为什么需要Money类? 在金融和商业计算中,精确的货币处理是至关重要的。虽然Java提供了BigDecimal类来处理高精度计算,…...
第三章:系统命令
1.系统当前时间 date命令: 2.切换用户 su 用户名 sudo 命令:表示使用超级管理员身份执行该命令,如果你当前不是管理员,希望以管理员身份执行某个命令时,使用sudo,需要输入超级管理员的密码: …...
第 83 场周赛:较大分组的位置、隐藏个人信息、连续整数求和、统计子串中的唯一字符
Q1、[简单] 较大分组的位置 1、题目描述 在一个由小写字母构成的字符串 s 中,包含由一些连续的相同字符所构成的分组。 例如,在字符串 s "abbxxxxzyy" 中,就含有 "a", "bb", "xxxx", "z&qu…...
NY244NY249美光闪存颗粒NY252NY256
NY244NY249美光闪存颗粒NY252NY256 美光闪存颗粒技术解析:从架构创新到性能突围 在数据中心轰鸣的服务器阵列中,某款新型存储颗粒正悄然改变着数据吞吐的规则。以NY系列为代表的美光闪存,凭借3D NAND架构与电荷捕获技术的深度融合ÿ…...
MCP本地高效与云端实时:stdio 与 HTTP+SSE 传输机制深度对比
概览 模型上下文协议(MCP)定义了客户端与服务器之间通信的统一标准,所有消息均采用 JSON-RPC 2.0 格式进行封装,并在此基础上支持两种传输机制:stdio(标准输入/输出) 与 HTTPSSE(Se…...
[IP地址科普] 服务器公网IP、私网IP、弹性IP是什么?区别与应用场景详解
更多服务器知识,尽在hostol.com 当我们谈论让一台服务器连接到互联网,或者让服务器上的网站、应用能够被用户访问时,IP 地址是绝对绕不开的核心概念。它就像是每台联网设备的唯一“身份证号码”和“邮政编码”,使得数据包能够在浩…...
【Python】在vscode利用pyinstaller中的.spec文件把py项目打包为.exe实现非py环境下使用的操作步骤
【需要打包的项目结构-简单】 【打包步骤】 【1-将图标以.ico的格式保存在项目中】 可以用.jpg或.png的图像进行重名,注意要和项目在同一个路径下 【2-创建并填写main.sepc文件】 在终端输入以下指令自动创建main.sepc文件,会自动生成标准的文件 pyi…...
MySQL如何查看某个表所占空间大小?(表空间大小查看方法)
文章目录 一、使用SQL查询查看表空间1.1 查询所有表的大小(包括数据和索引)1.2 查询特定数据库的表大小1.3 查询单个表的详细空间信息 二、使用命令行工具查看表空间2.1 使用mysql客户端查询2.2 查看物理文件大小(适用于MyISAM/InnoDB&#x…...
[数据结构]7. 堆-Heap
堆-Heap 1. 介绍2. 堆的实现3. 堆操作InitlilzeDestorySwapPushPopTopEmptySizeAdjustUpAdjustDown 4. HeapSort5. Top-K 1. 介绍 堆(heap) 是一种满足特定条件的完全二叉树。 小顶堆(min heap):任意节点的值 ≤ 其子…...
对心理幸福感含义的探索 | 幸福就是一切吗?
注:机翻,未校。 Happiness Is Everything, or Is It? Explorations on the Meaning of Psychological Well-Being 幸福就是一切吗?对心理幸福感含义的探索 Journal of Personality and Social Psychology 1989, Vol. 57, No. 6,1069-1081 …...
Java应用OOM排查:面试通关“三部曲”心法
开篇点题:OOM——Java应用的“内存爆仓”警报 OOM (OutOfMemoryError) 是啥病?想象一下,你的Java应用程序是一个大仓库,内存就是仓库的存储空间。如果货物(程序运行时创建的对象)越来越多,超出了…...
第28周——InceptionV1实现猴痘识别
前言 🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 一、前期准备 1.检查GPU import torch import torch.nn as nn import torchvision.transforms as transforms import torchvision from torchvision im…...
云上玩转 Qwen3 系列之三:PAI-LangStudio x Hologres构建ChatBI数据分析Agent应用
本文详细介绍了如何使用 LangStudio 和 Qwen3 构建基于 MCP 协议的 Hologres ChatBI 智能 Agent 应用。该应用通过将 Agent、MCP Server 等技术和阿里最新的推理模型 Qwen3 编排在一个应用流中,为大模型提供了 MCPOLAP 的智能数据分析能力,使用自然语言即…...
Android开发-在应用之间共享数据
在Android系统中,应用之间的隔离机制(沙箱机制)保障了系统的安全性与稳定性。然而,在实际开发中,我们经常需要实现跨应用的数据共享,例如: 从一个应用向另一个应用传递用户信息;多个…...
MySQL-数据库分布式XA事务
准备 innodb存储引擎开启支持分布式事务 set global innodb_support_axonMySQL数据库XA事务的SQL语法如下: XA {START| BEGIN} xid {JOIN | RESUME} XA END xid {SUSPEND [ FOR MIGRATE]} XA PREPARE xid XA COMMIT xid [ONE PHASE] XA ROLLBACK xid XA RECOVER 完…...
如何快速入门-衡石科技分析平台
快速指南 创建管理员账号 按照文档安装成功之后,假设安装所在服务器 IP 是<Server IP>,端口是<Server Port>,则可以通过浏览器访问http://<Server IP>:<Server Port>/ 访问衡石分析平台,如果正常&a…...
20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤
20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤 2025/5/15 20:26 缘起:荣品的PRO-RK3566适配视熙科技 的4800W的机芯。 1080p出图预览的时候没图了。 通过105的机芯出图确认 荣品的PRO-RK3566 的硬件正常。 然后要确认 视熙科技 的4800W的机芯是否出…...
OpenCV CUDA模块中矩阵操作-----矩阵最大最小值查找函数
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在OpenCV的CUDA模块中,矩阵最大最小值查找操作用于快速获取矩阵中的全局最小值、最大值及其位置。这些函数对于图像处理任务特别有用…...