前缀表达式求值怎么算?栈与操作数顺序的完整拆解

刷题时碰到“求前缀表达式的值”这种题,第一反应往往是把中缀转后缀那套逻辑反过来套,结果一写就错。前缀表达式也叫波兰式,运算符写在前面,操作数写在后面,比如+ 1 2就是1 + 2。这道题在OJ上分值常是25分,属于数据结构栈章节的经典题,看起来简单,实际上暗藏不少边界条件,尤其是减法、除法操作数的顺序,以及字符串转浮点数时的细节。

如果你正准备应对数据结构考试、刷OJ经典题,或者想彻底搞懂表达式求值背后的栈操作,这篇文章就是给你准备的。我会把这题的完整思路、代码实现、踩坑点、变种题全部拆开讲清楚,不绕弯子,直接给你能落地的解法。

1. 理解前缀表达式:先弄清楚题目在问什么

1.1 前缀表达式到底长什么样

我们平时写的大多是中缀表达式,比如(1 + 2) * 3,运算符夹在两个操作数中间,人能一眼看懂,但机器处理起来要额外考虑优先级和括号。后缀表达式(逆波兰式)把运算符放在最后,比如1 2 + 3 *,计算机用单个栈就能直接算。前缀表达式则是把运算符放在最前面,比如* + 1 2 3,意思就是(1 + 2) * 3。

这道题给的是一个完整的前缀表达式串,运算符只包含+ - * /,操作数可能是整数,也可能是小数,每个 token 之间用空格隔开。题目要求算出整个表达式的值。之所以用前缀而不是中缀,就是为了考察你能不能从右往左维护一个操作数栈,并且正确处理二元运算的顺序。

1.2 前缀表达式的求值规则

前缀表达式的求值逻辑可以一句话说清:从右往左扫描,遇到操作数就入栈,遇到运算符就弹出栈顶两个操作数,运算后把结果再压回栈中。扫描结束后,栈里剩下的唯一一个数就是表达式的值。

这里最大的坑在于弹出后的计算顺序。很多人在中缀转后缀题里习惯了b - a或b / a,因为后缀表达式从左往右扫描,先弹出的其实是右操作数。但前缀表达式是从右往左扫描,先弹出的反而是左操作数。举个例子,表达式- 5 2表示5 - 2,从右往左扫描时,先遇到2入栈,再遇到5入栈,接着遇到运算符-,弹出的第一个数是5,第二个数是2,所以要算a - b而不是b - a。

如果这里搞反,减法、除法全部出错。这是这道25分题最核心的得分点,也是大多数人丢分的原因。

1.3 题目输入输出的隐藏要求

这类题通常输入一行,包含若干个空格分隔的字符串,比如:

* + 2 3 4

输出要求保留两位小数,比如:

20.00

有些版本的操作数可能是浮点数,比如2.5。这就意味着你不能简单地用整数读入,必须用double或float处理。另外,输入的 token 数量可能很多,如果用递归去求,递归深度可能很危险;用栈迭代则完全没有问题。

还有一个容易被忽略的点:前缀表达式的第一个字符一定是运算符,但操作数本身可能是负数,例如- - 5 2 3这种形式,前面的-是减法运算符,后面的-5是负数操作数。因为输入用空格分隔,-5和-是两个不同 token,所以只需正常解析字符串,不会像中缀表达式那样产生歧义。

2. 核心思路拆解:为什么从右往左扫,操作数顺序怎么定

2.1 从右往左扫描的必然性

前缀表达式的定义是“运算符在前,操作数在后”,所以对于一个运算符,它的两个操作数一定在它右边的某个位置。为了能先拿到操作数,必须从右往左处理。这样每扫到一个运算符,它需要的两个操作数已经全部入栈,可以直接弹出。

如果从左往右扫,会遇到什么问题?比如* + 2 3 4,先扫到*,但此时还不知道两个操作数是什么,必须继续往后找,还得处理嵌套结构,这就必须用递归或者额外的栈来保存中间状态,复杂度立刻上去了。所以“从右往左扫描”不是随便定的,它是前缀表达式天然的匹配顺序。

2.2 操作数顺序的推导方法

我们可以从一个小例子推导通用规则。假设前缀表达式是- a b,从右往左扫描过程:

  • 遇到b,入栈;
  • 遇到a,入栈;
  • 遇到-,弹出两个数,假设第一个弹出的是x,第二个是y。

由于栈是后进先出,最后入栈的a会先弹出,所以x = a,y = b。而- a b的本意是“从 a 中减去 b”,即a - b,所以必须写成x - y。

再验证除法,表达式/ a b表示a / b,同样从右往左扫描后,先弹出的x = a,后弹出的y = b,所以计算时写x / y。规律就是:先弹出的是左操作数,后弹出的是右操作数。这个规则一定要亲手推一遍,比死记硬背可靠。

2.3 手算一个综合样例

来一个稍微复杂点的例子:

- + 5 * 2 3 4

这个表达式对应的中缀式是(5 + (2 * 3)) - 4,也就是5 + 6 - 4 = 7。我们按规则走一遍:

  • 从右往左扫描,token 序列是4、3、2、*、5、+、-。
  • 遇到4,入栈。栈:[4]
  • 遇到3,入栈。栈:[4, 3]
  • 遇到2,入栈。栈:[4, 3, 2]
  • 遇到*,弹出2和3,因为先弹的是左操作数,计算2 * 3 = 6,入栈。栈:[4, 6]
  • 遇到5,入栈。栈:[4, 6, 5]
  • 遇到+,弹出5和6,计算5 + 6 = 11,入栈。栈:[4, 11]
  • 遇到-,弹出11和4,计算11 - 4 = 7,入栈。栈:[7]
  • 扫描结束,结果为7。

这里每一步都对应了代码里的一次循环,你能清晰看到“先弹出左操作数”是如何起作用的。注意在第6步遇到+时,栈里从上到下是5和6,先弹出的5正好是+的左操作数,完美匹配。

3. 代码实现:从解析输入到输出结果的完整方案

3.1 数据结构选择:栈与字符串数组

实现方案用两个核心数据结构:

  • vector<string>保存按空格分割后的所有 token;
  • stack<double>保存操作数和中间结果。

为什么不直接用getline(cin, str)然后逐个字符解析?因为操作数可能是多位数、小数、负数,直接用空格分割更稳妥,istringstream就能完成。当然,如果题目输入格式严格,也可以直接在读取流的过程中每读到一个 token 就处理,但那种方式对“从右往左”要求不高时容易乱。我更推荐先把所有 token 存下来,统一从右往左遍历,逻辑更清晰。

3.2 字符串解析与数字转换

每个 token 要么是运算符,要么是数字。判断方法很简单:

if (s == "+" || s == "-" || s == "*" || s == "/") { // 运算符 } else { // 操作数 }

注意这里的-可能是运算符,也可能和数字一起构成负数 token,比如"-5"。用s == "-"判断是要看整个字符串是否只有一个减号,所以-5不会误判为运算符。

将字符串转成浮点数,C++ 里可以直接用stod(s):

double num = stod(s);

stod支持带符号和小数点的字符串,比如"-3.14",正好满足题目要求。不过有些编译器版本对非法输入会抛异常,建议在要求严格的OJ上用strtod替代:

double num = strtod(s.c_str(), nullptr);

这种方式更稳健,不会因为输入格式小问题直接崩溃。

3.3 完整C++实现

下面这段代码可以直接作为参考:

#include <iostream> #include <vector> #include <stack> #include <string> #include <sstream> #include <cstdlib> using namespace std; int main() { string line; getline(cin, line); stringstream ss(line); vector<string> tokens; string token; while (ss >> token) { tokens.push_back(token); } stack<double> st; for (int i = tokens.size() - 1; i >= 0; i--) { string cur = tokens[i]; if (cur == "+" || cur == "-" || cur == "*" || cur == "/") { double a = st.top(); st.pop(); double b = st.top(); st.pop(); double res; if (cur == "+") { res = a + b; } else if (cur == "-") { res = a - b; } else if (cur == "*") { res = a * b; } else { res = a / b; } st.push(res); } else { st.push(strtod(cur.c_str(), nullptr)); } } printf("%.2f\n", st.top()); return 0; }

注意在除法分支里我没有加除零判断。大部分题目数据会保证不出现除零,如果担心,可以额外加一句:

if (fabs(b) < 1e-9) { // 按题目要求处理,也许输出什么标记 }

但不要随便终止程序,因为不同题目对错误的处理方式不同。

3.4 用Python写又会怎样

如果你熟悉 Python,写起来更短小,但要留意字符串转浮点数的细节:

import sys line = sys.stdin.readline().strip() tokens = line.split() stack = [] for token in reversed(tokens): if token in ('+', '-', '*', '/'): a = stack.pop() b = stack.pop() if token == '+': res = a + b elif token == '-': res = a - b elif token == '*': res = a * b else: res = a / b stack.append(res) else: stack.append(float(token)) print(f"{stack[-1]:.2f}")

Python 的float("-3.14")同样能正确处理负数,并且reversed(tokens)避免了索引倒着写的麻烦。这个版本用来理解算法很舒服,但如果在性能要求高的场景下,C++ 会更快。

3.5 输出格式的坑

题目要求保留两位小数,C 的printf("%.2f")会自动四舍五入,Python 的f"{value:.2f}"也是一样。但要注意,有些评测系统的答案要求类似20.00,不能输出20.0。如果直接用cout << value,默认精度不是两位,必须设置fixed << setprecision(2)。

还有一个隐藏点:如果表达式只有一个操作数,比如输入5,那么栈里只有一个数,循环里不会遇到任何运算符,最后直接输出5.00。这种边界情况一开始容易忽略,但代码天然支持,因为从右往左扫描会把5入栈,循环结束时栈顶就是它。

4. 常见问题与排查技巧:为什么样例过了还是WA

4.1 减法和除法的计算顺序写反

最常见的WA原因就是res = b - a或res = b / a。如果你之前写过后缀表达式求值,特别容易顺手把后缀版的顺序搬过来。后缀表达式从左往右扫描,遇到运算符时栈顶是右操作数,弹出来的第一个要放右边;前缀表达式刚好相反,弹出来的第一个要放左边。

我在调试时遇到过一个典型错误:样例输入- 5 2,我的代码先弹出5再弹出2,却写了res = b - a,结果输出-3.00,正确答案是3.00。排查方法很简单,随便拿一个含减法或除法的短表达式,在纸上手算一遍,再对比程序输出,立刻就能定位是计算顺序的问题。

4.2 字符串转数字时把负数当成运算符

输入里可能包含-5这样的负数值。如果你用类似if (cur[0] == '-')判断运算符,会把-5误判为减号。正确做法是判断整个字符串是否等于"-",而不仅仅是看开头字符。

另外使用stoi或stod时,如果输入串里有额外空格或空 token,会导致转换失败。所以用stringstream分割时,默认会跳过连续空格,不用担心多空格问题。但如果你用getline加手动split,就要小心空字符串。

4.3 栈中元素不足:表达式的结构错误

如果输入的前缀表达式不合法,比如+ 1少了一个操作数,那么遇到+时栈里只有一个数,pop两次就会访问空栈,程序直接崩溃。OJ 数据通常保证表达式合法,但你在本地测试时如果自己造数据,容易踩到。

如果想让程序健壮一点,可以在每次弹出前检查栈大小:

if (st.size() < 2) { // 处理非法输入 }

不过在竞赛题中,这种防御性写法反而可能掩盖真正的问题,不如让程序暴露错误,方便调试。

4.4 读取整行时的末尾换行问题

输入可能是一行以换行结尾的字符串。用getline(cin, line)能正确读取,但如果前面用过cin >> n这类操作,缓冲区里会残留换行符,导致getline读到空串。在OJ的单道题中通常不涉及,但如果你把这题封装成函数,或者在多组测试数据里用,就要记得用cin.ignore()吃掉残留换行。

Python 中sys.stdin.readline()会保留末尾换行,用.strip()去掉后,再按空格分割,就不会把换行符带进 token。

4.5 用递归写法的坑

也有人选择直接递归求解,因为前缀表达式天然适合递归:遇到运算符时递归求右操作数,再递归求左操作数。但递归版本有几个问题:

  • 需要实时维护当前扫描位置,代码容易写错。
  • 表达式嵌套很深时,递归栈可能溢出。
  • 每个递归函数内部都要处理字符串转 double,频繁调用stod影响效率。

如果你是为了学习递归思想,可以写一下;为了快速AC,更推荐栈迭代版本。

5. 举一反三:前缀、中缀、后缀的相互转换与进阶应用

5.1 三种表达式求值对比

表格整理一下,方便对照:

表达式类型运算符位置扫描方向出栈顺序时的计算规则
前缀表达式操作数之前从右往左先弹出左操作数,后弹出右操作数
中缀表达式两个操作数之间需要处理优先级和括号一般转后缀或直接双栈
后缀表达式操作数之后从左往右先弹出右操作数,后弹出左操作数

理解这个对比后,你会发现这三种表达式的求值本质上都是“用栈把操作数兜住”,只是扫描方向和出栈后的运算顺序不同。如果你能自己推导一遍,比背口诀有用得多。

5.2 用表达式树解释前缀求值

前缀表达式可以唯一对应一棵表达式树:每个运算符节点有两个子节点,操作数是叶子节点。表达式树的前序遍历就是前缀表达式,后序遍历就是后缀表达式,中序遍历加括号就是中缀表达式。

用树的方式来看求值过程更直观:要求- + 5 * 2 3 4,其实就是先递归算左子树+ 5 * 2 3,再算右子树4,最后相减。而我们用栈从右往左扫描,本质上是在做“后序遍历的逆过程”。编程时用栈模拟了系统递归栈,所以效率更高。

5.3 如果题目改成求后缀表达式的值

后缀表达式的题更常见,比如1 2 + 3 *。求值规则是:从左往右扫描,遇到操作数入栈,遇到运算符弹出两个数,先弹出的放右边,计算b op a,结果入栈。注意这里的先弹放在右边,恰好和前缀相反。很多人在中了前缀的“先弹放左”之后,再做后缀题又容易绕晕。我的建议是:遇到这类题,不用硬记,直接在草稿纸上用一个小例子推一遍,比如1 2 -,后缀是-1.00,你立刻就知道该用a - b还是b - a。

5.4 前缀表达式求值的实际应用

前缀表达式在企业级项目里并不常见,因为人阅读不友好。但在一些编译器和计算器实现中,中间代码表示会选用类似前缀或后缀的形式,方便机器执行。比如很多栈式虚拟机(Java Virtual Machine 的字节码指令里,运算指令就是直接操作操作数栈,概念上非常接近后缀表达式)。

如果你以后要做解释器、表达式引擎,或者只是想在简历上写一个“自制计算器”项目,前缀/后缀求值都是绕不开的基础功。把这道题吃透,等于把栈、字符串解析、数字转换、边界处理这些基本功全部过了一遍,性价比很高。

最后再分享一个实战小技巧

我在实际调试这类栈题时,喜欢在pop之后加一行cout << a << " " << b << " " << cur << endl;,把弹出的两个数和当前运算符打出来,对比手算过程。这样一旦发现计算顺序、入栈顺序出错,肉眼就能看出来。调完再删掉调试输出,绝不把调试代码留在提交版本里。

另外,不要只测样例。我会自己构造几组边界测试:单操作数、负数操作数、浮点数、连续多个运算符、长表达式。把这些全部跑过一遍,再去提交,基本能做到一次AC。这种“先本地穷举边界,再上OJ”的习惯,能帮你省下大量反复提交的时间。

希望这篇思路详解能帮你彻底拿下“求前缀表达式的值”这类题。踩过坑、推过例、敲过代码,以后再遇到表达式求值,就是白给。

相关新闻

企业级用户登录流程设计:从密码安全到会话管理的完整落地指南

企业级用户登录流程设计:从密码安全到会话管理的完整落地指南

先说个我最近接到的真实需求&#xff1a;客户那边要上一套企业内部系统&#xff0c;第一批用户就有三千多人&#xff0c;安全部门给出的要求是"密码不能明文存、登录不能随便试、离职必须立刻失效、异地登录要有提醒"。我打开他们原来的代码一看&#xff0c;登录就是…

2026/10/20 16:32:24 阅读更多 →
ARM嵌入式开发核心机制详解:从寄存器到中断与启动流程

ARM嵌入式开发核心机制详解:从寄存器到中断与启动流程

做嵌入式开发这些年&#xff0c;我一直有个感触&#xff1a; ARM 是绕不开的一座山。不管你是做单片机、Linux驱动&#xff0c;还是物联网终端&#xff0c;最终都会撞见这颗内核。但很多初学者的困惑在于&#xff0c;ARM 不像单片机那样有一个具体的型号&#xff0c;它更像一…

2026/10/20 16:32:24 阅读更多 →
工业AI资料合集高效使用指南:从囤积到知识调用

工业AI资料合集高效使用指南:从囤积到知识调用

1. 从"资料囤积"到"知识调用"&#xff1a;工业AI合集到底该怎么用很多人看到"工业AI资料合集"这类标题&#xff0c;第一反应是收藏、转存、然后让它在硬盘里吃灰。我见过太多同行&#xff0c;网盘里躺着几十个G的PDF&#xff0c;真到项目上要写方…

2026/10/20 16:31:22 阅读更多 →

最新新闻

论文被批“AI味”?千笔·降AIGC助手与PaperRed选型对比

论文被批“AI味”?千笔·降AIGC助手与PaperRed选型对比

1. 先说结论&#xff1a;为什么你的论文总被说“机翻味”和“模板腔”本科生写论文被导师退回重写&#xff0c;理由里出现频率最高的三句话&#xff0c;我闭着眼都能背出来&#xff1a;“这段话像机翻的”“这一段完全没有你自己的判断”“每段都是首先、其次、最后&#xff0c…

2026/10/20 18:48:51 阅读更多 →
基于Q-learning的储能调度效益最大化:Matlab实现与参数调试全解析

基于Q-learning的储能调度效益最大化:Matlab实现与参数调试全解析

能源市场里的“效益最大化”&#xff0c;表面上是低买高卖&#xff0c;但真正上手做就会发现难点从来不是“判断价格高低”&#xff0c;而是“做决策序列”&#xff1a;这一小时贪婪地把储能里所有电卖光&#xff0c;下一小时遇到更高价的时段就只能干瞪眼&#xff1b;低谷时段…

2026/10/20 18:48:51 阅读更多 →
Pi 1.0 原生MCP与Durable:终端编程代理从对话到持久化执行

Pi 1.0 原生MCP与Durable:终端编程代理从对话到持久化执行

如果你也在终端里用过 AI 编程代理&#xff0c;应该能感受到一个尴尬&#xff1a;它能写代码、能跑命令&#xff0c;但一关终端&#xff0c;上下文全丢。这个痛点卡了我很久。所以当我看到 Pi 1.0 正式发布&#xff0c;主打原生 MCP 和 Pi Durable 时&#xff0c;第一反应不是“…

2026/10/20 18:48:51 阅读更多 →
context-mode设计实战:从上下文管理到模式切换的工程化落地

context-mode设计实战:从上下文管理到模式切换的工程化落地

1. 从“context-mode”说起&#xff1a;一个被低估的工程概念第一次看到“context-mode”这个词&#xff0c;很多人会下意识地把它归到某个具体框架的配置项里&#xff0c;觉得无非是个开关或者枚举值。但如果你真正在多个项目里跟“上下文”打过交道&#xff0c;就会发现它其实…

2026/10/20 18:48:51 阅读更多 →
面向对象设计实战:从封装多态到SOLID原则落地

面向对象设计实战:从封装多态到SOLID原则落地

1. 对象思维是一道分水岭我面试过不少人&#xff0c;聊到“面向对象的编程设计”&#xff0c;背概念都能背得滚瓜烂熟&#xff1a;封装、继承、多态&#xff0c;三大特征如数家珍。但一旦落到实际项目里&#xff0c;写出来的代码还是一把梭——几百行的方法&#xff0c;到处是i…

2026/10/20 18:48:51 阅读更多 →
EBS采购订单审批API集成实战:工作流、中间件与存储过程设计

EBS采购订单审批API集成实战:工作流、中间件与存储过程设计

做EBS集成的同学对采购订单审批肯定不陌生。标准功能里&#xff0c;审批人每天登录EBS工作台&#xff0c;从一堆待办通知里逐个点开、审批、写意见&#xff0c;流程虽然完整&#xff0c;但一旦公司上了OA、企业微信、钉钉或者供应商协同平台&#xff0c;业务方就会立刻找你&…

2026/10/20 18:47:50 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →