<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on farmer3-c Blog</title><link>https://farmer3-c.github.io/posts/</link><description>Recent content in Posts on farmer3-c Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 28 Jun 2026 22:00:00 +0800</lastBuildDate><atom:link href="https://farmer3-c.github.io/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>博客框架迁移：从 Jekyll 到 Hugo</title><link>https://farmer3-c.github.io/posts/blog-migration-to-hugo/</link><pubDate>Sun, 28 Jun 2026 22:00:00 +0800</pubDate><guid>https://farmer3-c.github.io/posts/blog-migration-to-hugo/</guid><description>告别 Jekyll，拥抱 Hugo 的简洁与速度</description><content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>之前的博客基于 <strong>Jekyll + Hux Blog 主题</strong>，用了快一年，总觉得不太顺手。Jekyll 是 Ruby 生态，本地构建慢，主题样式偏重（大图背景、多栏布局），对我这种只想简洁写文章的人来说有点臃肿。</p>
<p>于是决定迁移。目标是：</p>
<ul>
<li>🚀 <strong>更快的构建速度</strong></li>
<li>🎨 <strong>极简的页面风格</strong> —— 无背景图、干净利落</li>
<li>🔧 <strong>少折腾</strong> —— 配置简单，开箱即用</li>
<li>📝 <strong>保留所有文章和资源</strong></li>
</ul>
<p>最终选择了 <strong>Hugo + PaperMod 主题</strong>。</p>
<hr>
<h2 id="为什么选-hugo">为什么选 Hugo？</h2>
<table>
	<thead>
			<tr>
					<th>特性</th>
					<th>Jekyll</th>
					<th>Hugo</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>语言</td>
					<td>Ruby</td>
					<td>Go</td>
			</tr>
			<tr>
					<td>构建速度</td>
					<td>~5-10 秒</td>
					<td><strong>~250ms</strong></td>
			</tr>
			<tr>
					<td>安装</td>
					<td>需 Ruby + Gem</td>
					<td><strong>单二进制</strong></td>
			</tr>
			<tr>
					<td>配置</td>
					<td><code>_config.yml</code></td>
					<td><code>hugo.toml</code></td>
			</tr>
			<tr>
					<td>主题生态</td>
					<td>丰富</td>
					<td>丰富</td>
			</tr>
	</tbody>
</table>
<p>Hugo 最大的优势就是<strong>快</strong>——单二进制文件，没有任何依赖，构建 55 篇文章只要 250ms。PaperMod 主题默认就是白色极简风格，没有大图背景，几乎没有需要改动的地方。</p>
<hr>
<h2 id="迁移做了什么">迁移做了什么</h2>
<h3 id="1-文章转换55-篇">1. 文章转换（55 篇）</h3>
<p>原来的 Jekyll 文章格式：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l">post</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Introduction to Linear Programing&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">date</span><span class="p">:</span><span class="w"> </span><span class="ld">2025-09-14 23:54:39 +0800</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">author</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;farmer3-c&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">header-img</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;img/post-bg-2015.jpg&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">mathjax</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>转换为 Hugo 格式：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Introduction to Linear Programing&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">date</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;2025-09-14T23:54:39+08:00&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">author</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;farmer3-c&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">mathjax</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>主要变化：删掉了 <code>layout</code>、<code>header-img</code> 等 Jekyll 特有字段，日期改为 ISO 8601 格式。</p>
<h3 id="2-资源迁移">2. 资源迁移</h3>
<ul>
<li><code>img/</code> → <code>static/img/</code>（路径不变，文章中的图片引用不受影响）</li>
<li><code>pdf/</code> → <code>static/pdf/</code></li>
<li>删除了所有背景大图（<code>*-bg-*.jpg</code>）</li>
</ul>
<h3 id="3-功能集成">3. 功能集成</h3>
<table>
	<thead>
			<tr>
					<th>功能</th>
					<th>实现</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>评论区</td>
					<td>Utterances（基于 GitHub Issues）</td>
			</tr>
			<tr>
					<td>LaTeX</td>
					<td>MathJax 3 支持 <code>$..$</code>、<code>$$..$$</code></td>
			</tr>
			<tr>
					<td>搜索</td>
					<td>PaperMod 内置 Fuse.js</td>
			</tr>
			<tr>
					<td>标签</td>
					<td>自动标签页 <code>/tags/</code></td>
			</tr>
			<tr>
					<td>RSS</td>
					<td>自动生成 <code>/index.xml</code></td>
			</tr>
			<tr>
					<td>字体</td>
					<td>Times New Roman + 宋体</td>
			</tr>
			<tr>
					<td>深色模式</td>
					<td>自动跟随系统</td>
			</tr>
			<tr>
					<td>代码复制</td>
					<td>一键复制代码块</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="新博客使用指南">新博客使用指南</h2>
<h3 id="环境准备">环境准备</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 安装 Hugo（Windows）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 从 https://github.com/gohugoio/hugo/releases 下载 hugo_extended 版本</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 解压后添加到 PATH 即可</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 验证安装</span>
</span></span><span class="line"><span class="cl">hugo version
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="本地预览">本地预览</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 在博客根目录启动服务器</span>
</span></span><span class="line"><span class="cl">hugo server
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浏览器访问 http://localhost:1313/</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 修改文件后自动刷新</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="新建文章">新建文章</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">hugo new content posts/my-new-post.md
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后在 <code>content/posts/my-new-post.md</code> 中编辑：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;文章标题&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">description</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;文章摘要&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">date</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;2026-06-28T23:00:00+08:00&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">author</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;farmer3-c&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">Tag1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">Tag2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">mathjax</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">  </span><span class="c"># 如果用到 LaTeX 则启用</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">draft</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="添加图片">添加图片</h3>
<p>将图片放到 <code>static/img/</code> 目录下，在文章中引用：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">![<span class="nt">描述</span>](<span class="na">/img/your-image.png</span>)
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="添加-pdf">添加 PDF</h3>
<p>将 PDF 放到 <code>static/pdf/</code> 目录下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">[<span class="nt">下载文档</span>](<span class="na">/pdf/filename.pdf</span>)
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="部署">部署</h3>
<p>推送到 GitHub 即可自动构建部署：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git add -A
</span></span><span class="line"><span class="cl">git commit -m <span class="s2">&#34;更新&#34;</span>
</span></span><span class="line"><span class="cl">git push origin main
</span></span></code></pre></td></tr></table>
</div>
</div><p>GitHub Actions 会自动运行 Hugo 构建，将 <code>public/</code> 目录部署到 GitHub Pages。</p>
<hr>
<h2 id="文件结构">文件结构</h2>
<pre tabindex="0"><code>farmer3-c.github.io/
├── hugo.toml              # 主配置文件
├── content/
│   ├── posts/             # 所有文章
│   ├── about/             # 关于页面
│   └── search.md          # 搜索页
├── static/
│   ├── img/               # 图片资源
│   ├── pdf/               # PDF 文件
│   └── CNAME              # 自定义域名
├── layouts/
│   └── partials/
│       ├── comments.html  # Utterances 评论
│       └── extend_head.html  # MathJax 3
├── assets/
│   └── css/extended/
│       └── custom.css     # 自定义样式
└── .github/workflows/
    └── hugo.yml           # 自动部署
</code></pre><hr>
<h2 id="总结">总结</h2>
<p>这次迁移大概花了一晚上的时间，最耗时的是 55 篇文章的格式转换和内部链接检查。迁移之后，博客构建速度从秒级降到了毫秒级，主题干净了很多，写文章的体验也好了不少。</p>
<p>希望这篇记录对想从 Jekyll 迁移到 Hugo 的朋友有帮助 😄</p>
]]></content:encoded></item><item><title>wsl2到wsl1</title><link>https://farmer3-c.github.io/posts/wsl2%E5%88%B0wsl1/</link><pubDate>Thu, 18 Jun 2026 23:39:10 +0000</pubDate><guid>https://farmer3-c.github.io/posts/wsl2%E5%88%B0wsl1/</guid><description>&lt;h1 id="前因"&gt;前因&lt;/h1&gt;
&lt;p&gt;之前想在Windows上使用Linux系统，wsl很方便（为Windows用户提供了Linux环境，不需要装系统什么的）。但是不知道为什么，启动wsl的时间越来越长，从一开始的十几秒到后来的几分钟，实在让我不能忍受。我原来使用的是WSL 2，发现WSL 1 不依赖 Hyper-V 虚拟化，它直接共享 Windows 主机的 IP，启动会很快，所以试试转为 WSL 1。&lt;/p&gt;
&lt;h1 id="过程"&gt;过程&lt;/h1&gt;
&lt;p&gt;在 PowerShell 中逐条执行以下命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 1. 备份当前环境 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;wsl&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-export&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;22.04&lt;/span&gt; &lt;span class="n"&gt;D:&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="nb"&gt;wsl-backup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;tar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 2. 转换为 WSL 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;wsl&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-set-version&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;22.04&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 3. 彻底重启 WSL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;wsl&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-shutdown&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 4. 测试启动速度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Measure-Command&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;wsl&lt;/span&gt; &lt;span class="n"&gt;-d&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;22.04&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-exec&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 5. 测试网络&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;wsl&lt;/span&gt; &lt;span class="n"&gt;-d&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;22.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 进入 WSL 后，运行：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ping&lt;/span&gt; &lt;span class="n"&gt;baidu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;结果：&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="前因">前因</h1>
<p>之前想在Windows上使用Linux系统，wsl很方便（为Windows用户提供了Linux环境，不需要装系统什么的）。但是不知道为什么，启动wsl的时间越来越长，从一开始的十几秒到后来的几分钟，实在让我不能忍受。我原来使用的是WSL 2，发现WSL 1 不依赖 Hyper-V 虚拟化，它直接共享 Windows 主机的 IP，启动会很快，所以试试转为 WSL 1。</p>
<h1 id="过程">过程</h1>
<p>在 PowerShell 中逐条执行以下命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 1. 备份当前环境 </span>
</span></span><span class="line"><span class="cl"><span class="n">wsl</span> <span class="p">-</span><span class="n">-export</span> <span class="n">Ubuntu</span><span class="p">-</span><span class="mf">22.04</span> <span class="n">D:</span><span class="p">\</span><span class="nb">wsl-backup</span><span class="p">.</span><span class="py">tar</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 2. 转换为 WSL 1</span>
</span></span><span class="line"><span class="cl"><span class="n">wsl</span> <span class="p">-</span><span class="n">-set-version</span> <span class="n">Ubuntu</span><span class="p">-</span><span class="mf">22.04</span> <span class="mf">1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 3. 彻底重启 WSL</span>
</span></span><span class="line"><span class="cl"><span class="n">wsl</span> <span class="p">-</span><span class="n">-shutdown</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 4. 测试启动速度</span>
</span></span><span class="line"><span class="cl"><span class="nb">Measure-Command</span> <span class="p">{</span> <span class="n">wsl</span> <span class="n">-d</span> <span class="n">Ubuntu</span><span class="p">-</span><span class="mf">22.04</span> <span class="p">-</span><span class="n">-exec</span> <span class="n">true</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 5. 测试网络</span>
</span></span><span class="line"><span class="cl"><span class="n">wsl</span> <span class="n">-d</span> <span class="n">Ubuntu</span><span class="p">-</span><span class="mf">22.04</span>
</span></span><span class="line"><span class="cl"><span class="c"># 进入 WSL 后，运行：</span>
</span></span><span class="line"><span class="cl"><span class="n">ping</span> <span class="n">baidu</span><span class="p">.</span><span class="py">com</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>结果：</p>
<p><img alt="1" loading="lazy" src="/img/wsl/1.png"></p>
<p>启动很快，网络也没有问题，暂时没发现其他问题。</p>
]]></content:encoded></item><item><title>本地文件目录推送到GitHub上同名空repository</title><link>https://farmer3-c.github.io/posts/%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%E6%8E%A8%E9%80%81%E5%88%B0github%E4%B8%8A%E5%90%8C%E5%90%8D%E7%A9%BArepository/</link><pubDate>Fri, 12 Jun 2026 10:37:24 +0000</pubDate><guid>https://farmer3-c.github.io/posts/%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%E6%8E%A8%E9%80%81%E5%88%B0github%E4%B8%8A%E5%90%8C%E5%90%8D%E7%A9%BArepository/</guid><description>&lt;p&gt;在 GitHub 建&lt;strong&gt;同名、完全空的仓库（不要勾选 README/.gitignore）&lt;/strong&gt;，本地目录用 &lt;code&gt;git init&lt;/code&gt;→&lt;code&gt;git add .&lt;/code&gt;→&lt;code&gt;git commit&lt;/code&gt;→&lt;code&gt;git remote add origin&lt;/code&gt;→&lt;code&gt;git push -u origin main&lt;/code&gt; 即可一次性推上去。&lt;/p&gt;
&lt;p&gt;下面是完整操作（Windows/Mac/Linux 通用）：&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="一准备工作"&gt;一、准备工作&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;安装 Git：&lt;/p&gt;
&lt;p&gt;终端输入：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;能显示版本就说明已安装；没有就先装 Git。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在 GitHub 建&lt;strong&gt;同名空仓库&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;右上角点 &lt;code&gt;+&lt;/code&gt; → New repository&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Repository name：和你本地文件夹&lt;strong&gt;同名&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;不要勾选&lt;/strong&gt;：Add a README file、.gitignore、License&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点 Create repository&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;复制仓库地址（HTTPS 或 SSH），例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://github.com/你的用户名/仓库名.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id="二本地操作"&gt;二、本地操作&lt;/h3&gt;
&lt;p&gt;打开终端（Git Bash / Terminal / PowerShell），&lt;strong&gt;进入你要上传的本地目录根目录&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/你的本地文件夹 &lt;span class="c1"&gt;# Windows 示例：cd D:\my-project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="1-初始化为-git-仓库"&gt;1. 初始化为 Git 仓库&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="2-添加所有文件到暂存区"&gt;2. 添加所有文件到暂存区&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;（想忽略某些文件，新建 &lt;code&gt;.gitignore&lt;/code&gt; 写规则，比如 &lt;code&gt;node_modules/&lt;/code&gt;、&lt;code&gt;*.log&lt;/code&gt;）&lt;/p&gt;</description><content:encoded><![CDATA[<p>在 GitHub 建<strong>同名、完全空的仓库（不要勾选 README/.gitignore）</strong>，本地目录用 <code>git init</code>→<code>git add .</code>→<code>git commit</code>→<code>git remote add origin</code>→<code>git push -u origin main</code> 即可一次性推上去。</p>
<p>下面是完整操作（Windows/Mac/Linux 通用）：</p>
<hr>
<h3 id="一准备工作">一、准备工作</h3>
<ol>
<li>
<p>安装 Git：</p>
<p>终端输入：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git --version
</span></span></code></pre></td></tr></table>
</div>
</div><p>能显示版本就说明已安装；没有就先装 Git。</p>
</li>
<li>
<p>在 GitHub 建<strong>同名空仓库</strong></p>
<ul>
<li>
<p>右上角点 <code>+</code> → New repository</p>
</li>
<li>
<p>Repository name：和你本地文件夹<strong>同名</strong></p>
</li>
<li>
<p><strong>不要勾选</strong>：Add a README file、.gitignore、License</p>
</li>
<li>
<p>点 Create repository</p>
</li>
<li>
<p>复制仓库地址（HTTPS 或 SSH），例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line"><span class="cl">https://github.com/你的用户名/仓库名.git
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
</li>
</ol>
<hr>
<h3 id="二本地操作">二、本地操作</h3>
<p>打开终端（Git Bash / Terminal / PowerShell），<strong>进入你要上传的本地目录根目录</strong>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /path/to/你的本地文件夹   <span class="c1"># Windows 示例：cd D:\my-project</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="1-初始化为-git-仓库">1. 初始化为 Git 仓库</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git init
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="2-添加所有文件到暂存区">2. 添加所有文件到暂存区</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git add .
</span></span></code></pre></td></tr></table>
</div>
</div><p>（想忽略某些文件，新建 <code>.gitignore</code> 写规则，比如 <code>node_modules/</code>、<code>*.log</code>）</p>
<h4 id="3-提交到本地仓库">3. 提交到本地仓库</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git commit -m <span class="s2">&#34;Initial commit: 上传本地全部文件&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="4-关联远程-github-仓库">4. 关联远程 GitHub 仓库</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git remote add origin https://github.com/你的用户名/仓库名.git
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果提示 <code>remote origin already exists</code>，先删旧关联：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git remote remove origin
</span></span></code></pre></td></tr></table>
</div>
</div><p>再重新执行上面命令。</p>
<h4 id="5-重命名分支为-main和-github-默认一致">5. 重命名分支为 main（和 GitHub 默认一致）</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git branch -M main
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="6-推送到-github">6. 推送到 GitHub</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git push -u origin main
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><code>-u</code>：以后直接 <code>git push</code> 即可，不用每次写 <code>origin main</code></li>
<li>输入 GitHub 账号密码（或用个人访问令牌），完成。</li>
</ul>
<hr>
<h3 id="三常见报错解决">三、常见报错解决</h3>
<ol>
<li>
<p><strong>fatal: remote origin already exists</strong></p>
<p>→ <code>git remote remove origin</code> 后重新关联。</p>
</li>
<li>
<p><strong>error: src refspec main does not match any</strong></p>
<p>→ 没 <code>add</code> 或 <code>commit</code> 成功，重新执行：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git add .
</span></span><span class="line"><span class="cl">git commit -m <span class="s2">&#34;Initial commit&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>合并冲突（远程有 README 等）</strong></p>
<p>→ 必须保证远程是空仓库；如果已有内容，用：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git pull origin main --allow-unrelated-histories
</span></span></code></pre></td></tr></table>
</div>
</div><p>解决冲突后再 push。</p>
</li>
</ol>
]]></content:encoded></item><item><title>编译实践Lv1.main函数</title><link>https://farmer3-c.github.io/posts/%E7%BC%96%E8%AF%91%E5%AE%9E%E8%B7%B5lv1main%E5%87%BD%E6%95%B0/</link><pubDate>Wed, 10 Jun 2026 21:55:22 +0000</pubDate><guid>https://farmer3-c.github.io/posts/%E7%BC%96%E8%AF%91%E5%AE%9E%E8%B7%B5lv1main%E5%87%BD%E6%95%B0/</guid><description>&lt;h1 id="目的"&gt;目的&lt;/h1&gt;
&lt;p&gt;实现一个能处理 main 函数和 return 语句的编译器.编译器可以将如下的 SysY 程序:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;int main() {
// 注释也应该被删掉哦
return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;编译为对应的 Koopa IR:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;fun @main(): i32 {
%entry:
ret 0
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="实现"&gt;实现&lt;/h1&gt;
&lt;h2 id="lv12-词法语法分析初见"&gt;Lv1.2. 词法/语法分析初见&lt;/h2&gt;
&lt;p&gt;我使用项目提供的c++模板，直接执行：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;make
build/compiler -koopa hello.c -o hello.koopa
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;输出：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;int main() { return 0; }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是因为默认的模板使用string存放ast，所以输出的ast也是string形式：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;CompUnit
: FuncDef {
ast = unique_ptr&amp;lt;string&amp;gt;($1);
}
;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="lv13-解析-main-函数"&gt;Lv1.3. 解析 main 函数&lt;/h2&gt;
&lt;p&gt;这里设计一个ast用于输出程序的语法结构，教程写的已经很详细了：写一个头文件来定义AST,对于头文件重复声明的问题，加上&lt;code&gt;#pragma once&lt;/code&gt;就可以解决。&lt;/p&gt;
&lt;p&gt;我是这样定义基类和子类进行构造的：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// 所有 AST 的基类
class BaseAST {
public:
virtual ~BaseAST() = default;
virtual void Dump() const = 0;
};
// CompUnit 是 BaseAST
class CompUnitAST : public BaseAST {
public:
// 用智能指针管理对象
std::unique_ptr&amp;lt;BaseAST&amp;gt; func_def;
void Dump() const override {
std::cout &amp;lt;&amp;lt; &amp;#34;CompUnitAST { &amp;#34;;
func_def-&amp;gt;Dump();
std::cout &amp;lt;&amp;lt; &amp;#34; }&amp;#34;;
}
};
……
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;同时，修改参数类型的相关声明：比如&lt;code&gt;%parse-param { std::unique_ptr&amp;lt;string&amp;gt; &amp;amp;ast } &lt;/code&gt;改为&lt;code&gt;%parse-param { std::unique_ptr&amp;lt;BaseAST&amp;gt; &amp;amp;ast } &lt;/code&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="目的">目的</h1>
<p>实现一个能处理 main 函数和 return 语句的编译器.编译器可以将如下的 SysY 程序:</p>
<pre tabindex="0"><code>int main() {
  // 注释也应该被删掉哦
  return 0;
}
</code></pre><p>编译为对应的 Koopa IR:</p>
<pre tabindex="0"><code>fun @main(): i32 {
%entry:
  ret 0
}
</code></pre><h1 id="实现">实现</h1>
<h2 id="lv12-词法语法分析初见">Lv1.2. 词法/语法分析初见</h2>
<p>我使用项目提供的c++模板，直接执行：</p>
<pre tabindex="0"><code>make
build/compiler -koopa hello.c -o hello.koopa
</code></pre><p>输出：</p>
<pre tabindex="0"><code>int main() { return 0; }
</code></pre><p>这是因为默认的模板使用string存放ast，所以输出的ast也是string形式：</p>
<pre tabindex="0"><code>CompUnit
  : FuncDef {
    ast = unique_ptr&lt;string&gt;($1);
  }
  ;
</code></pre><h2 id="lv13-解析-main-函数">Lv1.3. 解析 main 函数</h2>
<p>这里设计一个ast用于输出程序的语法结构，教程写的已经很详细了：写一个头文件来定义AST,对于头文件重复声明的问题，加上<code>#pragma once</code>就可以解决。</p>
<p>我是这样定义基类和子类进行构造的：</p>
<pre tabindex="0"><code>// 所有 AST 的基类
class BaseAST {
 public:
  virtual ~BaseAST() = default;
  virtual void Dump() const = 0;
};

// CompUnit 是 BaseAST
class CompUnitAST : public BaseAST {
 public:
  // 用智能指针管理对象
  std::unique_ptr&lt;BaseAST&gt; func_def;

    void Dump() const override {
    std::cout &lt;&lt; &#34;CompUnitAST { &#34;;
    func_def-&gt;Dump();
    std::cout &lt;&lt; &#34; }&#34;;
  }
};
……
</code></pre><p>同时，修改参数类型的相关声明：比如<code>%parse-param { std::unique_ptr&lt;string&gt; &amp;ast } </code>改为<code>%parse-param { std::unique_ptr&lt;BaseAST&gt; &amp;ast } </code></p>
<p>make之后就会输出<code>CompUnitAST { FuncDefAST { FuncTypeAST { int }, main, BlockAST { StmtAST { 0 } } } } </code>。</p>
<h2 id="lv14-ir-生成">Lv1.4. IR 生成</h2>
<p>我采用定义 AST 一样定义表示 Koopa IR 的数据结构, 然后遍历 AST 输出这种结构, 再遍历这种结构输出字符串。</p>
<p>类似的，写一个KoopaIR头文件，定义它的结构：</p>
<pre tabindex="0"><code>// Value 是所有指令和常量的基类
class Value {
 public:
  virtual ~Value() = default;
  virtual void Dump() const = 0;
};

// 整数常量
class Integer : public Value {
 public:
  int value;
  
  Integer(int v) : value(v) {}
  
  void Dump() const override {
    std::cout &lt;&lt; value;
  }
};
</code></pre><p>接着完成<code>GenerateIR</code>的工作，完成遍历 AST 生成 IR，由于只需要识别main函数就可以了，复杂一些的递归之类的暂时不需要写。</p>
<pre tabindex="0"><code>main.cpp
  │
  ├─ yyparse(ast)          // 调用 Bison/Flex 解析源码 → 得到 AST
  │
  ├─ GenerateIR(*ast)      // ← 遍历 AST，生成 Koopa IR (Program)
  │     └─ IRGenerator.cpp
  │          ├─ dynamic_cast&lt;CompUnitAST*&gt; 取出 func_def
  │          ├─ dynamic_cast&lt;FuncDefAST*&gt;  取出 ident + block
  │          ├─ dynamic_cast&lt;BlockAST*&gt;    取出 stmt
  │          ├─ dynamic_cast&lt;StmtAST*&gt;     取出 num
  │          └─ 构建 Return(Integer(num)) → BasicBlock → Function → Program
  │
  └─ program-&gt;Dump()       // 以文本格式输出 Koopa IR
</code></pre><h2 id="lv15-测试">Lv1.5. 测试</h2>
<p>有一个小问题，模板给出的sysy.l没有给出注释块的定义，需要我们自己加上<code>BlockComment  &quot;/*&quot;(.|\n)*?&quot;*/&quot;</code>,否则测试的时候会有一个测试点不过。</p>
<p>测试结果：
<img alt="1" loading="lazy" src="/img/pku-compiler/image.png"></p>
]]></content:encoded></item><item><title>Windows磁盘合并</title><link>https://farmer3-c.github.io/posts/windows%E7%A3%81%E7%9B%98%E5%90%88%E5%B9%B6/</link><pubDate>Tue, 09 Jun 2026 22:13:58 +0000</pubDate><guid>https://farmer3-c.github.io/posts/windows%E7%A3%81%E7%9B%98%E5%90%88%E5%B9%B6/</guid><description>&lt;h1 id="前因"&gt;前因&lt;/h1&gt;
&lt;p&gt;C盘越来越满，D盘和E盘还有许多空间，磁盘合并理所当然的成为了一个缓解C盘压力的解决方案。&lt;/p&gt;
&lt;h2 id="想法"&gt;想法&lt;/h2&gt;
&lt;p&gt;我的想法是将D盘的文件都挪到E盘，然后腾出D盘的空间来分配到C盘和E盘。考虑到我习惯使用D盘存放应用，所以我打算之后将E盘的盘符改成D。&lt;/p&gt;
&lt;p&gt;处于方便和迅捷考虑，我使用&lt;code&gt;robocopy &amp;quot;D:\&amp;quot; &amp;quot;E:\D盘备份&amp;quot; /E /J /MT:8 /R:3 /W:1&lt;/code&gt;复制D盘文件到E盘的一个文件夹，效果还不错。于是在完成修改后我同样使用&lt;code&gt;robocopy D:\D盘备份 D:\ /E /MIR&lt;/code&gt;来将配置带到新的D盘，殊不知这会带来怎么样的灾难😭&lt;/p&gt;
&lt;h1 id="过程"&gt;过程&lt;/h1&gt;
&lt;p&gt;我使用&lt;a href="https://www.minitool.com/partition-manager/partition-wizard-home.html"&gt;MiniTool Partition Wizard&lt;/a&gt;进行磁盘操作。由于原来D盘删除后的内存与C盘之间存在恢复分区，C盘只能合并它右侧的空间，所以要move恢复分区，这就为C盘扩容了。&lt;/p&gt;
&lt;p&gt;然后是将剩余空间合并到E盘，结果因为BitLocker而合并不了，解密之后顺利合并。&lt;/p&gt;
&lt;p&gt;最后，灾难性的一幕发生了，使用&lt;code&gt;robocopy D:\D盘备份 D:\ /E /MIR&lt;/code&gt;后，修改后D盘空了。&lt;/p&gt;
&lt;p&gt;可能的原因是：带 /MIR 的 robocopy 命令在执行时，先清空了 D 盘根目录，再尝试复制备份文件，但中途因为 $RECYCLE.BIN 报错中断，导致备份文件也被系统误删了。&lt;/p&gt;
&lt;p&gt;数据恢复工具需要的时间太长了，被删除的数据也没有很重要的，我就先配置了日常要用的工具草草了结了，剩下的日后再说。&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="前因">前因</h1>
<p>C盘越来越满，D盘和E盘还有许多空间，磁盘合并理所当然的成为了一个缓解C盘压力的解决方案。</p>
<h2 id="想法">想法</h2>
<p>我的想法是将D盘的文件都挪到E盘，然后腾出D盘的空间来分配到C盘和E盘。考虑到我习惯使用D盘存放应用，所以我打算之后将E盘的盘符改成D。</p>
<p>处于方便和迅捷考虑，我使用<code>robocopy &quot;D:\&quot; &quot;E:\D盘备份&quot; /E /J /MT:8 /R:3 /W:1</code>复制D盘文件到E盘的一个文件夹，效果还不错。于是在完成修改后我同样使用<code>robocopy D:\D盘备份 D:\ /E /MIR</code>来将配置带到新的D盘，殊不知这会带来怎么样的灾难😭</p>
<h1 id="过程">过程</h1>
<p>我使用<a href="https://www.minitool.com/partition-manager/partition-wizard-home.html">MiniTool Partition Wizard</a>进行磁盘操作。由于原来D盘删除后的内存与C盘之间存在恢复分区，C盘只能合并它右侧的空间，所以要move恢复分区，这就为C盘扩容了。</p>
<p>然后是将剩余空间合并到E盘，结果因为BitLocker而合并不了，解密之后顺利合并。</p>
<p>最后，灾难性的一幕发生了，使用<code>robocopy D:\D盘备份 D:\ /E /MIR</code>后，修改后D盘空了。</p>
<p>可能的原因是：带 /MIR 的 robocopy 命令在执行时，先清空了 D 盘根目录，再尝试复制备份文件，但中途因为 $RECYCLE.BIN 报错中断，导致备份文件也被系统误删了。</p>
<p>数据恢复工具需要的时间太长了，被删除的数据也没有很重要的，我就先配置了日常要用的工具草草了结了，剩下的日后再说。</p>
]]></content:encoded></item><item><title>Flex 和 Bison 教程</title><link>https://farmer3-c.github.io/posts/flex-%E5%92%8C-bison-%E6%95%99%E7%A8%8B/</link><pubDate>Sat, 23 May 2026 16:26:30 +0000</pubDate><guid>https://farmer3-c.github.io/posts/flex-%E5%92%8C-bison-%E6%95%99%E7%A8%8B/</guid><description>&lt;blockquote&gt;
&lt;p&gt;说明：本篇内容译自 Santa Clara University COEN 259 编译原理课程讲义，用于学习 Flex 和 Bison 编译器工具。
本篇内容为个人学习，不构成任何商业用途。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="flex"&gt;Flex&lt;/h2&gt;
&lt;p&gt;Flex 是一个用于词法分析的扫描器生成工具，它基于有限状态机 (FSM)。输入是一组正则表达式，输出是根据输入规则实现扫描器的代码。&lt;/p&gt;
&lt;p&gt;为了实现计算器的一个扫描器，我们可以将文件 “cal1.l” 编写如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/* this is only for scanner, not link with parser yet */
%{
int lineNum = 0;
%}
%%
&amp;#34;(&amp;#34; { printf(&amp;#34;(\n&amp;#34;); }
&amp;#34;)&amp;#34; { printf(&amp;#34;)\n&amp;#34;); }
&amp;#34;+&amp;#34; { printf(&amp;#34;+\n&amp;#34;); }
&amp;#34;*&amp;#34; { printf(&amp;#34;*\n&amp;#34;); }
\n { lineNum++; }
[ \t]+ { }
[0-9]+ { printf(&amp;#34;%s\n&amp;#34;, yytext); }
%%
int yywrap() {
return 1;
}
int main () {
yylex();
return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这是用于构建扫描器的 Makefile：&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>
<p>说明：本篇内容译自 Santa Clara University COEN 259 编译原理课程讲义，用于学习 Flex 和 Bison 编译器工具。
本篇内容为个人学习，不构成任何商业用途。</p>
</blockquote>
<h2 id="flex">Flex</h2>
<p>Flex 是一个用于词法分析的扫描器生成工具，它基于有限状态机 (FSM)。输入是一组正则表达式，输出是根据输入规则实现扫描器的代码。</p>
<p>为了实现计算器的一个扫描器，我们可以将文件 “cal1.l” 编写如下：</p>
<pre tabindex="0"><code>/* this is only for scanner, not link with parser yet */ 
%{ 
int lineNum = 0; 
%} 
 
%% 
 
&#34;(&#34; { printf(&#34;(\n&#34;); } 
&#34;)&#34; { printf(&#34;)\n&#34;); } 
&#34;+&#34; { printf(&#34;+\n&#34;); } 
&#34;*&#34; { printf(&#34;*\n&#34;); } 
\n { lineNum++; } 
[ \t]+ { } 
[0-9]+ { printf(&#34;%s\n&#34;, yytext); } 
 
%% 
 
int yywrap() { 
 return 1; 
} 
 
int main () { 
 yylex(); 
 return 0; 
} 
</code></pre><p>这是用于构建扫描器的 Makefile：</p>
<pre tabindex="0"><code>p1: lex.yy.o 
 gcc -g -o p1 lex.yy.o 
 
lex.yy.o: cal1.l 
 flex cal1.l; gcc -g -c lex.yy.c 
 
clean: 
 rm -f p1 *.o lex.yy.c
</code></pre><p><strong>注意</strong>：对于更复杂的 flex 输入文件，你可能会收到类似的错误信息</p>
<pre tabindex="0"><code>parse tree too big, try %a num (or %e num)&#34; 
</code></pre><p>然后你需要定义 <code>%e &lt;num&gt;</code>。你应该把它放在宏和 <code>%start</code> 符号之间。其他选项有 <code>%a、%o、%n、%p</code> 等。</p>
<h2 id="bison">Bison</h2>
<p>Bison 是一个用于语法分析的 LALR(1) 解析器生成工具，它基于下推自动机 (PDA)。输入是一组上下文无关文法 (CFG) 规则，输出是根据输入规则实现解析器的代码。</p>
<p>要实现计算器的一个解析器，我们可以按如下方式编写文件“cal.y”:</p>
<pre tabindex="0"><code>%{ 
#include &lt;stdio.h&gt; 
#include &lt;ctype.h&gt; 
int lineNum = 1; 
void yyerror(char *ps, ...) {  /* need this to avoid 
link problem */ 
 printf(&#34;%s\n&#34;, ps); 
} 
%} 
 
%union { 
 int d; 
} 
// need to choose token type from union above 
%token &lt;d&gt; NUMBER 
%token &#39;(&#39; &#39;)&#39; 
%left &#39;+&#39; 
%left &#39;*&#39; 
%type &lt;d&gt; exp factor term 
 
%start cal 
 
%% 
 
cal 
  : exp 
 { printf(&#34;The result is %d\n&#34;, $1); } 
  ; 
 
exp 
  : exp &#39;+&#39; factor 
 { $$ = $1 + $3; } 
  | factor 
 { $$ = $1; } 
  ; 
 
factor
 : factor &#39;*&#39; term 
 { $$ = $1 * $3; } 
  | term 
 { $$ = $1; } 
  ; 
 
term 
  : NUMBER 
 { $$ = $1; } 
  | &#39;(&#39; exp &#39;)&#39; 
 { $$ = $2; } 
  ; 
 
%% 
 
int main() { 
 yyparse(); 
 return 0; 
}
</code></pre><p>为了整合扫描器和解析器，我们需要修改扫描器输入文件“cal1.l”，并将其保存为“cal.l”，如下所示：</p>
<pre tabindex="0"><code>%{ 
#include &lt;stdlib.h&gt; /* for atoi call */ 
#define DEBUG  /* for debuging: print tokens and 
their line numbers */ 
#define NUMBER 258 /* copy this from cal.tab.c */ 
typedef union {  /* copy this from cal.tab.c */ 
 int d; 
} YYSTYPE; 
YYSTYPE yylval; /* for passing value to parser */ 
extern int lineNum; /* line number from cal.tab.c */ 
%} 
 
%% 
 
[ \t]+ {} 
[\n] { lineNum++; } 
&#34;(&#34; { 
#ifdef DEBUG 
  printf(&#34;token &#39;(&#39; at line %d\n&#34;, lineNum); 
#endif 
  return &#39;(&#39;; 
 } 
&#34;)&#34; { 
#ifdef DEBUG 
  printf(&#34;token &#39;)&#39; at line %d\n&#34;, lineNum); 
#endif 
  return &#39;)&#39;; 
 } 
&#34;+&#34; {
#ifdef DEBUG 
  printf(&#34;token &#39;+&#39; at line %d\n&#34;, lineNum); 
#endif 
  return &#39;+&#39;; 
 } 
&#34;*&#34; { 
#ifdef DEBUG 
  printf(&#34;token &#39;*&#39; at line %d\n&#34;, lineNum); 
#endif 
  return &#39;*&#39;; 
 } 
[0-9]+ { 
#ifdef DEBUG 
 printf(&#34;token %s at line %d\n&#34;, yytext, lineNum); 
#endif 
 yylval.d = atoi(yytext); 
 return NUMBER; 
} 
 
%% 
 
int yywrap() {  /* need this to avoid link problem */ 
 return 1; 
}
</code></pre><p>这是用于构建扫描器和解析器的 Makefile：</p>
<pre tabindex="0"><code>p2: lex.yy.o cal.tab.o 
 gcc -o p2 lex.yy.o cal.tab.o 
 
lex.yy.o: cal.l 
 flex cal.l; gcc -c lex.yy.c 
 
cal.tab.o: cal.y 
 bison -d cal.y; gcc -c cal.tab.c 
 
clean: 
 rm -f p2 cal.output *.o cal.tab.c lex.yy.c 
</code></pre><p>有一些调试 Bison 的技巧。</p>
<ol>
<li>使用 -v 选项运行 Bison，然后会生成一个名为 cal.output 的文件。它包含所有的冲突和/或永远不会被归约的规则，以及 Bison 生成的所有状态。</li>
<li>获取 Bison 的调试信息：首先，在编译 cal.tab.c 时添加 -DYYDEBUG；其次，设置环境变量 YYDEBUG=1。然后它会打印大量的调试信息，例如如何进行移入或归约。</li>
</ol>
<hr>
<p><a href="https://www.cse.scu.edu/~m1wang/compiler/TutorialFlexBison.pdf">原文</a></p>
]]></content:encoded></item><item><title>博客优化问题与解决方案总结</title><link>https://farmer3-c.github.io/posts/blog-problems-and-solutions/</link><pubDate>Sat, 16 May 2026 01:00:00 +0800</pubDate><guid>https://farmer3-c.github.io/posts/blog-problems-and-solutions/</guid><description>Jekyll 博客遇到的问题及修复方法</description><content:encoded><![CDATA[<h1 id="博客优化问题与解决方案总结">博客优化问题与解决方案总结</h1>
<p>最近对博客进行了多次优化，遇到了各种问题，现在总结一下遇到的问题及解决方案，供大家参考。</p>
<h2 id="1-service-worker-自动刷新问题">1. Service Worker 自动刷新问题</h2>
<h3 id="问题描述">问题描述</h3>
<p>博客添加了 Service Worker 后，每次检测到更新都会显示 &ldquo;Content updated. REFRESH&rdquo; 按钮，需要手动点击刷新。</p>
<h3 id="解决方案">解决方案</h3>
<p>修改 <code>js/sw-registration.js</code>，移除手动刷新提示，直接使用 <code>location.reload()</code>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">if</span><span class="p">(</span><span class="nx">data</span><span class="p">.</span><span class="nx">command</span> <span class="o">==</span> <span class="s2">&#34;UPDATE_FOUND&#34;</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;UPDATE_FOUND_BY_SW&#34;</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// 自动刷新页面，无需手动点击
</span></span></span><span class="line"><span class="cl">  <span class="nx">location</span><span class="p">.</span><span class="nx">reload</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="后续问题">后续问题</h3>
<p>启用自动刷新后，网站出现了<strong>无限刷新循环</strong>的问题，用户体验极差。</p>
<h3 id="最终解决方案">最终解决方案</h3>
<p>移除 Service Worker 的自动刷新机制，改用 Stale-While-Revalidate 缓存策略：</p>
<ul>
<li>优先显示缓存内容</li>
<li>后台更新缓存</li>
<li>用户下次访问时自然看到新内容</li>
</ul>
<hr>
<h2 id="2-导航栏显示文章标题问题">2. 导航栏显示文章标题问题</h2>
<h3 id="问题描述-1">问题描述</h3>
<p>导航栏突然显示了文章标题 &ldquo;编译实践Lv1. main 函数&rdquo;，而不是正常的页面链接。</p>
<h3 id="根本原因">根本原因</h3>
<p>之前误将一篇博客文章放到了 <code>css/</code> 文件夹，Jekyll 将其当作页面处理，导致导航栏循环显示所有有 title 的页面。</p>
<h3 id="解决方案-1">解决方案</h3>
<p><strong>彻底解决方案：</strong> 硬编码导航栏，只显示固定页面。</p>
<p>修改 <code>_includes/nav.html</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;nav navbar-nav navbar-right&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/&#34;</span><span class="p">&gt;</span>Home<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/about/&#34;</span><span class="p">&gt;</span>About<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/archive/&#34;</span><span class="p">&gt;</span>Archive<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;search-icon&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;javascript:void(0)&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">i</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;fa fa-search&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">i</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>同时从 git 历史中彻底移除误放的文章。</p>
<hr>
<h2 id="3-about-和-archive-页面-404-问题">3. About 和 Archive 页面 404 问题</h2>
<h3 id="问题描述-2">问题描述</h3>
<p>点击导航栏的 About 和 Archive，跳转到 <code>/about.html</code> 和 <code>/archive.html</code>，显示 404 错误。</p>
<h3 id="原因">原因</h3>
<p>博客使用了 <code>permalink: pretty</code> 配置，正确的 URL 应该是 <code>/about/</code> 和 <code>/archive/</code>（带斜杠），而不是 <code>.html</code> 结尾。</p>
<h3 id="解决方案-2">解决方案</h3>
<p>修改导航栏链接格式：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="c">&lt;!-- 修改前 --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/about.html&#34;</span><span class="p">&gt;</span>About<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/archive.html&#34;</span><span class="p">&gt;</span>Archive<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">&lt;!-- 修改后 --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/about/&#34;</span><span class="p">&gt;</span>About<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ site.baseurl }}/archive/&#34;</span><span class="p">&gt;</span>Archive<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="4-github-pages-构建队列卡住问题">4. GitHub Pages 构建队列卡住问题</h2>
<h3 id="问题描述-3">问题描述</h3>
<p>推送代码后，GitHub Actions 一直显示 &ldquo;Queued&rdquo; 状态，超过 10 分钟甚至更久都没有构建。</p>
<h3 id="原因分析">原因分析</h3>
<p>这是 <strong>GitHub 服务本身的问题</strong>，不是代码问题。根据 GitHub Status 页面显示，GitHub Actions 服务正在经历事故（Incident）。</p>
<h3 id="解决方案-3">解决方案</h3>
<ol>
<li>
<p><strong>等待 GitHub 修复</strong></p>
<ul>
<li>通常需要 30 分钟到几小时</li>
<li>关注 <a href="https://www.githubstatus.com/">https://www.githubstatus.com/</a> 获取最新状态</li>
</ul>
</li>
<li>
<p><strong>检查 GitHub 服务状态</strong></p>
<ul>
<li>GitHub Status: <a href="https://www.githubstatus.com/">https://www.githubstatus.com/</a></li>
<li>Twitter: @githubstatus</li>
<li>Downdetector: downdetector.com/status/github</li>
</ul>
</li>
<li>
<p><strong>本地验证代码正常</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">bundle <span class="nb">exec</span> jekyll build
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果本地构建成功，说明代码没问题，只是 GitHub 服务问题。</p>
</li>
</ol>
<h3 id="预防措施">预防措施</h3>
<ul>
<li>推送代码前先在本地预览</li>
<li>避免在 GitHub 服务不稳定时推送重要更新</li>
</ul>
<hr>
<h2 id="5-新文章推送后不显示问题">5. 新文章推送后不显示问题</h2>
<h3 id="问题描述-4">问题描述</h3>
<p>新写的文章 <code>git push</code> 之后在博客网站没有显示。</p>
<h3 id="常见原因">常见原因</h3>
<ol>
<li>
<p><strong>文件名格式问题</strong></p>
<ul>
<li>要求：<code>YYYY-MM-DD-title.md</code></li>
<li>避免在文件名末尾使用特殊字符</li>
</ul>
</li>
<li>
<p><strong>Front Matter 格式问题</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">layout</span><span class="p">:</span><span class="w"> </span><span class="l">post</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;文章标题&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">date</span><span class="p">:</span><span class="w"> </span><span class="ld">2026-03-06</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">Tag1, Tag2] </span><span class="w"> </span><span class="c"># 标签用逗号分隔，不要有空格</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>标签格式问题</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># 错误：包含空格的标签</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">Algorithm programming problem]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># 正确：逗号分隔或加引号</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">Algorithm, programming, problem]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># 或</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">tags</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;Algorithm programming problem&#34;</span><span class="p">]</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h3 id="解决方案-4">解决方案</h3>
<ul>
<li>确保文件名格式正确</li>
<li>检查 front matter 格式</li>
<li>修复后重新提交推送</li>
</ul>
<hr>
<h2 id="6-latex-数学公式渲染失败问题">6. LaTeX 数学公式渲染失败问题</h2>
<h3 id="问题描述-5">问题描述</h3>
<p>博客中的 LaTeX 代码显示为纯文本 <code>[Math Processing Error]</code>，无法正常渲染。</p>
<h3 id="解决方案-5">解决方案</h3>
<p>更新 MathJax 配置到稳定版本。</p>
<p>修改 <code>_includes/mathjax_support.html</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;text/x-mathjax-config&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">MathJax</span><span class="p">.</span><span class="nx">Hub</span><span class="p">.</span><span class="nx">Config</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">    <span class="nx">tex2jax</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">inlineMath</span><span class="o">:</span> <span class="p">[</span> <span class="p">[</span><span class="s1">&#39;$&#39;</span><span class="p">,</span><span class="s1">&#39;$&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;\\(&#39;</span><span class="p">,</span><span class="s1">&#39;\\)&#39;</span><span class="p">]</span> <span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nx">displayMath</span><span class="o">:</span> <span class="p">[</span> <span class="p">[</span><span class="s1">&#39;$$&#39;</span><span class="p">,</span><span class="s1">&#39;$$&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;\\[&#39;</span><span class="p">,</span><span class="s1">&#39;\\]&#39;</span><span class="p">]</span> <span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nx">processEscapes</span><span class="o">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">TeX</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">equationNumbers</span><span class="o">:</span> <span class="p">{</span> <span class="nx">autoNumber</span><span class="o">:</span> <span class="s2">&#34;AMS&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="nx">extensions</span><span class="o">:</span> <span class="p">[</span><span class="s2">&#34;AMSmath.js&#34;</span><span class="p">,</span><span class="s2">&#34;AMSsymbols.js&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;HTML-CSS&#34;</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">scale</span><span class="o">:</span> <span class="mi">100</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS_HTML&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="使用方法">使用方法</h3>
<p>确保文章头部开启了 mathjax：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">mathjax</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">---</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>支持的语法：</p>
<table>
	<thead>
			<tr>
					<th>类型</th>
					<th>语法</th>
					<th>示例</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>行内公式</td>
					<td><code>$...$</code></td>
					<td>$E=mc^2$</td>
			</tr>
			<tr>
					<td>行间公式</td>
					<td><code>$$...$$</code></td>
					<td>$$\int_0^1 x^2 dx$$</td>
			</tr>
			<tr>
					<td>括号公式</td>
					<td><code>\[...\]</code></td>
					<td>\[a^2 + b^2 = c^2\]</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="7-添加相关文章侧边栏功能">7. 添加相关文章侧边栏功能</h2>
<h3 id="功能描述">功能描述</h3>
<p>在文章页面左侧显示同标签的其他文章列表，方便读者浏览相关内容。</p>
<h3 id="解决方案-6">解决方案</h3>
<ol>
<li>创建 <code>_includes/related-posts.html</code></li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{% if page.tags.size &gt; 0 %}
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;related-posts&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">hr</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;hidden-sm hidden-xs&#34;</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;margin: 0 0 20px 0;&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">h5</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;color: #333; margin-bottom: 15px; font-size: 14px; font-weight: bold;&#34;</span><span class="p">&gt;</span>相关文章<span class="p">&lt;/</span><span class="nt">h5</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;related-posts-list&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        {% assign current_url = page.url %}
</span></span><span class="line"><span class="cl">        {% assign tag_posts = &#34;&#34; | split: &#34;&#34; %}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        {% for tag in page.tags %}
</span></span><span class="line"><span class="cl">            {% for post in site.tags[tag] %}
</span></span><span class="line"><span class="cl">                {% unless post.url == current_url %}
</span></span><span class="line"><span class="cl">                    {% unless tag_posts contains post %}
</span></span><span class="line"><span class="cl">                        {% assign tag_posts = tag_posts | push: post %}
</span></span><span class="line"><span class="cl">                    {% endunless %}
</span></span><span class="line"><span class="cl">                {% endunless %}
</span></span><span class="line"><span class="cl">            {% endfor %}
</span></span><span class="line"><span class="cl">        {% endfor %}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        {% for post in tag_posts limit: 10 %}
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;{{ post.url | prepend: site.baseurl }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">                {{ post.title | truncate: 28 }}
</span></span><span class="line"><span class="cl">            <span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        {% endfor %}
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">{% endif %}
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="2">
<li>修改 <code>_layouts/post.html</code>，在左侧添加：</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="c">&lt;!-- Left Sidebar - Related Posts --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-lg-2 visible-lg-block sidebar-container&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    {% include related-posts.html %}
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h2 id="总结">总结</h2>
<table>
	<thead>
			<tr>
					<th>问题</th>
					<th>状态</th>
					<th>解决方案</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>自动刷新</td>
					<td>✅ 已解决</td>
					<td>移除自动刷新，改用自然更新</td>
			</tr>
			<tr>
					<td>导航栏异常</td>
					<td>✅ 已解决</td>
					<td>硬编码导航栏</td>
			</tr>
			<tr>
					<td>页面 404</td>
					<td>✅ 已解决</td>
					<td>修复链接格式</td>
			</tr>
			<tr>
					<td>GitHub 构建卡住</td>
					<td>⏳ 等待恢复</td>
					<td>等待 GitHub 服务修复</td>
			</tr>
			<tr>
					<td>文章不显示</td>
					<td>✅ 已解决</td>
					<td>修复文件名和标签格式</td>
			</tr>
			<tr>
					<td>LaTeX 渲染失败</td>
					<td>✅ 已解决</td>
					<td>更新 MathJax 配置</td>
			</tr>
			<tr>
					<td>相关文章功能</td>
					<td>✅ 已实现</td>
					<td>添加侧边栏组件</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="经验教训">经验教训</h2>
<ol>
<li><strong>本地预览很重要</strong> - 推送前先在本地测试</li>
<li><strong>GitHub 服务也会出问题</strong> - 遇到问题先检查服务状态</li>
<li><strong>文件名和格式要规范</strong> - 遵循 Jekyll 的命名规则</li>
<li><strong>做好备份</strong> - 重要修改前先 commit</li>
</ol>
<hr>
<p><em>本文持续更新中&hellip;</em></p>
]]></content:encoded></item><item><title>VScode断点使用</title><link>https://farmer3-c.github.io/posts/vscode/</link><pubDate>Tue, 21 Apr 2026 23:20:25 +0800</pubDate><guid>https://farmer3-c.github.io/posts/vscode/</guid><description>&lt;h1 id="前因"&gt;前因&lt;/h1&gt;
&lt;p&gt;今天遇到了一个问题，c++编程解决问题时不能正确输出，于是我想使用断点调试来找出问题所在。此前很少使用断点调试，对于调试的几个按钮仅仅认为向下的箭头是向下运行一步、向上的箭头是回退一步、方框是退出调试。&lt;/p&gt;
&lt;p&gt;于是：出现
（1）
&lt;img alt="1" loading="lazy" src="https://farmer3-c.github.io/img/vscode/1.png"&gt;&lt;/p&gt;
&lt;p&gt;本应长度为3的数组b却是&lt;code&gt;std::vector of length -1198221809, capacity 2069355498&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;继续点击向下的箭头；结果在几个头文件中来回转跳
（2）
&lt;img alt="2" loading="lazy" src="https://farmer3-c.github.io/img/vscode/2.png"&gt;&lt;/p&gt;
&lt;p&gt;回退到（1）的状态，再点击&lt;code&gt;step over&lt;/code&gt;符号，数组b的长度恢复正常：
（3）
&lt;img alt="3" loading="lazy" src="https://farmer3-c.github.io/img/vscode/3.png"&gt;&lt;/p&gt;
&lt;p&gt;不知道其中原因，我查了下断点用法。&lt;/p&gt;
&lt;h1 id="断点使用"&gt;断点使用&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;继续 / 暂停 F5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;继续&lt;/strong&gt;：恢复程序/脚本的正常执行（直到下一个断点）。 &lt;strong&gt;暂停&lt;/strong&gt;：检查当前行正在执行的代码并逐行进行调试。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单步跳过 F10&lt;/td&gt;
&lt;td&gt;将下一行代码作为一个整体执行，而不进入该方法的内部步骤。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单步调试 F11&lt;/td&gt;
&lt;td&gt;进入下一行代码的方法，以便逐行跟踪其执行过程。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单步跳出 Shift+F11&lt;/td&gt;
&lt;td&gt;在方法或子程序内部时，完成当前方法的剩余行并返回到之前的执行上下文，就像将其作为一个命令执行一样。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;重启 Ctrl+Shift+F5&lt;/td&gt;
&lt;td&gt;终止当前程序执行并使用当前的运行配置再次开始调试。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;停止 Shift+F5&lt;/td&gt;
&lt;td&gt;终止当前程序执行。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;单步调试： 进入下一行代码的方法，以便逐行跟踪其执行过程。意思是说要把最基础的编译文件显示出来，单步跳过封装了执行单步调试的所有过程，可以一直按 F11 达到 F10 所完成的任务。&lt;/p&gt;
&lt;p&gt;之前以为按f11是在几个头文件中来回转跳，其实不是。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vscode.js.cn/docs/debugtest/debugging"&gt;使用 Visual Studio Code 调试代码&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><content:encoded><![CDATA[<h1 id="前因">前因</h1>
<p>今天遇到了一个问题，c++编程解决问题时不能正确输出，于是我想使用断点调试来找出问题所在。此前很少使用断点调试，对于调试的几个按钮仅仅认为向下的箭头是向下运行一步、向上的箭头是回退一步、方框是退出调试。</p>
<p>于是：出现
（1）
<img alt="1" loading="lazy" src="/img/vscode/1.png"></p>
<p>本应长度为3的数组b却是<code>std::vector of length -1198221809, capacity 2069355498</code>。</p>
<p>继续点击向下的箭头；结果在几个头文件中来回转跳
（2）
<img alt="2" loading="lazy" src="/img/vscode/2.png"></p>
<p>回退到（1）的状态，再点击<code>step over</code>符号，数组b的长度恢复正常：
（3）
<img alt="3" loading="lazy" src="/img/vscode/3.png"></p>
<p>不知道其中原因，我查了下断点用法。</p>
<h1 id="断点使用">断点使用</h1>
<table>
	<thead>
			<tr>
					<th>操作</th>
					<th>描述</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>继续 / 暂停 F5</td>
					<td><strong>继续</strong>：恢复程序/脚本的正常执行（直到下一个断点）。 <strong>暂停</strong>：检查当前行正在执行的代码并逐行进行调试。</td>
			</tr>
			<tr>
					<td>单步跳过 F10</td>
					<td>将下一行代码作为一个整体执行，而不进入该方法的内部步骤。</td>
			</tr>
			<tr>
					<td>单步调试 F11</td>
					<td>进入下一行代码的方法，以便逐行跟踪其执行过程。</td>
			</tr>
			<tr>
					<td>单步跳出 Shift+F11</td>
					<td>在方法或子程序内部时，完成当前方法的剩余行并返回到之前的执行上下文，就像将其作为一个命令执行一样。</td>
			</tr>
			<tr>
					<td>重启 Ctrl+Shift+F5</td>
					<td>终止当前程序执行并使用当前的运行配置再次开始调试。</td>
			</tr>
			<tr>
					<td>停止 Shift+F5</td>
					<td>终止当前程序执行。</td>
			</tr>
	</tbody>
</table>
<p>单步调试： 进入下一行代码的方法，以便逐行跟踪其执行过程。意思是说要把最基础的编译文件显示出来，单步跳过封装了执行单步调试的所有过程，可以一直按 F11 达到 F10 所完成的任务。</p>
<p>之前以为按f11是在几个头文件中来回转跳，其实不是。</p>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://vscode.js.cn/docs/debugtest/debugging">使用 Visual Studio Code 调试代码</a></li>
</ul>
]]></content:encoded></item><item><title>3290. 最高乘法得分</title><link>https://farmer3-c.github.io/posts/3290-/</link><pubDate>Sun, 22 Mar 2026 18:58:15 +0800</pubDate><guid>https://farmer3-c.github.io/posts/3290-/</guid><description>&lt;h1 id="3290-最高乘法得分"&gt;&lt;a href="https://leetcode.cn/problems/maximum-multiplication-score/description/"&gt;3290. 最高乘法得分&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;给你一个大小为 4 的整数数组 &lt;code&gt;a&lt;/code&gt; 和一个大小 &lt;strong&gt;至少&lt;/strong&gt;为 4 的整数数组 &lt;code&gt;b&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;你需要从数组 &lt;code&gt;b&lt;/code&gt; 中选择四个下标 &lt;code&gt;i0&lt;/code&gt;, &lt;code&gt;i1&lt;/code&gt;, &lt;code&gt;i2&lt;/code&gt;, 和 &lt;code&gt;i3&lt;/code&gt;，并满足 &lt;code&gt;i0 &amp;lt; i1 &amp;lt; i2 &amp;lt; i3&lt;/code&gt;。你的得分将是 &lt;code&gt;a[0] * b[i0] + a[1] * b[i1] + a[2] * b[i2] + a[3] * b[i3]&lt;/code&gt; 的值。&lt;/p&gt;
&lt;p&gt;返回你能够获得的 &lt;strong&gt;最大&lt;/strong&gt; 得分。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$a.length == 4$&lt;/li&gt;
&lt;li&gt;$4 &lt;= b.length &lt;= 10^5$&lt;/li&gt;
&lt;li&gt;$-10^5 &lt;= a[i], b[i] &lt;= 10^5$&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="思路"&gt;思路&lt;/h1&gt;
&lt;p&gt;用dp来做，从后往前选取&lt;code&gt;a[i]、b[j]&lt;/code&gt;相乘，考虑2种状态：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;选当前a[i]、b[j]相乘，继续考虑a[i-1]、b[j-1]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;不选选当前a[i]、b[j]相乘，继续考虑a[i]、b[j-1]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;状态转换：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dfs(i,j)=max(dfs(i-1,j-1)+a[i]*b[j],dfs(i,j-1))&lt;/code&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;maxScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nl"&gt;row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ranges&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;LLONG_MIN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;LLONG_MIN&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;LLONG_MIN&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="3290-最高乘法得分"><a href="https://leetcode.cn/problems/maximum-multiplication-score/description/">3290. 最高乘法得分</a></h1>
<p>给你一个大小为 4 的整数数组 <code>a</code> 和一个大小 <strong>至少</strong>为 4 的整数数组 <code>b</code>。</p>
<p>你需要从数组 <code>b</code> 中选择四个下标 <code>i0</code>, <code>i1</code>, <code>i2</code>, 和 <code>i3</code>，并满足 <code>i0 &lt; i1 &lt; i2 &lt; i3</code>。你的得分将是 <code>a[0] * b[i0] + a[1] * b[i1] + a[2] * b[i2] + a[3] * b[i3]</code> 的值。</p>
<p>返回你能够获得的 <strong>最大</strong> 得分。</p>
<p><strong>提示：</strong></p>
<ul>
<li>$a.length == 4$</li>
<li>$4 <= b.length <= 10^5$</li>
<li>$-10^5 <= a[i], b[i] <= 10^5$</li>
</ul>
<h1 id="思路">思路</h1>
<p>用dp来做，从后往前选取<code>a[i]、b[j]</code>相乘，考虑2种状态：</p>
<p><code>选当前a[i]、b[j]相乘，继续考虑a[i-1]、b[j-1]</code></p>
<p><code>不选选当前a[i]、b[j]相乘，继续考虑a[i]、b[j-1]</code></p>
<p>状态转换：</p>
<p><code>dfs(i,j)=max(dfs(i-1,j-1)+a[i]*b[j],dfs(i,j-1))</code></p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">long</span> <span class="kt">long</span> <span class="n">maxScore</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">n</span><span class="o">=</span><span class="n">b</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="n">array</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="p">,</span><span class="mi">4</span><span class="o">&gt;&gt;</span><span class="n">memo</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span><span class="nl">row</span><span class="p">:</span><span class="n">memo</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="n">ranges</span><span class="o">::</span><span class="n">fill</span><span class="p">(</span><span class="n">row</span><span class="p">,</span><span class="n">LLONG_MIN</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">auto</span> <span class="n">dfs</span><span class="o">=</span><span class="p">[</span><span class="o">&amp;</span><span class="p">](</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="n">dfs</span><span class="p">,</span><span class="kt">int</span> <span class="n">i</span><span class="p">,</span><span class="kt">int</span> <span class="n">j</span><span class="p">)</span><span class="o">-&gt;</span><span class="kt">long</span> <span class="kt">long</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">j</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">)</span><span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">i</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="n">LLONG_MIN</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">auto</span> <span class="o">&amp;</span><span class="n">res</span><span class="o">=</span><span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">res</span><span class="o">==</span><span class="n">LLONG_MIN</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span><span class="o">=</span><span class="n">max</span><span class="p">(</span><span class="n">dfs</span><span class="p">(</span><span class="n">dfs</span><span class="p">,</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">j</span><span class="p">),</span><span class="n">dfs</span><span class="p">(</span><span class="n">dfs</span><span class="p">,</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">a</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">*</span><span class="n">b</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nf">dfs</span><span class="p">(</span><span class="n">dfs</span><span class="p">,</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://leetcode.cn/problems/maximum-multiplication-score/solutions/2917840/jiao-ni-yi-bu-bu-si-kao-dpcong-ji-yi-hua-9ul8/">灵茶山艾府</a></li>
</ul>
]]></content:encoded></item><item><title>474. 一和零</title><link>https://farmer3-c.github.io/posts/474-/</link><pubDate>Tue, 17 Mar 2026 12:36:21 +0800</pubDate><guid>https://farmer3-c.github.io/posts/474-/</guid><description>&lt;h1 id="474-一和零"&gt;&lt;a href="https://leetcode.cn/problems/ones-and-zeroes/description/"&gt;474. 一和零&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;给你一个二进制字符串数组 &lt;code&gt;strs&lt;/code&gt; 和两个整数 &lt;code&gt;m&lt;/code&gt; 和 &lt;code&gt;n&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;请你找出并返回 &lt;code&gt;strs&lt;/code&gt; 的最大子集的长度，该子集中 &lt;strong&gt;最多&lt;/strong&gt; 有 &lt;code&gt;m&lt;/code&gt; 个 &lt;code&gt;0&lt;/code&gt; 和 &lt;code&gt;n&lt;/code&gt; 个 &lt;code&gt;1&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;如果 &lt;code&gt;x&lt;/code&gt; 的所有元素也是 &lt;code&gt;y&lt;/code&gt; 的元素，集合 &lt;code&gt;x&lt;/code&gt; 是集合 &lt;code&gt;y&lt;/code&gt; 的 &lt;strong&gt;子集&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= strs.length &amp;lt;= 600&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= strs[i].length &amp;lt;= 100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strs[i]&lt;/code&gt; 仅由 &lt;code&gt;'0'&lt;/code&gt; 和 &lt;code&gt;'1'&lt;/code&gt; 组成&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= m, n &amp;lt;= 100&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="思路"&gt;思路&lt;/h1&gt;
&lt;p&gt;首先，这是一个二维0-1背包问题，可以使用三维数组解决。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;f[i][j][k]&lt;/code&gt;:&lt;code&gt;i&lt;/code&gt;代表&lt;code&gt;0~i&lt;/code&gt;的选取结果,&lt;code&gt;j&lt;/code&gt;代表不超过&lt;code&gt;j&lt;/code&gt;个零,&lt;code&gt;k&lt;/code&gt;同理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;f[i][j][k]=max(dp[i−1][j][k],dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dp[i−1][j][k]&lt;/code&gt; 不选择当前考虑的字符串&lt;code&gt;i&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1&lt;/code&gt; 选择当前考虑的字符串​&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;初始化&lt;/strong&gt;：为了避免分类讨论，通常多设置一行。这里可以认为，第 0 个字符串是空串。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;findMaxForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cnum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;x0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;cnum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="nl"&gt;c&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="474-一和零"><a href="https://leetcode.cn/problems/ones-and-zeroes/description/">474. 一和零</a></h1>
<p>给你一个二进制字符串数组 <code>strs</code> 和两个整数 <code>m</code> 和 <code>n</code> 。</p>
<p>请你找出并返回 <code>strs</code> 的最大子集的长度，该子集中 <strong>最多</strong> 有 <code>m</code> 个 <code>0</code> 和 <code>n</code> 个 <code>1</code> 。</p>
<p>如果 <code>x</code> 的所有元素也是 <code>y</code> 的元素，集合 <code>x</code> 是集合 <code>y</code> 的 <strong>子集</strong> 。</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= strs.length &lt;= 600</code></li>
<li><code>1 &lt;= strs[i].length &lt;= 100</code></li>
<li><code>strs[i]</code> 仅由 <code>'0'</code> 和 <code>'1'</code> 组成</li>
<li><code>1 &lt;= m, n &lt;= 100</code></li>
</ul>
<h1 id="思路">思路</h1>
<p>首先，这是一个二维0-1背包问题，可以使用三维数组解决。</p>
<p><code>f[i][j][k]</code>:<code>i</code>代表<code>0~i</code>的选取结果,<code>j</code>代表不超过<code>j</code>个零,<code>k</code>同理。</p>
<p><code>f[i][j][k]=max(dp[i−1][j][k],dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1)</code></p>
<p><code>dp[i−1][j][k]</code>   不选择当前考虑的字符串<code>i</code></p>
<p><code>dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1</code>    选择当前考虑的字符串​</p>
<blockquote>
<p><strong>初始化</strong>：为了避免分类讨论，通常多设置一行。这里可以认为，第 0 个字符串是空串。</p>
</blockquote>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">findMaxForm</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&amp;</span> <span class="n">strs</span><span class="p">,</span> <span class="kt">int</span> <span class="n">m</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">strs</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">         <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;&gt;</span> <span class="n">dp</span><span class="p">(</span><span class="n">len</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="n">m</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">x1</span> <span class="o">=</span> <span class="n">cnum</span><span class="p">(</span><span class="n">strs</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">x0</span> <span class="o">=</span> <span class="n">strs</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="n">x1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="n">m</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="n">k</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="n">x0</span> <span class="o">&amp;&amp;</span> <span class="n">k</span> <span class="o">&gt;=</span> <span class="n">x1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span>
</span></span><span class="line"><span class="cl">                            <span class="n">max</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="n">k</span><span class="p">],</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="n">x0</span><span class="p">][</span><span class="n">k</span> <span class="o">-</span> <span class="n">x1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">len</span><span class="p">][</span><span class="n">m</span><span class="p">][</span><span class="n">n</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="nf">cnum</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">&#39;1&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="n">cnt</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">cnt</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://leetcode.cn/problems/ones-and-zeroes/solutions/72372/dong-tai-gui-hua-zhuan-huan-wei-0-1-bei-bao-wen-ti/">liweiwei1419</a></li>
</ul>
]]></content:encoded></item><item><title>1415. 长度为 n 的开心字符串中字典序第 k 小的字符串</title><link>https://farmer3-c.github.io/posts/1415--n--k-/</link><pubDate>Sat, 14 Mar 2026 10:46:56 +0800</pubDate><guid>https://farmer3-c.github.io/posts/1415--n--k-/</guid><description>&lt;h1 id="1415-长度为-n-的开心字符串中字典序第-k-小的字符串"&gt;&lt;a href="https://leetcode.cn/problems/the-k-th-lexicographical-string-of-all-happy-strings-of-length-n/description/?envType=daily-question&amp;amp;envId=2026-03-14"&gt;1415. 长度为 n 的开心字符串中字典序第 k 小的字符串&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;一个 「开心字符串」定义为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;仅包含小写字母 &lt;code&gt;['a', 'b', 'c']&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;对所有在 &lt;code&gt;1&lt;/code&gt; 到 &lt;code&gt;s.length - 1&lt;/code&gt; 之间的 &lt;code&gt;i&lt;/code&gt; ，满足 &lt;code&gt;s[i] != s[i + 1]&lt;/code&gt; （字符串的下标从 1 开始）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比方说，字符串 &lt;strong&gt;&amp;ldquo;abc&amp;rdquo;&lt;/strong&gt;，&lt;strong&gt;&amp;ldquo;ac&amp;rdquo;，&amp;ldquo;b&amp;rdquo;&lt;/strong&gt; 和 &lt;strong&gt;&amp;ldquo;abcbabcbcb&amp;rdquo;&lt;/strong&gt; 都是开心字符串，但是 &lt;strong&gt;&amp;ldquo;aa&amp;rdquo;&lt;/strong&gt;，&lt;strong&gt;&amp;ldquo;baa&amp;rdquo;&lt;/strong&gt; 和 &lt;strong&gt;&amp;ldquo;ababbc&amp;rdquo;&lt;/strong&gt; 都不是开心字符串。&lt;/p&gt;
&lt;p&gt;给你两个整数 &lt;code&gt;n&lt;/code&gt; 和 &lt;code&gt;k&lt;/code&gt; ，你需要将长度为 &lt;code&gt;n&lt;/code&gt; 的所有开心字符串按字典序排序。&lt;/p&gt;
&lt;p&gt;请你返回排序后的第 k 个开心字符串，如果长度为 &lt;code&gt;n&lt;/code&gt; 的开心字符串少于 &lt;code&gt;k&lt;/code&gt; 个，那么请你返回 &lt;strong&gt;空字符串&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= n &amp;lt;= 10&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= k &amp;lt;= 100&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="思路"&gt;思路&lt;/h1&gt;
&lt;p&gt;首先，长度为 &lt;code&gt;n&lt;/code&gt; 的开心字符串个数为&lt;code&gt;(1&amp;lt;&amp;lt;(n-1))*3&lt;/code&gt;，若小于k，则返回&lt;strong&gt;空字符串&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;设置一个字符作为已经添加的前一个字符，保证得到开心字符串。&lt;/p&gt;
&lt;p&gt;令&lt;code&gt;count_per_choice=1&amp;lt;&amp;lt;(n-i-1)&lt;/code&gt;为每添加一个字符所代表的可能性，每次从&lt;code&gt;a&lt;/code&gt;到&lt;code&gt;c&lt;/code&gt;遍历，若&lt;code&gt;count_per_choice&amp;gt;=k&lt;/code&gt;,则取当前字符，跳出循环，否则&lt;code&gt;k-count_per_choice&lt;/code&gt;,继续遍历。&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="1415-长度为-n-的开心字符串中字典序第-k-小的字符串"><a href="https://leetcode.cn/problems/the-k-th-lexicographical-string-of-all-happy-strings-of-length-n/description/?envType=daily-question&amp;envId=2026-03-14">1415. 长度为 n 的开心字符串中字典序第 k 小的字符串</a></h1>
<p>一个 「开心字符串」定义为：</p>
<ul>
<li>仅包含小写字母 <code>['a', 'b', 'c']</code>.</li>
<li>对所有在 <code>1</code> 到 <code>s.length - 1</code> 之间的 <code>i</code> ，满足 <code>s[i] != s[i + 1]</code> （字符串的下标从 1 开始）。</li>
</ul>
<p>比方说，字符串 <strong>&ldquo;abc&rdquo;</strong>，<strong>&ldquo;ac&rdquo;，&ldquo;b&rdquo;</strong> 和 <strong>&ldquo;abcbabcbcb&rdquo;</strong> 都是开心字符串，但是 <strong>&ldquo;aa&rdquo;</strong>，<strong>&ldquo;baa&rdquo;</strong> 和 <strong>&ldquo;ababbc&rdquo;</strong> 都不是开心字符串。</p>
<p>给你两个整数 <code>n</code> 和 <code>k</code> ，你需要将长度为 <code>n</code> 的所有开心字符串按字典序排序。</p>
<p>请你返回排序后的第 k 个开心字符串，如果长度为 <code>n</code> 的开心字符串少于 <code>k</code> 个，那么请你返回 <strong>空字符串</strong> 。</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= n &lt;= 10</code></li>
<li><code>1 &lt;= k &lt;= 100</code></li>
</ul>
<h1 id="思路">思路</h1>
<p>首先，长度为 <code>n</code> 的开心字符串个数为<code>(1&lt;&lt;(n-1))*3</code>，若小于k，则返回<strong>空字符串</strong> 。</p>
<p>设置一个字符作为已经添加的前一个字符，保证得到开心字符串。</p>
<p>令<code>count_per_choice=1&lt;&lt;(n-i-1)</code>为每添加一个字符所代表的可能性，每次从<code>a</code>到<code>c</code>遍历，若<code>count_per_choice&gt;=k</code>,则取当前字符，跳出循环，否则<code>k-count_per_choice</code>,继续遍历。</p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">string</span> <span class="n">getHappyString</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">total</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">));</span> 
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&gt;</span> <span class="n">total</span><span class="p">)</span> <span class="k">return</span> <span class="s">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">string</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">char</span> <span class="n">prev</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">count_per_choice</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 2^(n-i-1)
</span></span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="n">c</span> <span class="o">=</span> <span class="sc">&#39;a&#39;</span><span class="p">;</span> <span class="n">c</span> <span class="o">&lt;=</span> <span class="sc">&#39;c&#39;</span><span class="p">;</span> <span class="o">++</span><span class="n">c</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="n">prev</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span> 
</span></span><span class="line"><span class="cl">                
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">&lt;=</span> <span class="n">count_per_choice</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">result</span> <span class="o">+=</span> <span class="n">c</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="n">prev</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="n">k</span> <span class="o">-=</span> <span class="n">count_per_choice</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>]]></content:encoded></item><item><title>3129. 找出所有稳定的二进制数组 I</title><link>https://farmer3-c.github.io/posts/3129--i/</link><pubDate>Mon, 09 Mar 2026 23:30:45 +0800</pubDate><guid>https://farmer3-c.github.io/posts/3129--i/</guid><description>&lt;h1 id="3129-找出所有稳定的二进制数组-i"&gt;&lt;a href="https://leetcode.cn/problems/find-all-possible-stable-binary-arrays-i/description/?envType=daily-question&amp;amp;envId=2026-03-09"&gt;3129. 找出所有稳定的二进制数组 I&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;给你 3 个正整数 &lt;code&gt;zero&lt;/code&gt; ，&lt;code&gt;one&lt;/code&gt; 和 &lt;code&gt;limit&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;一个 二进制数组 &lt;code&gt;arr&lt;/code&gt; 如果满足以下条件，那么我们称它是 &lt;strong&gt;稳定的&lt;/strong&gt; ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 在 &lt;code&gt;arr&lt;/code&gt; 中出现次数 &lt;strong&gt;恰好&lt;/strong&gt; 为 &lt;code&gt;zero&lt;/code&gt; 。&lt;/li&gt;
&lt;li&gt;1 在 &lt;code&gt;arr&lt;/code&gt; 中出现次数 &lt;strong&gt;恰好&lt;/strong&gt; 为 &lt;code&gt;one&lt;/code&gt; 。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arr&lt;/code&gt; 中每个长度超过 &lt;code&gt;limit&lt;/code&gt; 的 子数组 都 &lt;strong&gt;同时&lt;/strong&gt; 包含 0 和 1 。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请你返回 &lt;strong&gt;稳定&lt;/strong&gt; 二进制数组的 &lt;em&gt;总&lt;/em&gt; 数目。&lt;/p&gt;
&lt;p&gt;由于答案可能很大，将它对 $10^9 + 7$ &lt;strong&gt;取余&lt;/strong&gt; 后返回。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= zero, one, limit &amp;lt;= 200&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="思路"&gt;思路&lt;/h1&gt;
&lt;p&gt;首先，这个问题是每个位有两个选择&lt;code&gt;0/1&lt;/code&gt;，再加上限制&lt;code&gt;limit&lt;/code&gt;,感觉就可以用dp做。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;定义：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;f[i][j][0] 为使用 i 个 0，j 个 1，且末尾为 0 的稳定数组个数；&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="3129-找出所有稳定的二进制数组-i"><a href="https://leetcode.cn/problems/find-all-possible-stable-binary-arrays-i/description/?envType=daily-question&amp;envId=2026-03-09">3129. 找出所有稳定的二进制数组 I</a></h1>
<p>给你 3 个正整数 <code>zero</code> ，<code>one</code> 和 <code>limit</code> 。</p>
<p>一个 二进制数组 <code>arr</code> 如果满足以下条件，那么我们称它是 <strong>稳定的</strong> ：</p>
<ul>
<li>0 在 <code>arr</code> 中出现次数 <strong>恰好</strong> 为 <code>zero</code> 。</li>
<li>1 在 <code>arr</code> 中出现次数 <strong>恰好</strong> 为 <code>one</code> 。</li>
<li><code>arr</code> 中每个长度超过 <code>limit</code> 的 子数组 都 <strong>同时</strong> 包含 0 和 1 。</li>
</ul>
<p>请你返回 <strong>稳定</strong> 二进制数组的 <em>总</em> 数目。</p>
<p>由于答案可能很大，将它对 $10^9 + 7$ <strong>取余</strong> 后返回。</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>1 &lt;= zero, one, limit &lt;= 200</code></li>
</ul>
<h1 id="思路">思路</h1>
<p>首先，这个问题是每个位有两个选择<code>0/1</code>，再加上限制<code>limit</code>,感觉就可以用dp做。</p>
<p><strong>定义：</strong></p>
<p>f[i][j][0] 为使用 i 个 0，j 个 1，且末尾为 0 的稳定数组个数；</p>
<p>f[i][j][1] 为使用 i 个 0，j 个 1，且末尾为 1 的稳定数组个数。</p>
<p>因为<code>limit</code>的限制，末尾连续<code>0/1</code>的数量不能超过它，f[i][j][0]为f[i-limit][j][0]~f[i-1][j][0]之和，f[i][j][1]同理。</p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">f</span><span class="p">[</span><span class="mi">205</span><span class="p">][</span><span class="mi">205</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="nf">numberOfStableArrays</span><span class="p">(</span><span class="kt">int</span> <span class="n">z</span><span class="p">,</span> <span class="kt">int</span> <span class="n">o</span><span class="p">,</span> <span class="kt">int</span> <span class="n">limit</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">const</span> <span class="kt">int</span> <span class="n">mod</span> <span class="o">=</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="mi">7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">z</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;=</span> <span class="n">limit</span><span class="p">),</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">o</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;=</span> <span class="n">limit</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">sum1</span><span class="p">[</span><span class="n">o</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="n">o</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">sum1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">z</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">sum0</span> <span class="o">=</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="n">o</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">sum1</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">sum0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="n">sum0</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum0</span> <span class="o">+</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;=</span> <span class="n">limit</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">sum0</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum0</span> <span class="o">+</span> <span class="n">mod</span> <span class="o">-</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="n">limit</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="n">sum1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;=</span> <span class="n">limit</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">sum1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">sum1</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="n">mod</span> <span class="o">-</span> <span class="n">f</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="n">limit</span><span class="p">][</span><span class="n">j</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">(</span><span class="n">f</span><span class="p">[</span><span class="n">z</span><span class="p">][</span><span class="n">o</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">f</span><span class="p">[</span><span class="n">z</span><span class="p">][</span><span class="n">o</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://leetcode.cn/discuss/post/3583871/di-129-chang-li-kou-ye-miao-shuang-zhou-7hwjq/comments/2953983/">newhar</a></li>
</ul>
]]></content:encoded></item><item><title>1594. 矩阵的最大非负积</title><link>https://farmer3-c.github.io/posts/1594-/</link><pubDate>Sun, 08 Mar 2026 16:10:38 +0800</pubDate><guid>https://farmer3-c.github.io/posts/1594-/</guid><description>&lt;h1 id="1594-矩阵的最大非负积"&gt;&lt;a href="https://leetcode.cn/problems/maximum-non-negative-product-in-a-matrix/description/"&gt;1594. 矩阵的最大非负积&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;给你一个大小为 &lt;code&gt;m x n&lt;/code&gt; 的矩阵 &lt;code&gt;grid&lt;/code&gt; 。最初，你位于左上角 &lt;code&gt;(0, 0)&lt;/code&gt; ，每一步，你可以在矩阵中 &lt;strong&gt;向右&lt;/strong&gt; 或 &lt;strong&gt;向下&lt;/strong&gt; 移动。&lt;/p&gt;
&lt;p&gt;在从左上角 &lt;code&gt;(0, 0)&lt;/code&gt; 开始到右下角 &lt;code&gt;(m - 1, n - 1)&lt;/code&gt; 结束的所有路径中，找出具有 &lt;strong&gt;最大非负积&lt;/strong&gt; 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。&lt;/p&gt;
&lt;p&gt;返回 &lt;strong&gt;最大非负积&lt;/strong&gt; 对 &lt;strong&gt;$10^9 + 7$&lt;/strong&gt; &lt;strong&gt;取余&lt;/strong&gt; 的结果。如果最大积为 &lt;strong&gt;负数&lt;/strong&gt; ，则返回 &lt;code&gt;-1&lt;/code&gt; 。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;取余是在得到最大积之后执行的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;m == grid.length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n == grid[i].length&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 &amp;lt;= m, n &amp;lt;= 15&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-4 &amp;lt;= grid[i][j] &amp;lt;= 4&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="思路"&gt;思路&lt;/h1&gt;
&lt;p&gt;首先，这是一个典型的dp问题，要求从左上角到右下角的路径乘积和最大非负积 &lt;strong&gt;取余&lt;/strong&gt; 的结果。&lt;/p&gt;
&lt;p&gt;可以使用两个和gird大小一致的数组big,sml分别存放到某个位置（i,j）的最大和最小乘积。&lt;/p&gt;
&lt;p&gt;计算时注意，最上一行没有来自上的计算，最左一行没有来自左的计算，所以计算时先初始化（0，0）位置的&lt;code&gt;big[0][0]=sml[0][0]=grid[0][0]&lt;/code&gt;,然后计算最上一行、最左一行，最后计算剩下的。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxProductPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MOD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1e9&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;max_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sml&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;min_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;MOD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;</description><content:encoded><![CDATA[<h1 id="1594-矩阵的最大非负积"><a href="https://leetcode.cn/problems/maximum-non-negative-product-in-a-matrix/description/">1594. 矩阵的最大非负积</a></h1>
<p>给你一个大小为 <code>m x n</code> 的矩阵 <code>grid</code> 。最初，你位于左上角 <code>(0, 0)</code> ，每一步，你可以在矩阵中 <strong>向右</strong> 或 <strong>向下</strong> 移动。</p>
<p>在从左上角 <code>(0, 0)</code> 开始到右下角 <code>(m - 1, n - 1)</code> 结束的所有路径中，找出具有 <strong>最大非负积</strong> 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。</p>
<p>返回 <strong>最大非负积</strong> 对 <strong>$10^9 + 7$</strong> <strong>取余</strong> 的结果。如果最大积为 <strong>负数</strong> ，则返回 <code>-1</code> 。</p>
<p><strong>注意</strong>取余是在得到最大积之后执行的。</p>
<p><strong>提示：</strong></p>
<ul>
<li><code>m == grid.length</code></li>
<li><code>n == grid[i].length</code></li>
<li><code>1 &lt;= m, n &lt;= 15</code></li>
<li><code>-4 &lt;= grid[i][j] &lt;= 4</code></li>
</ul>
<h1 id="思路">思路</h1>
<p>首先，这是一个典型的dp问题，要求从左上角到右下角的路径乘积和最大非负积 <strong>取余</strong> 的结果。</p>
<p>可以使用两个和gird大小一致的数组big,sml分别存放到某个位置（i,j）的最大和最小乘积。</p>
<p>计算时注意，最上一行没有来自上的计算，最左一行没有来自左的计算，所以计算时先初始化（0，0）位置的<code>big[0][0]=sml[0][0]=grid[0][0]</code>,然后计算最上一行、最左一行，最后计算剩下的。</p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">maxProductPath</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;&amp;</span> <span class="n">grid</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">const</span> <span class="kt">int</span> <span class="n">MOD</span> <span class="o">=</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="mi">7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="n">grid</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span> <span class="n">n</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;&gt;</span> <span class="n">big</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;&gt;</span> <span class="n">sml</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;</span><span class="p">(</span><span class="n">n</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">big</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="n">sml</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">m</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">big</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">sml</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">big</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">big</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">sml</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">big</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">m</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;</span> <span class="n">candidates</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">big</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">sml</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">*</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">big</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">sml</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">                <span class="p">};</span>
</span></span><span class="line"><span class="cl">                <span class="n">big</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="o">*</span><span class="n">max_element</span><span class="p">(</span><span class="n">candidates</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">candidates</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">                <span class="n">sml</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="o">*</span><span class="n">min_element</span><span class="p">(</span><span class="n">candidates</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">candidates</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">big</span><span class="p">[</span><span class="n">m</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">?</span> <span class="p">(</span><span class="n">big</span><span class="p">[</span><span class="n">m</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">%</span> <span class="n">MOD</span><span class="p">)</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
]]></content:encoded></item><item><title>1888. 使二进制字符串字符交替的最少反转次数</title><link>https://farmer3-c.github.io/posts/1888-/</link><pubDate>Sat, 07 Mar 2026 22:54:15 +0800</pubDate><guid>https://farmer3-c.github.io/posts/1888-/</guid><description>&lt;h1 id="1888-使二进制字符串字符交替的最少反转次数"&gt;&lt;a href="https://leetcode.cn/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/description/?envType=daily-question&amp;amp;envId=2026-03-07"&gt;1888. 使二进制字符串字符交替的最少反转次数&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;给你一个二进制字符串 &lt;code&gt;s&lt;/code&gt; 。你可以按任意顺序执行以下两种操作任意次：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;类型 1 ：删除&lt;/strong&gt; 字符串 &lt;code&gt;s&lt;/code&gt; 的第一个字符并将它 &lt;strong&gt;添加&lt;/strong&gt; 到字符串结尾。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型 2 ：选择&lt;/strong&gt; 字符串 &lt;code&gt;s&lt;/code&gt; 中任意一个字符并将该字符 &lt;strong&gt;反转&lt;/strong&gt; ，也就是如果值为 &lt;code&gt;'0'&lt;/code&gt; ，则反转得到 &lt;code&gt;'1'&lt;/code&gt; ，反之亦然。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请你返回使 &lt;code&gt;s&lt;/code&gt; 变成 &lt;strong&gt;交替&lt;/strong&gt; 字符串的前提下， &lt;strong&gt;类型 2&lt;/strong&gt; 的 &lt;strong&gt;最少&lt;/strong&gt; 操作次数 。&lt;/p&gt;
&lt;p&gt;我们称一个字符串是 &lt;strong&gt;交替&lt;/strong&gt; 的，需要满足任意相邻字符都不同。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比方说，字符串 &lt;code&gt;&amp;quot;010&amp;quot;&lt;/code&gt; 和 &lt;code&gt;&amp;quot;1010&amp;quot;&lt;/code&gt; 都是交替的，但是字符串 &lt;code&gt;&amp;quot;0100&amp;quot;&lt;/code&gt; 不是。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1 &lt;= s.length &lt;= 10^5$&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s[i]&lt;/code&gt; 要么是 &lt;code&gt;'0'&lt;/code&gt; ，要么是 &lt;code&gt;'1'&lt;/code&gt; 。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="思路"&gt;思路&lt;/h1&gt;
&lt;p&gt;首先，目的是得到&lt;code&gt;0101..&lt;/code&gt;或&lt;code&gt;1010..&lt;/code&gt;样式的字符串。&lt;/p&gt;
&lt;p&gt;类型1可以操作任意次，也就是说可以使用&lt;code&gt;s+s&lt;/code&gt;的长度为 n 的子串和目标字符串进行比较。&lt;/p&gt;
&lt;p&gt;使用cnt记录达到&lt;code&gt;0101..&lt;/code&gt;需要进行的类型2操作数，n-cnt 就是达到&lt;code&gt;0101..&lt;/code&gt;需要进行的类型2操作数。&lt;/p&gt;
&lt;p&gt;每次向右滑动一位，出滑动窗口的字符与目标字符串对应位进行比较，若不同，则cnt&amp;ndash;，因为之前记录时加入了修改用的操作数；进滑动窗口的字符与目标字符串对应位进行比较，若不同，同理，cnt++。&lt;/p&gt;
&lt;p&gt;每滑一次，更新&lt;code&gt;ans=min({ans,n-cnt,cnt})&lt;/code&gt;。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;minFlips&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;01&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cnt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;</description><content:encoded><![CDATA[<h1 id="1888-使二进制字符串字符交替的最少反转次数"><a href="https://leetcode.cn/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/description/?envType=daily-question&amp;envId=2026-03-07">1888. 使二进制字符串字符交替的最少反转次数</a></h1>
<p>给你一个二进制字符串 <code>s</code> 。你可以按任意顺序执行以下两种操作任意次：</p>
<ul>
<li><strong>类型 1 ：删除</strong> 字符串 <code>s</code> 的第一个字符并将它 <strong>添加</strong> 到字符串结尾。</li>
<li><strong>类型 2 ：选择</strong> 字符串 <code>s</code> 中任意一个字符并将该字符 <strong>反转</strong> ，也就是如果值为 <code>'0'</code> ，则反转得到 <code>'1'</code> ，反之亦然。</li>
</ul>
<p>请你返回使 <code>s</code> 变成 <strong>交替</strong> 字符串的前提下， <strong>类型 2</strong> 的 <strong>最少</strong> 操作次数 。</p>
<p>我们称一个字符串是 <strong>交替</strong> 的，需要满足任意相邻字符都不同。</p>
<ul>
<li>比方说，字符串 <code>&quot;010&quot;</code> 和 <code>&quot;1010&quot;</code> 都是交替的，但是字符串 <code>&quot;0100&quot;</code> 不是。</li>
</ul>
<p><strong>提示：</strong></p>
<ul>
<li>$1 <= s.length <= 10^5$</li>
<li><code>s[i]</code> 要么是 <code>'0'</code> ，要么是 <code>'1'</code> 。</li>
</ul>
<h1 id="思路">思路</h1>
<p>首先，目的是得到<code>0101..</code>或<code>1010..</code>样式的字符串。</p>
<p>类型1可以操作任意次，也就是说可以使用<code>s+s</code>的长度为 n 的子串和目标字符串进行比较。</p>
<p>使用cnt记录达到<code>0101..</code>需要进行的类型2操作数，n-cnt 就是达到<code>0101..</code>需要进行的类型2操作数。</p>
<p>每次向右滑动一位，出滑动窗口的字符与目标字符串对应位进行比较，若不同，则cnt&ndash;，因为之前记录时加入了修改用的操作数；进滑动窗口的字符与目标字符串对应位进行比较，若不同，同理，cnt++。</p>
<p>每滑一次，更新<code>ans=min({ans,n-cnt,cnt})</code>。</p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">minFlips</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">string</span> <span class="n">tar</span> <span class="o">=</span> <span class="s">&#34;01&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">cnt</span> <span class="o">+=</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">tar</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="mi">2</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">ans</span> <span class="o">=</span> <span class="n">min</span><span class="p">({</span><span class="n">cnt</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="n">cnt</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">cnt</span> <span class="o">-=</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">tar</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="mi">2</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="n">cnt</span> <span class="o">+=</span> <span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">tar</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">2</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="n">ans</span> <span class="o">=</span> <span class="n">min</span><span class="p">({</span><span class="n">ans</span><span class="p">,</span> <span class="n">cnt</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="n">cnt</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
]]></content:encoded></item><item><title>2266. 统计打字方案数</title><link>https://farmer3-c.github.io/posts/2266/</link><pubDate>Fri, 06 Mar 2026 00:07:01 +0800</pubDate><guid>https://farmer3-c.github.io/posts/2266/</guid><description>&lt;h1 id="2266-统计打字方案数"&gt;&lt;a href="https://leetcode.cn/problems/count-number-of-texts/"&gt;2266. 统计打字方案数&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Alice 在给 Bob 用手机打字。数字到字母的 &lt;strong&gt;对应&lt;/strong&gt; 如下图所示。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://pic.leetcode.cn/1722224025-gsUAIv-image.png"&gt;&lt;/p&gt;
&lt;p&gt;为了 &lt;strong&gt;打出&lt;/strong&gt; 一个字母，Alice 需要 &lt;strong&gt;按&lt;/strong&gt; 对应字母 &lt;code&gt;i&lt;/code&gt; 次，&lt;code&gt;i&lt;/code&gt; 是该字母在这个按键上所处的位置。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比方说，为了按出字母 &lt;code&gt;'s'&lt;/code&gt; ，Alice 需要按 &lt;code&gt;'7'&lt;/code&gt; 四次。类似的， Alice 需要按 &lt;code&gt;'5'&lt;/code&gt; 两次得到字母  &lt;code&gt;'k'&lt;/code&gt; 。&lt;/li&gt;
&lt;li&gt;注意，数字 &lt;code&gt;'0'&lt;/code&gt; 和 &lt;code&gt;'1'&lt;/code&gt; 不映射到任何字母，所以 Alice &lt;strong&gt;不&lt;/strong&gt; 使用它们。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但是，由于传输的错误，Bob 没有收到 Alice 打字的字母信息，反而收到了 &lt;strong&gt;按键的字符串信息&lt;/strong&gt; 。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比方说，Alice 发出的信息为 &lt;code&gt;&amp;quot;bob&amp;quot;&lt;/code&gt; ，Bob 将收到字符串 &lt;code&gt;&amp;quot;2266622&amp;quot;&lt;/code&gt; 。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;给你一个字符串 &lt;code&gt;pressedKeys&lt;/code&gt; ，表示 Bob 收到的字符串，请你返回 Alice &lt;strong&gt;总共可能发出多少种文字信息&lt;/strong&gt; 。&lt;/p&gt;
&lt;p&gt;由于答案可能很大，将它对 $10^9 + 7$ &lt;strong&gt;取余&lt;/strong&gt; 后返回。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;提示：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1 &lt;= pressedKeys.length &lt;= 10^5$&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pressedKeys&lt;/code&gt; 只包含数字 &lt;code&gt;'2'&lt;/code&gt; 到 &lt;code&gt;'9'&lt;/code&gt; 。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="题解"&gt;题解&lt;/h1&gt;
&lt;p&gt;首先，这是一个动态规划问题，接收的字符串 &lt;code&gt;pressedKeys&lt;/code&gt; 可以被分割成多个子问题，每个子问题都是一个子字符串，子字符串为同样字符。&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="2266-统计打字方案数"><a href="https://leetcode.cn/problems/count-number-of-texts/">2266. 统计打字方案数</a></h1>
<p>Alice 在给 Bob 用手机打字。数字到字母的 <strong>对应</strong> 如下图所示。</p>
<p><img loading="lazy" src="https://pic.leetcode.cn/1722224025-gsUAIv-image.png"></p>
<p>为了 <strong>打出</strong> 一个字母，Alice 需要 <strong>按</strong> 对应字母 <code>i</code> 次，<code>i</code> 是该字母在这个按键上所处的位置。</p>
<ul>
<li>比方说，为了按出字母 <code>'s'</code> ，Alice 需要按 <code>'7'</code> 四次。类似的， Alice 需要按 <code>'5'</code> 两次得到字母  <code>'k'</code> 。</li>
<li>注意，数字 <code>'0'</code> 和 <code>'1'</code> 不映射到任何字母，所以 Alice <strong>不</strong> 使用它们。</li>
</ul>
<p>但是，由于传输的错误，Bob 没有收到 Alice 打字的字母信息，反而收到了 <strong>按键的字符串信息</strong> 。</p>
<ul>
<li>比方说，Alice 发出的信息为 <code>&quot;bob&quot;</code> ，Bob 将收到字符串 <code>&quot;2266622&quot;</code> 。</li>
</ul>
<p>给你一个字符串 <code>pressedKeys</code> ，表示 Bob 收到的字符串，请你返回 Alice <strong>总共可能发出多少种文字信息</strong> 。</p>
<p>由于答案可能很大，将它对 $10^9 + 7$ <strong>取余</strong> 后返回。</p>
<p><strong>提示：</strong></p>
<ul>
<li>$1 <= pressedKeys.length <= 10^5$</li>
<li><code>pressedKeys</code> 只包含数字 <code>'2'</code> 到 <code>'9'</code> 。</li>
</ul>
<h1 id="题解">题解</h1>
<p>首先，这是一个动态规划问题，接收的字符串 <code>pressedKeys</code> 可以被分割成多个子问题，每个子问题都是一个子字符串，子字符串为同样字符。</p>
<p>结果为每个子问题的答案相乘并取模。</p>
<p>按键可以映射的字母数量决定子问题的动态规划状态转移方程。</p>
<p>按键 <code>'2'</code> 到 <code>'6'</code> 每个按键最多可以映射 3 个字母：</p>
<p>$dp[i] = dp[i-1] + dp[i-2] + dp[i-3]$</p>
<p>按键 <code>'7'</code> 和 <code>'9'</code> 每个按键最多可以映射 4 个字母，状态转移方程为：</p>
<p>$dp[i] = dp[i-1] + dp[i-2] + dp[i-3] + dp[i-4]$</p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">mod</span> <span class="o">=</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="mi">7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;</span> <span class="n">v3</span><span class="p">,</span> <span class="n">v4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="nf">f3</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">v3</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">a</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">v3</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">v3</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">v3</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">v3</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">v3</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">3</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">v3</span><span class="p">[</span><span class="n">a</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="nf">f4</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">v4</span><span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">a</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">v4</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">v4</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">v4</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">v4</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">v4</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="n">v4</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">4</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">v4</span><span class="p">[</span><span class="n">a</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="nf">countTexts</span><span class="p">(</span><span class="n">string</span> <span class="n">pressedKeys</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">k</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="kt">long</span> <span class="kt">long</span> <span class="n">ans</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">pressedKeys</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">si</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">v3</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">si</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">v4</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">si</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">v3</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">v3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">v3</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">v3</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">v4</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">v4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">v4</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">v4</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">v4</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">char</span> <span class="n">c</span> <span class="o">=</span> <span class="n">pressedKeys</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">while</span> <span class="p">(</span><span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">&amp;&amp;</span> <span class="n">pressedKeys</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">j</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span><span class="p">,</span> <span class="n">kv</span> <span class="o">=</span> <span class="n">c</span> <span class="o">-</span> <span class="sc">&#39;0&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">k</span><span class="p">[</span><span class="n">kv</span><span class="p">]</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">ans</span> <span class="o">=</span> <span class="n">ans</span> <span class="o">*</span> <span class="p">(</span><span class="n">f3</span><span class="p">(</span><span class="n">cnt</span><span class="p">))</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">ans</span> <span class="o">=</span> <span class="n">ans</span> <span class="o">*</span> <span class="p">(</span><span class="n">f4</span><span class="p">(</span><span class="n">cnt</span><span class="p">))</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="n">i</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<blockquote>
<p>这题前几个月做过，一开始没做出来，现在重新做了一遍。但是又没做出来，忘记了， 这也许就是错误局部性吧，一开始就做错的，后面很可能也会出错，一开始做对的话，后面也大概率会做对。要经常做，才能记住。</p>
</blockquote>
]]></content:encoded></item><item><title>博客网站 自动更新</title><link>https://farmer3-c.github.io/posts/blog-auto-update/</link><pubDate>Mon, 16 Feb 2026 23:46:44 +0800</pubDate><guid>https://farmer3-c.github.io/posts/blog-auto-update/</guid><description>&lt;h2 id="问题-1如何让网站自动更新无需手动刷新"&gt;问题 1：如何让网站自动更新，无需手动刷新&lt;/h2&gt;
&lt;p&gt;问题描述： 添加新文章或变化后，需要手动刷新才能看到更新&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;添加了 Jekyll Livereload 支持（ npm run start:live ）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置了 Service Worker 自动更新检测&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;添加了 BrowserSync 作为可选方案
修改文件：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;package.json - 添加新脚本命令&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gruntfile.js - 配置 BrowserSync&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="问题-2还是会有刷新确认按钮"&gt;问题 2：还是会有刷新确认按钮&lt;/h2&gt;
&lt;p&gt;问题描述： 网站检测到更新时，会显示 &amp;ldquo;Content updated. REFRESH&amp;rdquo; 按钮，需要手动点击&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;修改 sw-registration.js ，移除手动刷新提示，改为直接自动刷新
修改文件：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;js/sw-registration.js - 移除 createSnackbar 调用，直接使用 location.reload()&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="问题-3网站不停自动更新无限循环"&gt;问题 3：网站不停自动更新（无限循环）&lt;/h2&gt;
&lt;p&gt;问题描述： 打开网站后不停自动刷新&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;移除了自动刷新逻辑&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;改用 Stale-While-Revalidate 策略：先显示缓存，后台更新&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户下次访问时自然看到新内容
修改文件：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;sw.js - 移除 UPDATE_FOUND 消息发送&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;js/sw-registration.js - 移除自动刷新&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="问题-4删除的文章仍在网站上显示"&gt;问题 4：删除的文章仍在网站上显示&lt;/h2&gt;
&lt;p&gt;问题描述： 从仓库删除的文章，网站上还能看到&lt;/p&gt;
&lt;p&gt;解决方案：&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="问题-1如何让网站自动更新无需手动刷新">问题 1：如何让网站自动更新，无需手动刷新</h2>
<p>问题描述： 添加新文章或变化后，需要手动刷新才能看到更新</p>
<p>解决方案：</p>
<ul>
<li>
<p>添加了 Jekyll Livereload 支持（ npm run start:live ）</p>
</li>
<li>
<p>配置了 Service Worker 自动更新检测</p>
</li>
<li>
<p>添加了 BrowserSync 作为可选方案
修改文件：</p>
</li>
<li>
<p>package.json - 添加新脚本命令</p>
</li>
<li>
<p>Gruntfile.js - 配置 BrowserSync</p>
</li>
</ul>
<h2 id="问题-2还是会有刷新确认按钮">问题 2：还是会有刷新确认按钮</h2>
<p>问题描述： 网站检测到更新时，会显示 &ldquo;Content updated. REFRESH&rdquo; 按钮，需要手动点击</p>
<p>解决方案：</p>
<ul>
<li>
<p>修改 sw-registration.js ，移除手动刷新提示，改为直接自动刷新
修改文件：</p>
</li>
<li>
<p>js/sw-registration.js - 移除 createSnackbar 调用，直接使用 location.reload()</p>
</li>
</ul>
<h2 id="问题-3网站不停自动更新无限循环">问题 3：网站不停自动更新（无限循环）</h2>
<p>问题描述： 打开网站后不停自动刷新</p>
<p>解决方案：</p>
<ul>
<li>
<p>移除了自动刷新逻辑</p>
</li>
<li>
<p>改用 Stale-While-Revalidate 策略：先显示缓存，后台更新</p>
</li>
<li>
<p>用户下次访问时自然看到新内容
修改文件：</p>
</li>
<li>
<p>sw.js - 移除 UPDATE_FOUND 消息发送</p>
</li>
<li>
<p>js/sw-registration.js - 移除自动刷新</p>
</li>
</ul>
<h2 id="问题-4删除的文章仍在网站上显示">问题 4：删除的文章仍在网站上显示</h2>
<p>问题描述： 从仓库删除的文章，网站上还能看到</p>
<p>解决方案：</p>
<ul>
<li>
<p>优化 Service Worker 策略，HTML 页面优先从网络获取</p>
</li>
<li>
<p>检测到 404 时自动从缓存中删除</p>
</li>
<li>
<p>更新缓存版本，清理旧缓存
修改文件：</p>
</li>
<li>
<p>sw.js - 实现智能缓存策略，导航请求优先网络</p>
</li>
</ul>
<h2 id="问题-5导航栏显示文章标题">问题 5：导航栏显示文章标题</h2>
<p>问题描述： 导航栏出现了文章标题（&ldquo;编译实践Lv1. main 函数&rdquo;）</p>
<p>根本原因：</p>
<ul>
<li>
<p>之前误将一篇博客文章放到了 css/ 文件夹</p>
</li>
<li>
<p>那篇文章有 layout: post ，被 Jekyll 当作页面处理</p>
</li>
<li>
<p>导航栏循环显示所有有 title 的页面
解决方案：</p>
</li>
<li>
<p>彻底解决方案： 硬编码导航栏，只显示固定页面（Home、About、Archive）</p>
</li>
<li>
<p>从 git 历史中彻底移除误放的文章</p>
</li>
<li>
<p>清理临时文件
修改文件：</p>
</li>
<li>
<p>_includes/nav.html - 硬编码导航链接，移除循环</p>
</li>
<li>
<p>删除了 css/2026-02-15-lv1-main-.md</p>
</li>
</ul>
<h2 id="问题-6about-和-archive-页面-404">问题 6：About 和 Archive 页面 404</h2>
<p>问题描述： 点击导航栏的 About 和 Archive 跳转到 /about.html 和 /archive.html ，显示 404</p>
<p>原因：</p>
<ul>
<li>
<p>博客使用 permalink: pretty 配置</p>
</li>
<li>
<p>正确的 URL 应该是 /about/ 和 /archive/ （带斜杠）
解决方案：</p>
</li>
<li>
<p>修改导航链接，使用正确的 pretty permalink 格式
修改文件：</p>
</li>
<li>
<p>_includes/nav.html - 链接改为 /about/ 和 /archive/</p>
</li>
</ul>
<h2 id="-最终效果总结">📊 最终效果总结</h2>
<table>
	<thead>
			<tr>
					<th>功能</th>
					<th>状态</th>
					<th>说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>导航栏</td>
					<td>✅ 正常</td>
					<td>只显示 Home、About、Archive</td>
			</tr>
			<tr>
					<td>About 页面</td>
					<td>✅ 正常</td>
					<td>访问 /about/</td>
			</tr>
			<tr>
					<td>Archive 页面</td>
					<td>✅ 正常</td>
					<td>访问 /archive/</td>
			</tr>
			<tr>
					<td>Service Worker</td>
					<td>✅ 优化</td>
					<td>Stale-While-Revalidate 策略</td>
			</tr>
			<tr>
					<td>缓存管理</td>
					<td>✅ 智能</td>
					<td>HTML 优先网络，404 自动清理</td>
			</tr>
			<tr>
					<td>本地开发</td>
					<td>✅ 支持</td>
					<td>npm run start:live 自动刷新</td>
			</tr>
	</tbody>
</table>
<h2 id="-所有修改的文件">🗂️ 所有修改的文件</h2>
<ol>
<li>package.json - 添加脚本命令和依赖</li>
<li>Gruntfile.js - 配置 BrowserSync</li>
<li>js/sw-registration.js - 移除自动刷新</li>
<li>sw.js - 智能缓存策略，多次版本更新（v1→v2→v3→v4→v5）</li>
<li>_config.yml - 更新 exclude 列表</li>
<li>_includes/nav.html - 硬编码导航，修复链接格式</li>
</ol>
]]></content:encoded></item><item><title>编译实践Lv0. 环境配置</title><link>https://farmer3-c.github.io/posts/lv0-/</link><pubDate>Sat, 14 Feb 2026 00:08:02 +0800</pubDate><guid>https://farmer3-c.github.io/posts/lv0-/</guid><description>&lt;h1 id="目的"&gt;目的&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;配置实验环境的 Docker 容器, 并学习 Docker 的基本使用方法.&lt;/li&gt;
&lt;li&gt;认识编译实践中用到的编译器中间表示: Koopa IR.&lt;/li&gt;
&lt;li&gt;认识编译实践中开发的编译器的目标架构: RISC-V.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="配置实验环境的-docker-容器-并学习-docker-的基本使用方法"&gt;配置实验环境的 Docker 容器, 并学习 Docker 的基本使用方法.&lt;/h2&gt;
&lt;h3 id="安装docker-desktop"&gt;安装Docker Desktop&lt;/h3&gt;
&lt;h3 id="使用docker"&gt;使用docker&lt;/h3&gt;
&lt;h4 id="一镜像相关常用命令"&gt;一、镜像相关常用命令&lt;/h4&gt;
&lt;p&gt;镜像是容器的 “模板”，所有容器都基于镜像创建，这部分是基础操作。&lt;/p&gt;
&lt;h5 id="1-拉取镜像下载到本地"&gt;1. 拉取镜像（下载到本地）&lt;/h5&gt;
&lt;p&gt;如果本地没有该镜像，先从 Docker 仓库拉取（如果是私有仓库，需先&lt;code&gt;docker login&lt;/code&gt;）：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;powershell&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 拉取指定镜像（格式：docker pull 镜像名:标签，latest是默认标签可省略）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;pull&lt;/span&gt; &lt;span class="n"&gt;maxxing&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;compiler-dev&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 简写（省略latest，效果同上）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;pull&lt;/span&gt; &lt;span class="n"&gt;maxxing&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;compiler-dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;作用：把远程仓库的&lt;code&gt;maxxing/compiler-dev&lt;/code&gt;镜像下载到本地，后续创建容器无需重复下载；&lt;/li&gt;
&lt;li&gt;场景：首次使用该镜像、需要更新镜像版本时。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="2-查看本地镜像"&gt;2. 查看本地镜像&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;powershell&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 查看所有本地镜像（重点看REPOSITORY、TAG、IMAGE ID）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 过滤查看指定镜像（只显示maxxing/compiler-dev）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="n"&gt;maxxing&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;compiler-dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;输出示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REPOSITORY TAG IMAGE ID CREATED SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;maxxing/compiler-dev latest 5bcecbbe34b6 3 months ago 4.14GB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;场景：确认镜像是否已下载、查看镜像 ID / 大小等信息。&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="目的">目的</h1>
<ul>
<li>配置实验环境的 Docker 容器, 并学习 Docker 的基本使用方法.</li>
<li>认识编译实践中用到的编译器中间表示: Koopa IR.</li>
<li>认识编译实践中开发的编译器的目标架构: RISC-V.</li>
</ul>
<h2 id="配置实验环境的-docker-容器-并学习-docker-的基本使用方法">配置实验环境的 Docker 容器, 并学习 Docker 的基本使用方法.</h2>
<h3 id="安装docker-desktop">安装Docker Desktop</h3>
<h3 id="使用docker">使用docker</h3>
<h4 id="一镜像相关常用命令">一、镜像相关常用命令</h4>
<p>镜像是容器的 “模板”，所有容器都基于镜像创建，这部分是基础操作。</p>
<h5 id="1-拉取镜像下载到本地">1. 拉取镜像（下载到本地）</h5>
<p>如果本地没有该镜像，先从 Docker 仓库拉取（如果是私有仓库，需先<code>docker login</code>）：</p>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 拉取指定镜像（格式：docker pull 镜像名:标签，latest是默认标签可省略）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">pull</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 简写（省略latest，效果同上）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">pull</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>作用：把远程仓库的<code>maxxing/compiler-dev</code>镜像下载到本地，后续创建容器无需重复下载；</li>
<li>场景：首次使用该镜像、需要更新镜像版本时。</li>
</ul>
<h5 id="2-查看本地镜像">2. 查看本地镜像</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 查看所有本地镜像（重点看REPOSITORY、TAG、IMAGE ID）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">images</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 过滤查看指定镜像（只显示maxxing/compiler-dev）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">images</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p>输出示例：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line"><span class="cl">REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
</span></span><span class="line"><span class="cl">maxxing/compiler-dev   latest    5bcecbbe34b6   3 months ago   4.14GB
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>场景：确认镜像是否已下载、查看镜像 ID / 大小等信息。</p>
</li>
</ul>
<h5 id="3-查看镜像详情">3. 查看镜像详情</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 查看镜像的详细信息（创建时间、作者、启动命令等）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">inspect</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 简化查看：只提取镜像的默认启动命令 </span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">inspect</span> <span class="p">-</span><span class="n">-format</span><span class="p">=</span><span class="s1">&#39;{{.Config.Cmd}}&#39;</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>场景：排查镜像默认启动命令、确认镜像配置是否符合预期。</li>
</ul>
<h5 id="4-删除镜像">4. 删除镜像</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 删除指定镜像（需确保无容器关联，否则加-f强制删除）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">rmi</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 或用镜像ID删除（更精准）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">rmi</span> <span class="n">5bcecbbe34b6</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>注意：如果有容器使用该镜像，需先删除容器（参考下文 “删除容器” 命令）；</li>
<li>场景：清理无用镜像、释放磁盘空间。</li>
</ul>
<h4 id="二容器相关常用命令基于-maxxingcompiler-dev-创建容器">二、容器相关常用命令（基于 maxxing/compiler-dev 创建容器）</h4>
<p>容器是镜像的 “运行实例”，这部分是使用镜像的核心操作。</p>
<h5 id="1-创建并启动容器">1. 创建并启动容器</h5>
<p>这是最常用的命令，直接创建并进入容器，避免启动后退出：</p>
<p>powershell</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 方式1：临时交互（推荐测试用，退出容器即停止）</span>
</span></span><span class="line"><span class="cl"><span class="c"># -it：交互终端，/bin/sh：适配Alpine镜像（无bash），--name：自定义容器名（避免随机名称）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="n">-it</span> <span class="p">-</span><span class="n">-name</span> <span class="nb">compiler-dev</span><span class="n">-container</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 方式2：后台运行（长期使用，可随时进入）</span>
</span></span><span class="line"><span class="cl"><span class="c"># -d：后台运行，--restart=always：容器开机自启（可选）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="n">-d</span> <span class="n">-it</span> <span class="p">-</span><span class="n">-name</span> <span class="nb">compiler-dev</span><span class="n">-container</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 方式3：映射端口/目录（映射本地目录到容器）</span>
</span></span><span class="line"><span class="cl"><span class="c"># -v：本地目录:Docker容器目录（实现文件共享），-p：本地端口:容器端口（网络映射）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="n">-it</span> <span class="n">-v</span> <span class="n">D:</span><span class="p">\</span><span class="n">DockerData</span><span class="p">\</span><span class="n">code</span><span class="err">:</span><span class="p">/</span><span class="n">root</span><span class="p">/</span><span class="n">code</span> <span class="n">-p</span> <span class="mf">8080</span><span class="err">:</span><span class="mf">80</span> <span class="p">-</span><span class="n">-name</span> <span class="nb">compiler-dev</span><span class="n">-container</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p>参数说明：</p>
<ul>
<li><code>-i</code>：保持输入交互；<code>-t</code>：分配伪终端；<code>-d</code>：后台运行；</li>
<li><code>--name</code>：给容器起固定名称（方便后续操作，比如<code>compiler-dev-container</code>）；</li>
<li><code>-v</code>：目录挂载（本地<code>D:\DockerData\code</code>和容器<code>/root/code</code>双向同步）；</li>
<li><code>-p</code>：端口映射（访问本地 8080 端口等价于访问容器 80 端口）；</li>
</ul>
</li>
<li>
<p>场景：</p>
<ul>
<li>临时测试镜像：用方式 1；</li>
<li>长期运行服务：用方式 2；</li>
<li>需要读写本地文件 / 暴露端口：用方式 3。</li>
</ul>
</li>
</ul>
<h5 id="2-查看容器状态">2. 查看容器状态</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 查看运行中的容器</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="nb">ps
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 查看所有容器（包括已停止的）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="nb">ps </span><span class="n">-a</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 只查看指定容器的状态（用容器名/ID）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="nb">ps </span><span class="n">-a</span> <span class="p">-</span><span class="n">-filter</span> <span class="s2">&#34;name=compiler-dev-container&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p>输出关键字段：</p>
<ul>
<li><code>STATUS</code>：<code>Up X minutes</code>（运行中）/<code>Exited (0) X minutes ago</code>（已退出）；</li>
<li><code>NAMES</code>：容器名（compiler-dev-container）；</li>
<li><code>CONTAINER ID</code>：容器 ID（比如 37dadd02cbf2）；</li>
</ul>
</li>
<li>
<p>场景：确认容器是否运行、查找容器 ID / 名称。</p>
</li>
</ul>
<h5 id="3-进入运行中的容器">3. 进入运行中的容器</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 进入后台运行的容器</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">exec</span> <span class="n">-it</span> <span class="nb">compiler-dev</span><span class="n">-container</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 或用容器ID进入（比如容器ID是37dadd02cbf2）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">exec</span> <span class="n">-it</span> <span class="n">37dadd02cbf2</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>注意：必须确保容器处于 “Up” 状态（运行中），否则会提示 “container is not running”；</li>
<li>场景：在运行中的容器内执行命令、操作文件。</li>
</ul>
<h5 id="4-启动--停止--重启容器">4. 启动 / 停止 / 重启容器</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 启动已停止的容器（用容器名/ID）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="nb">start compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 停止运行中的容器</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">stop</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 重启容器（先停止再启动）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">restart</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p>场景：</p>
<ul>
<li>容器意外停止：用<code>docker start</code>重启；</li>
<li>调整容器配置后：用<code>docker restart</code>生效；</li>
<li>不需要容器运行时：用<code>docker stop</code>停止（释放资源）。</li>
</ul>
</li>
</ul>
<h5 id="5-查看容器日志排查问题">5. 查看容器日志（排查问题）</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 查看容器的全部日志</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">logs</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 实时查看日志（类似Linux tail -f）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">logs</span> <span class="o">-f</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 查看最新100行日志</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">logs</span> <span class="p">-</span><span class="n">-tail</span><span class="p">=</span><span class="mf">100</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>场景：容器启动失败、运行异常时，通过日志排查原因（比如命令执行错误、文件缺失）。</li>
</ul>
<h5 id="6-删除容器">6. 删除容器</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 先停止容器，再删除（推荐）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">stop</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="nb">rm compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 强制删除运行中的容器（不推荐，可能丢失数据）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="nb">rm </span><span class="o">-f</span> <span class="nb">compiler-dev</span><span class="n">-container</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 批量删除所有已停止的容器（清理垃圾）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">container</span> <span class="n">prune</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>场景：容器不再使用、需要重新创建容器时。</li>
</ul>
<h5 id="7挂载目录">7.挂载目录</h5>
<ul>
<li>场景：需要在容器内读写本地文件时，通过目录挂载实现（比如<code>-v D:\DockerData\code:/root/code</code>）。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 挂载本地目录到容器（读写模式）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="n">-it</span> <span class="n">-v</span> <span class="n">D:</span><span class="p">\</span><span class="n">DockerData</span><span class="p">\</span><span class="n">code</span><span class="err">:</span><span class="p">/</span><span class="n">root</span><span class="p">/</span><span class="n">code</span> <span class="p">-</span><span class="n">-name</span> <span class="nb">compiler-dev</span><span class="n">-container</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 挂载本地目录到容器（只读模式）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="n">-it</span> <span class="n">-v</span> <span class="n">D:</span><span class="p">\</span><span class="n">DockerData</span><span class="p">\</span><span class="n">code</span><span class="err">:</span><span class="p">/</span><span class="n">root</span><span class="p">/</span><span class="n">code</span><span class="err">:</span><span class="n">ro</span> <span class="p">-</span><span class="n">-name</span> <span class="nb">compiler-dev</span><span class="n">-container</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span><span class="err">:</span><span class="n">latest</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 基于maxxing/compiler-dev镜像创建名为mycp的交互式容器，挂载Windows D盘指定目录到容器/root/sysy-make-template，容器退出后自动删除并进入Shell交互界面</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="n">-it</span> <span class="p">-</span><span class="n">-rm</span> <span class="p">-</span><span class="n">-name</span> <span class="n">mycp</span> <span class="n">-v</span> <span class="p">/</span><span class="n">d</span><span class="p">/</span><span class="n">githubprojects</span><span class="p">/</span><span class="nb">sysy-make</span><span class="n">-template:</span><span class="p">/</span><span class="n">root</span><span class="p">/</span><span class="nb">sysy-make</span><span class="n">-template</span> <span class="n">maxxing</span><span class="p">/</span><span class="nb">compiler-dev</span> <span class="p">/</span><span class="n">bin</span><span class="p">/</span><span class="n">sh</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="三运维管理常用命令">三、运维管理常用命令</h4>
<h5 id="1-查看-docker-系统信息">1. 查看 Docker 系统信息</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 查看Docker整体信息（版本、镜像/容器数量、存储驱动等）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">info</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 查看Docker版本</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">version</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>场景：排查 Docker 环境问题、确认版本兼容性。</li>
</ul>
<h5 id="2-清理-docker-垃圾释放磁盘空间">2. 清理 Docker 垃圾（释放磁盘空间）</h5>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 清理所有无用的镜像、容器、网络、缓存（安全）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">system</span> <span class="n">prune</span> <span class="n">-a</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 只清理镜像缓存（保留镜像/容器）</span>
</span></span><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">builder</span> <span class="n">prune</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>注意：<code>docker system prune -a</code>会删除未使用的镜像，执行前确认无需保留。</li>
</ul>
<h4 id="总结">总结</h4>
<p>以<code>maxxing/compiler-dev:latest</code>为例，核心常用命令可归纳为 3 类：</p>
<ol>
<li><strong>镜像操作</strong>：<code>docker pull</code>（拉取）→ <code>docker images</code>（查看）→ <code>docker inspect</code>（详情）→ <code>docker rmi</code>（删除）；</li>
<li><strong>容器操作</strong>：<code>docker run -it</code>（创建启动）→ <code>docker ps</code>（查看状态）→ <code>docker exec -it</code>（进入容器）→ <code>docker start/stop</code>（启停）→ <code>docker rm</code>（删除）；</li>
<li><strong>运维操作</strong>：<code>docker logs</code>（查日志）→ <code>docker system prune</code>（清理垃圾）。</li>
</ol>
<p>关键提醒：针对该镜像（Alpine 系统），创建容器时必须指定<code>/bin/sh</code>（而非<code>/bin/bash</code>），且加<code>-it</code>参数，否则容器会启动后立刻退出。</p>
<h3 id="使用powershell">使用powershell</h3>
<h4 id="切换目录的正确写法">切换目录的正确写法</h4>
<p>如果要切换到 C 盘根目录，正确命令有两种：</p>
<p><strong>powershell</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 方法1：完整路径（最规范，推荐）</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd </span><span class="n">C:</span><span class="p">\</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 方法2：简写（PowerShell支持的盘符切换方式）</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd </span><span class="n">C:</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>其他常用的目录切换规范：</p>
<p>powershell</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="c"># 切换到上级目录</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd </span><span class="p">..</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 切换到用户主目录（比如C:\Users\你的用户名）</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd </span><span class="p">~</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 切换到带空格的目录（必须用引号包裹）</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd </span><span class="s2">&#34;C:\Program Files&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 切换到指定子目录（比如C盘下的Temp文件夹）</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd </span><span class="n">C:</span><span class="p">\</span><span class="n">Temp</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="powershell-命令的通用规范">PowerShell 命令的通用规范</h4>
<ul>
<li><strong>路径区分大小写吗？</strong>：不区分（Windows 系统特性），<code>cd C:\temp</code> 和 <code>cd C:\Temp</code> 效果一样。</li>
<li><strong>特殊字符处理</strong>：路径含空格 / 特殊符号（如<code>&amp;</code>、<code>(</code>）时，必须用双引号<code>&quot;&quot;</code>包裹。</li>
<li><strong>命令别名</strong>：PowerShell 兼容部分 DOS/CMD 别名（比如<code>cd</code>等价于<code>Set-Location</code>，<code>dir</code>等价于<code>Get-ChildItem</code>），但推荐优先用完整命令（更易读）。</li>
<li><strong>执行脚本 / 程序</strong>：当前目录下的脚本需要加<code>./</code>，比如<code>./test.ps1</code>（直接写<code>test.ps1</code>会报错）。</li>
</ul>
<h4 id="推荐的-powershell-学习--参考网站">推荐的 PowerShell 学习 / 参考网站</h4>
<ol>
<li>
<p><strong>微软官方文档（最权威）</strong></p>
<ul>
<li>地址：<a href="https://learn.microsoft.com/zh-cn/powershell/">https://learn.microsoft.com/zh-cn/powershell/</a></li>
<li>优势：全中文、覆盖基础到高级、示例丰富，包含命令参考、语法规范、最佳实践，是新手入门的首选。</li>
</ul>
</li>
<li>
<p><strong>PowerShell Gallery（命令 / 模块库）</strong></p>
<ul>
<li>地址：<a href="https://www.powershellgallery.com/">https://www.powershellgallery.com/</a></li>
<li>优势：可以查找官方 / 社区维护的 PowerShell 模块，附带使用示例，解决实际场景问题（比如文件处理、系统管理）。</li>
</ul>
</li>
<li>
<p><strong>SS64（速查手册）</strong></p>
<ul>
<li>地址：<a href="https://ss64.com/ps/">https://ss64.com/ps/</a></li>
<li>优势：按字母排序的 PowerShell 命令速查表，每个命令都有简洁的语法、示例，适合快速查阅（支持中英文）。</li>
</ul>
</li>
<li>
<p><strong>GitHub PowerShell 社区</strong></p>
<ul>
<li>地址：<a href="https://github.com/PowerShell/PowerShell">https://github.com/PowerShell/PowerShell</a></li>
<li>优势：查看 PowerShell 源码、提问题、看社区贡献的示例脚本，适合进阶学习。</li>
</ul>
</li>
</ol>
<h2 id="认识编译实践中用到的编译器中间表示-koopa-ir">认识编译实践中用到的编译器中间表示: Koopa IR.</h2>
<h3 id="运行hello-world">运行hello world</h3>
<h4 id="具体环境">具体环境</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># cat /etc/os-release</span>
</span></span><span class="line"><span class="cl"><span class="nv">PRETTY_NAME</span><span class="o">=</span><span class="s2">&#34;Ubuntu 24.04.3 LTS&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">NAME</span><span class="o">=</span><span class="s2">&#34;Ubuntu&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">VERSION_ID</span><span class="o">=</span><span class="s2">&#34;24.04&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">VERSION</span><span class="o">=</span><span class="s2">&#34;24.04.3 LTS (Noble Numbat)&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">VERSION_CODENAME</span><span class="o">=</span>noble
</span></span><span class="line"><span class="cl"><span class="nv">ID</span><span class="o">=</span>ubuntu
</span></span><span class="line"><span class="cl"><span class="nv">ID_LIKE</span><span class="o">=</span>debian
</span></span><span class="line"><span class="cl"><span class="nv">HOME_URL</span><span class="o">=</span><span class="s2">&#34;https://www.ubuntu.com/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">SUPPORT_URL</span><span class="o">=</span><span class="s2">&#34;https://help.ubuntu.com/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">BUG_REPORT_URL</span><span class="o">=</span><span class="s2">&#34;https://bugs.launchpad.net/ubuntu/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">PRIVACY_POLICY_URL</span><span class="o">=</span><span class="s2">&#34;https://www.ubuntu.com/legal/terms-and-policies/privacy-policy&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">UBUNTU_CODENAME</span><span class="o">=</span>noble
</span></span><span class="line"><span class="cl"><span class="nv">LOGO</span><span class="o">=</span>ubuntu-logo
</span></span></code></pre></td></tr></table>
</div>
</div><table>
	<thead>
			<tr>
					<th>参数名</th>
					<th>具体值</th>
					<th>含义解释</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>PRETTY_NAME</code></td>
					<td>&ldquo;Ubuntu 24.04.3 LTS&rdquo;</td>
					<td><strong>友好显示名称</strong>：最直观的系统版本描述，告诉你这是 Ubuntu 24.04.3 长期支持版（LTS）</td>
			</tr>
			<tr>
					<td><code>NAME</code></td>
					<td>&ldquo;Ubuntu&rdquo;</td>
					<td><strong>系统发行版名称</strong>：明确这是 Ubuntu 系统（而非 Debian/CentOS 等）</td>
			</tr>
			<tr>
					<td><code>VERSION_ID</code></td>
					<td>&ldquo;24.04&rdquo;</td>
					<td><strong>核心版本号</strong>：Ubuntu 的版本号规则是「年份。月份」，24.04 代表 2024 年 4 月发布的版本，这是系统的核心标识，安装软件时主要参考这个</td>
			</tr>
			<tr>
					<td><code>VERSION</code></td>
					<td>&ldquo;24.04.3 LTS (Noble Numbat)&rdquo;</td>
					<td><strong>完整版本信息</strong>： \- 24.04.3：24.04 版本的第 3 次更新维护版 \- LTS：Long Term Support（长期支持版），Ubuntu LTS 版本会提供 5 年的安全更新和维护 \- Noble Numbat：该版本的开发代号（每代 Ubuntu 都有动物代号）</td>
			</tr>
			<tr>
					<td><code>VERSION_CODENAME</code></td>
					<td>noble</td>
					<td><strong>版本代号（简写）</strong>：对应上面的 Noble Numbat，简写为 noble，在配置软件源、安装特定版本软件时可能会用到</td>
			</tr>
			<tr>
					<td><code>ID</code></td>
					<td>ubuntu</td>
					<td><strong>系统唯一标识</strong>：标准的系统 ID，脚本 / 程序中会用这个判断系统类型（比如判断是否是 Ubuntu）</td>
			</tr>
			<tr>
					<td><code>ID_LIKE</code></td>
					<td>debian</td>
					<td><strong>亲缘系统</strong>：Ubuntu 基于 Debian 开发，所以包管理器（apt）、系统架构和 Debian 一致，这也是为什么 Ubuntu 能用 Debian 的很多软件源</td>
			</tr>
			<tr>
					<td><code>HOME_URL</code></td>
					<td><a href="https://www.ubuntu.com/">https://www.ubuntu.com/</a></td>
					<td>Ubuntu 官方主页地址</td>
			</tr>
			<tr>
					<td><code>SUPPORT_URL</code></td>
					<td><a href="https://help.ubuntu.com/">https://help.ubuntu.com/</a></td>
					<td>Ubuntu 官方帮助文档地址</td>
			</tr>
			<tr>
					<td><code>BUG_REPORT_URL</code></td>
					<td><a href="https://bugs.launchpad.net/ubuntu/">https://bugs.launchpad.net/ubuntu/</a></td>
					<td>Ubuntu 官方 bug 反馈平台地址</td>
			</tr>
			<tr>
					<td><code>PRIVACY_POLICY_URL</code></td>
					<td><a href="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy">https://www.ubuntu.com/legal/terms-and-policies/privacy-policy</a></td>
					<td>Ubuntu 隐私政策地址</td>
			</tr>
			<tr>
					<td><code>UBUNTU_CODENAME</code></td>
					<td>noble</td>
					<td><strong>Ubuntu 专属版本代号</strong>：和 VERSION\_CODENAME 一致，是 Ubuntu 特有的标识，作用相同</td>
			</tr>
			<tr>
					<td><code>LOGO</code></td>
					<td>ubuntu-logo</td>
					<td>系统默认 logo 标识（主要用于图形界面，容器中一般用不到）</td>
			</tr>
	</tbody>
</table>
<h4 id="步骤">步骤</h4>
<p>把一个 Koopa IR 程序保存在了文件 hello.koopa 中
hello.koopa :</p>
<pre tabindex="0"><code class="language-koopa" data-lang="koopa">// SysY 中的 `putch` 函数的声明.
decl @putch(i32)

// 一个用来输出字符串 (其实是整数数组) 的函数.
// 函数会扫描输入的数组, 将数组中的整数视作 ASCII 码, 并作为字符输出到屏幕上,
// 遇到 0 时停止扫描.
fun @putstr(@arr: *i32) {
%entry:
  jump %loop_entry(@arr)

// Koopa IR 采用基本块参数代替 SSA 形式中的 Phi 函数.
// 当然这部分内容并不在实践要求的必选内容之中, 你无需过分关注.
%loop_entry(%ptr: *i32):
  %cur = load %ptr
  br %cur, %loop_body, %end

%loop_body:
  call @putch(%cur)
  %next = getptr %ptr, 1
  jump %loop_entry(%next)

%end:
  ret
}

// 字符串 &#34;Hello, world!\n\0&#34;.
global @str = alloc [i32, 15], {
  72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 10, 0
}

// `main` 函数, 程序的入口.
fun @main(): i32 {
%entry:
  %str = getelemptr @str, 0
  call @putstr(%str)
  ret 0
}
</code></pre><p>运行</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">koopac hello.koopa <span class="p">|</span> llc --filetype<span class="o">=</span>obj -o hello.o
</span></span><span class="line"><span class="cl">clang hello.o -L<span class="nv">$CDE_LIBRARY_PATH</span>/native -lsysy -o hello
</span></span><span class="line"><span class="cl">./hello
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="什么是-koopa-ir">什么是 Koopa IR</h3>
<blockquote>
<p>Koopa IR 是一种专为北京大学编译原理课程实践设计的教学用的中间表示 (IR), 它在设计上类似 LLVM IR, 但简化了很多内容, 方便大家上手和理解.</p>
<p>同时, 我们为 Koopa IR 开发了对应的框架 (koopa 和 libkoopa), 大家在使用 C/C++/Rust 编程时, 可以直接调用框架的接口, 实现 Koopa IR 的生成/解析/转换.</p>
<p>Koopa IR 是一种强类型的 IR, IR 中的所有值 (Value) 和函数 (Function) 都具备类型 (Type). 这种设计避免了一些 IR 定义上的模糊之处, 例如之前的教学用 IR 完全不区分整数变量和数组变量, 很容易出现混淆; 同时可以在生成 IR 之前就确定 IR 中存在的部分问题, 例如将任意整数作为内存地址并向其中存储数据.</p>
<p>Koopa IR 中, 基本块 (basic block) 必须是显式定义的. 即, 在描述函数内的指令时, 你必须把指令按照基本块分组, 每个基本块结尾的指令只能是分支/跳转/函数返回指令之一. 在 IR 的数据结构表示上, 指令也会被按照基本块分类. 这很大程度上方便了 IR 的优化, 因为许多优化算法都是在基本块的基础上对程序进行分析/变换的.</p>
<p>Koopa IR 还是一种 SSA 形式的 IR. 虽然这部分内容在课程实践中并非必须掌握, 但考虑到有些同学可能希望在课程实践的要求上, 做出一个更完备, 更强大的编译器, 我们将 Koopa IR 设计成了同时兼容非 SSA 形式和 SSA 形式的样子. 基于 SSA 形式下的 Koopa IR, 你可以开展更多复杂且有效的编译优化.</p>
</blockquote>
<blockquote>
<p>&mdash; 引自 <a href="https://pku-minic.github.io/online-doc/#/lv0-env-config/koopa?id=%e6%9c%ac%e5%9c%b0%e8%bf%90%e8%a1%8c-koopa-ir">北大编译实践在线文档</a></p>
</blockquote>
<ul>
<li>
<p>LLVM IR（Intermediate Representation）: 是LLVM编译器架构中的一种中间表示形式，它充当编译器前端和后端之间的桥梁。LLVM IR设计为与特定目标机器无关，使得编译器能够支持多种源语言并为多种目标生成代码。LLVM IR在编译过程中起到至关重要的作用，因为它是大多数目标无关优化发生的地方。</p>
</li>
<li>
<p>SSA形式（Static Single Assignment Form）: 是一种程序表示形式。SSA形式要求每个变量在程序中只能被赋值一次，这意味着每个变量的定义（def）和使用（use）关系非常明确。变量的生命周期从第一次定义到最后一次使用，这种清晰的结构使得编译器能够更容易地进行数据流分析和优化。</p>
</li>
</ul>
<h3 id="认识编译实践中开发的编译器的目标架构-risc-v">认识编译实践中开发的编译器的目标架构: RISC-V.</h3>
<blockquote>
<p>在编译实践中, 你将开发一个生成 RISC-V 汇编的编译器. 那么首先, 什么是 RISC-V?</p>
<p>RISC-V, 读作 “risk-five”, 是由加州大学伯克利分校设计并推广的第五代 RISC 指令系统体系结构 (ISA). RISC-V 没有任何历史包袱, 设计简洁, 高效低能耗, 且高度模块化——最主要的, 它还是一款完全开源的 ISA.</p>
<p>RISC-V 的指令系统由基础指令系统 (base instruction set) 和指令系统扩展 (extension) 构成. 每个 RISC-V 处理器必须实现基础指令系统, 同时可以支持若干扩展. 常用的基础指令系统有两种:</p>
<ul>
<li><code>RV32I</code>: 32 位整数指令系统.</li>
<li><code>RV64I</code>: 64 位整数指令系统. 兼容 <code>RV32I</code>.</li>
</ul>
<p>常用的标准指令系统扩展包括:</p>
<ul>
<li><code>M</code> 扩展: 包括乘法和除法相关的指令.</li>
<li><code>A</code> 扩展: 包括原子内存操作相关的指令.</li>
<li><code>F</code> 扩展: 包括单精度浮点操作相关的指令.</li>
<li><code>D</code> 扩展: 包括双精度浮点操作相关的指令.</li>
<li><code>C</code> 扩展: 包括常用指令的 16 位宽度的压缩版本.</li>
</ul>
<p>我们通常使用 <code>RV32/64I</code> + 扩展名称的方式来描述某个处理器/平台支持的 RISC-V 指令系统类型, 例如 <code>RV32IMA</code> 代表这个处理器是一个 32 位的, 支持 <code>M</code> 和 <code>A</code> 扩展的 RISC-V 处理器.</p>
<p>在课程实践中, 你的编译器将生成 <code>RV32IM</code> 范围内的 RISC-V 汇编.</p>
</blockquote>
<blockquote>
<p>&mdash; 引自 <a href="https://pku-minic.github.io/online-doc/#/lv0-env-config/riscv">北大编译实践在线文档</a></p>
</blockquote>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://pku-minic.github.io/online-doc/#/">北大编译实践在线文档</a></li>
<li><a href="https://docs.docker.top/manuals/index.htm">docker文档</a></li>
<li><a href="https://www.doubao.com/chat">doubao</a></li>
</ul>
]]></content:encoded></item><item><title>三段式数组 II</title><link>https://farmer3-c.github.io/posts/trionic-array-ii/</link><pubDate>Wed, 04 Feb 2026 08:37:14 +0800</pubDate><guid>https://farmer3-c.github.io/posts/trionic-array-ii/</guid><description>&lt;h2 id="三段式数组-ii"&gt;&lt;a href="https://leetcode.cn/problems/trionic-array-ii/description/?envType=daily-question&amp;amp;envId=2026-02-04"&gt;三段式数组 II&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;给你一个长度为 n 的整数数组 nums。&lt;/p&gt;
&lt;p&gt;三段式子数组 是一个连续子数组 nums[l&amp;hellip;r]（满足 0 &amp;lt;= l &amp;lt; r &amp;lt; n），并且存在下标 l &amp;lt; p &amp;lt; q &amp;lt; r，使得：&lt;/p&gt;
&lt;p&gt;nums[l&amp;hellip;p] 严格 递增，
nums[p&amp;hellip;q] 严格 递减，
nums[q&amp;hellip;r] 严格 递增。
请你从数组 nums 的所有三段式子数组中找出和最大的那个，并返回其 最大 和。&lt;/p&gt;
&lt;p&gt;提示:&lt;/p&gt;
&lt;p&gt;$4 &lt;= n = nums.length &lt;= 10^5$&lt;/p&gt;
&lt;p&gt;$-10^9 &lt;= nums[i] &lt;= 10^9$&lt;/p&gt;
&lt;p&gt;保证至少存在一个三段式子数组。&lt;/p&gt;
&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;p&gt;由于&lt;code&gt;l &amp;lt; p &amp;lt; q &amp;lt; r&lt;/code&gt;, $p$ 是第一段的终点和第二段的起点，$q$ 是第二段的终点和第三段的起点，我们可以通过预处理和线性扫描来解决。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;preSum[i]: 以 $i$ 结尾且满足“严格递增”的最大子数组和。&lt;/p&gt;
&lt;p&gt;条件：必须包含 $nums[i]$ 和 $nums[i-1]$。&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="三段式数组-ii"><a href="https://leetcode.cn/problems/trionic-array-ii/description/?envType=daily-question&amp;envId=2026-02-04">三段式数组 II</a></h2>
<p>给你一个长度为 n 的整数数组 nums。</p>
<p>三段式子数组 是一个连续子数组 nums[l&hellip;r]（满足 0 &lt;= l &lt; r &lt; n），并且存在下标 l &lt; p &lt; q &lt; r，使得：</p>
<p>nums[l&hellip;p] 严格 递增，
nums[p&hellip;q] 严格 递减，
nums[q&hellip;r] 严格 递增。
请你从数组 nums 的所有三段式子数组中找出和最大的那个，并返回其 最大 和。</p>
<p>提示:</p>
<p>$4 <= n = nums.length <= 10^5$</p>
<p>$-10^9 <= nums[i] <= 10^9$</p>
<p>保证至少存在一个三段式子数组。</p>
<h2 id="思路">思路</h2>
<p>由于<code>l &lt; p &lt; q &lt; r</code>, $p$ 是第一段的终点和第二段的起点，$q$ 是第二段的终点和第三段的起点，我们可以通过预处理和线性扫描来解决。</p>
<ul>
<li>
<p>preSum[i]: 以 $i$ 结尾且满足“严格递增”的最大子数组和。</p>
<p>条件：必须包含 $nums[i]$ 和 $nums[i-1]$。</p>
<p>公式：如果 $nums[i] > nums[i-1]$，$preSum[i] = \max(nums[i] + nums[i-1], preSum[i-1] + nums[i])$。</p>
</li>
<li>
<p>sufSum[i]: 以 $i$ 开头且满足“严格递增”的最大子数组和。</p>
<p>条件：必须包含 $nums[i]$ 和 $nums[i+1]$。</p>
<p>公式：如果 $nums[i] < nums[i+1]$，$sufSum[i] = \max(nums[i] + nums[i+1], sufSum[i+1] + nums[i])$。</p>
</li>
</ul>
<p>如果前面的和已经变成负数，我们应当果断抛弃旧的部分，从当前能构成的最短合法子数组重新开始计算。</p>
<p>最后，我们枚举每一个可能的递减段 $[p...q]$。只要满足 $nums[p] > nums[p+1] > \dots > nums[q]$，我们就尝试用 preSum[p] + (中间段的和) + sufSum[q] 来更新答案。</p>
<details>
<summary>点击展开/折叠</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">long</span> <span class="kt">long</span> <span class="n">maxSumTrionic</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span> <span class="o">&gt;</span> <span class="n">pre</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">LLONG_MIN</span><span class="p">),</span><span class="n">suf</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">LLONG_MIN</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">&gt;</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">long</span> <span class="kt">long</span> <span class="n">bs</span><span class="o">=</span><span class="p">(</span><span class="n">i</span><span class="o">&gt;</span><span class="mi">1</span><span class="o">&amp;&amp;</span><span class="n">pre</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">!=</span><span class="n">LLONG_MIN</span><span class="p">)</span><span class="o">?</span><span class="n">pre</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">:</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="n">pre</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">=</span><span class="n">max</span><span class="p">((</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">+</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="n">bs</span><span class="o">+</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">;</span><span class="n">i</span><span class="o">&gt;=</span><span class="mi">0</span><span class="p">;</span><span class="o">--</span><span class="n">i</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span><span class="o">&gt;</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">long</span> <span class="kt">long</span> <span class="n">bs</span><span class="o">=</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">2</span><span class="o">&lt;</span><span class="n">n</span><span class="o">&amp;&amp;</span><span class="n">suf</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span><span class="o">!=</span><span class="n">LLONG_MIN</span><span class="p">)</span><span class="o">?</span><span class="n">suf</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span><span class="o">:</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="n">suf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">=</span><span class="n">max</span><span class="p">((</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">bs</span><span class="o">+</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="kt">long</span> <span class="kt">long</span> <span class="n">ans</span><span class="o">=</span><span class="n">LLONG_MIN</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">&gt;</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]){</span>
</span></span><span class="line"><span class="cl">                <span class="kt">int</span> <span class="n">p</span><span class="o">=</span><span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="kt">long</span> <span class="kt">long</span> <span class="n">t</span><span class="o">=</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                <span class="k">while</span><span class="p">(</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="o">&amp;&amp;</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">&gt;</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]){</span>
</span></span><span class="line"><span class="cl">                    <span class="o">++</span><span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="n">t</span><span class="o">+=</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span><span class="p">(</span><span class="n">pre</span><span class="p">[</span><span class="n">p</span><span class="p">]</span><span class="o">!=</span><span class="n">LLONG_MIN</span><span class="o">&amp;&amp;</span><span class="n">suf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">!=</span><span class="n">LLONG_MIN</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                        <span class="n">ans</span><span class="o">=</span><span class="n">max</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span><span class="n">t</span><span class="o">+</span><span class="n">pre</span><span class="p">[</span><span class="n">p</span><span class="p">]</span><span class="o">+</span><span class="n">suf</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="n">nums</span><span class="p">[</span><span class="n">p</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="n">i</span><span class="o">--</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
]]></content:encoded></item><item><title>System.IO.FileLoadException: 未能加载文件或程序集“WindowsDebugLauncher……</title><link>https://farmer3-c.github.io/posts/systemiofileloadexception-windowsdebuglauncher/</link><pubDate>Tue, 03 Feb 2026 00:18:48 +0800</pubDate><guid>https://farmer3-c.github.io/posts/systemiofileloadexception-windowsdebuglauncher/</guid><description/><content:encoded><![CDATA[<h2 id="问题">问题</h2>
<p>在使用VS code编写C++程序时，运行程序时出现了以下错误：</p>
<p><code>未经处理的异常:  System.IO.FileLoadException: 未能加载文件或程序集“WindowsDebugLauncher, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。强名称验证失败。 (异常来自 HRESULT:0x8013141A) ---&gt; System.Security.SecurityException: 强名称验证失败。 (异常来自 HRESULT:0x8013141A) --- 内部异常堆栈跟踪的结尾 ---</code></p>
<p><img alt="1" loading="lazy" src="/img/in-post/vscode_wrn/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-02-03%20002612.png"></p>
<p><img alt="2" loading="lazy" src="/img/in-post/vscode_wrn/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-02-03%20002821.png"></p>
<h2 id="解决方法">解决方法</h2>
<p>异常信息的重点在：强名称验证失败。</p>
<p>这个问题主要出现在c#开发，在c#中，程序集的强名称是由程序集的公钥和版本号组成的。如果程序集的强名称验证失败，就会出现这个错误。</p>
<p>所以我想先尝试临时禁用强名称验证（仅用于调试环境），以查看是否能解决问题。</p>
<p>因为没有安装 sn.exe 工具，所以通过安装 .NET SDK 来获取 sn.exe 工具。</p>
<p>安装好后，我灵机一动，是不是可以删除VS code “PORTS”面板的进程，然后再重新运行程序，看看是否能解决问题。</p>
<p><img alt="3" loading="lazy" src="/img/in-post/vscode_wrn/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-02-03%20013105.png"></p>
<p>于是我在“PORTS”面板中 结束了所有进程 ，然后再重新打开VS code,运行程序，问题解决了。</p>
<h4 id="猜测原因">猜测原因</h4>
<blockquote>
<p>首先要明确：这个错误表面是 C++ 运行报错，实际是 VS Code 的 C/C++ 调试插件依赖的.NET 程序集出了问题，不是 C++ 代码本身有逻辑错误。</p>
</blockquote>
<blockquote>
<p>WindowsDebugLauncher是 VS Code 的 C/C++ 调试插件（ms-vscode.cpptools）在 Windows 平台上依赖的调试启动程序集（基于.NET Framework 开发），它带有强名称签名（公钥令牌正是b03f5f7f11d50a3a）。强名称验证失败的核心是：系统在加载这个程序集时，验证它的签名完整性、版本一致性、公钥合法性时出了问题，导致拒绝加载，最终调试器无法启动，抛出FileLoadException。</p>
</blockquote>
<p><strong>调试进程残留</strong></p>
<ul>
<li>
<p>之前多次启动 C++ 程序调试，部分调试进程（hello.exe、use4set.exe）没有正常退出，而是在后台残留，对应的cppdbg调试器也没有释放。</p>
</li>
<li>
<p>这些残留进程会占用WindowsDebugLauncher程序集的资源，或者导致程序集被锁定在 “已加载但未释放” 的状态，后续再次启动调试时，系统无法重新验证该程序集的强名称（相当于 “资源被占用，验证流程无法正常执行”），从而抛出验证失败错误。</p>
</li>
<li>
<p>结束 PORTS 面板所有进程、重启 VS Code 后，残留进程被清理，程序集资源被释放，后续调试时验证流程正常执行，问题解决。</p>
</li>
</ul>
]]></content:encoded></item><item><title>c++怎么用set</title><link>https://farmer3-c.github.io/posts/cset/</link><pubDate>Mon, 02 Feb 2026 13:40:27 +0800</pubDate><guid>https://farmer3-c.github.io/posts/cset/</guid><description>&lt;h2 id="什么是set"&gt;什么是set&lt;/h2&gt;
&lt;p&gt;简单来说，set是一个集合，里面的元素是唯一的，而且是有序的。&lt;/p&gt;
&lt;p&gt;set是一个容器，可以提供快速的查找、插入和删除操作,具有对数复杂度。&lt;/p&gt;
&lt;p&gt;set 通常实现为 红黑树。&lt;/p&gt;
&lt;h2 id="怎么用set"&gt;怎么用set&lt;/h2&gt;
&lt;h3 id="迭代器"&gt;迭代器&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;begin&lt;/strong&gt;      返回指向起始的迭代器&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cbegin&lt;/strong&gt; (C++11)      (public 成员函数)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;set&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// std::for_each(set.begin(), set.end(), [](int x)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// std::cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; &amp;#39; &amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;*&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;end&lt;/strong&gt;      返回指向末尾的迭代器&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cend&lt;/strong&gt; (C++11)      (public 成员函数)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;cbegin()和cend()是C++11新增的，它们返回一个const的迭代器，不能用于修改元素。&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="什么是set">什么是set</h2>
<p>简单来说，set是一个集合，里面的元素是唯一的，而且是有序的。</p>
<p>set是一个容器，可以提供快速的查找、插入和删除操作,具有对数复杂度。</p>
<p>set 通常实现为 红黑树。</p>
<h2 id="怎么用set">怎么用set</h2>
<h3 id="迭代器">迭代器</h3>
<ul>
<li><strong>begin</strong>      返回指向起始的迭代器</li>
<li><strong>cbegin</strong> (C++11)      (public 成员函数)</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// std::for_each(set.begin(), set.end(), [](int x)
</span></span></span><span class="line"><span class="cl">    <span class="c1">// {
</span></span></span><span class="line"><span class="cl">    <span class="c1">//     std::cout &lt;&lt; x &lt;&lt; &#39; &#39;;
</span></span></span><span class="line"><span class="cl">    <span class="c1">// });
</span></span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;*</span><span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>end</strong>      返回指向末尾的迭代器</li>
<li><strong>cend</strong> (C++11)      (public 成员函数)</li>
</ul>
<blockquote>
<p>cbegin()和cend()是C++11新增的，它们返回一个const的迭代器，不能用于修改元素。</p>
</blockquote>
<ul>
<li>
<p><strong>rbegin</strong>      返回指向起始的逆向迭代器</p>
</li>
<li>
<p><strong>crbegin</strong> (C++11)      (public 成员函数)</p>
</li>
<li>
<p><strong>rend</strong>      返回指向末尾的逆向迭代器</p>
</li>
<li>
<p><strong>crend</strong> (C++11)      (public 成员函数)</p>
</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">unsigned</span><span class="o">&gt;</span> <span class="n">rep</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">rep</span><span class="p">.</span><span class="n">crbegin</span><span class="p">();</span> <span class="n">it</span> <span class="o">!=</span> <span class="n">rep</span><span class="p">.</span><span class="n">crend</span><span class="p">();</span> <span class="o">++</span><span class="n">it</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="o">*</span><span class="n">it</span><span class="p">;</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="o">--</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;⏼&#34;</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h3 id="容量">容量</h3>
<ul>
<li><strong>empty</strong>      检查容器是否为空</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">numbers</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">boolalpha</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Initially, numbers.empty(): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">numbers</span><span class="p">.</span><span class="n">empty</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">numbers</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">numbers</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">19937</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;After adding elements, numbers.empty(): &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">numbers</span><span class="p">.</span><span class="n">empty</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>size</strong>      返回元素数量</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cassert&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums</span><span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">assert</span><span class="p">(</span><span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>max_size</strong>      返回元素的最大可能数量</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;locale&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="n">p</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">long</span><span class="o">&gt;</span> <span class="n">q</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// std::cout.imbue(std::locale(&#34;en_US.UTF-8&#34;));
</span></span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">uppercase</span>
</span></span><span class="line"><span class="cl">              <span class="o">&lt;&lt;</span> <span class="s">&#34;p.max_size() = &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">dec</span> <span class="o">&lt;&lt;</span> <span class="n">p</span><span class="p">.</span><span class="n">max_size</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; = 0x&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">hex</span> <span class="o">&lt;&lt;</span> <span class="n">p</span><span class="p">.</span><span class="n">max_size</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span>
</span></span><span class="line"><span class="cl">              <span class="o">&lt;&lt;</span> <span class="s">&#34;q.max_size() = &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">dec</span> <span class="o">&lt;&lt;</span> <span class="n">q</span><span class="p">.</span><span class="n">max_size</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; = 0x&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">hex</span> <span class="o">&lt;&lt;</span> <span class="n">q</span><span class="p">.</span><span class="n">max_size</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h3 id="修改器">修改器</h3>
<ul>
<li><strong>clear</strong>      清除内容</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string_view&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">print_info</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string_view</span> <span class="n">rem</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">v</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">rem</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;{ &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="nl">value</span> <span class="p">:</span> <span class="n">v</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">value</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;}</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Size=&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">v</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">container</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">print_info</span><span class="p">(</span><span class="s">&#34;Before clear: &#34;</span><span class="p">,</span> <span class="n">container</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">container</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="n">print_info</span><span class="p">(</span><span class="s">&#34;After clear: &#34;</span><span class="p">,</span> <span class="n">container</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>insert</strong>      插入元素 或节点 (C++17 起)</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cassert&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">result_1</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">assert</span><span class="p">(</span><span class="n">result_1</span><span class="p">.</span><span class="n">first</span> <span class="o">!=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> <span class="c1">// it is a valid iterator
</span></span></span><span class="line"><span class="cl">    <span class="n">assert</span><span class="p">(</span><span class="o">*</span><span class="n">result_1</span><span class="p">.</span><span class="n">first</span> <span class="o">==</span> <span class="mi">3</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">result_1</span><span class="p">.</span><span class="n">second</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;insert done</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">result_2</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">assert</span><span class="p">(</span><span class="n">result_2</span><span class="p">.</span><span class="n">first</span> <span class="o">==</span> <span class="n">result_1</span><span class="p">.</span><span class="n">first</span><span class="p">);</span> <span class="c1">// same iterator
</span></span></span><span class="line"><span class="cl">    <span class="n">assert</span><span class="p">(</span><span class="o">*</span><span class="n">result_2</span><span class="p">.</span><span class="n">first</span> <span class="o">==</span> <span class="mi">3</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">result_2</span><span class="p">.</span><span class="n">second</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;no insertion</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span><span class="p">(</span><span class="k">auto</span> <span class="nl">it</span><span class="p">:</span><span class="n">set</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">       <span class="n">std</span><span class="o">::</span> <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">it</span><span class="o">&lt;&lt;</span><span class="s">&#34;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>insert_range</strong> (C++23)      插入元素范围</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">println</span><span class="p">(</span><span class="k">auto</span><span class="p">,</span> <span class="k">auto</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">container</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="nl">elem</span> <span class="p">:</span> <span class="n">container</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">elem</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">container</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">rg</span> <span class="o">=</span> <span class="p">{</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="c1">// #ifdef __cpp_lib_containers_ranges
</span></span></span><span class="line"><span class="cl"><span class="c1">//     container.insert_range(rg);
</span></span></span><span class="line"><span class="cl"><span class="c1">// #else
</span></span></span><span class="line"><span class="cl">    <span class="n">container</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">rg</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">rg</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"><span class="c1">// #endif
</span></span></span><span class="line"><span class="cl">    <span class="n">println</span><span class="p">(</span><span class="s">&#34;{}&#34;</span><span class="p">,</span> <span class="n">container</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>emplace</strong> (C++11)      就地构造元素</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span><span class="lnt">72
</span><span class="lnt">73
</span><span class="lnt">74
</span><span class="lnt">75
</span><span class="lnt">76
</span><span class="lnt">77
</span><span class="lnt">78
</span><span class="lnt">79
</span><span class="lnt">80
</span><span class="lnt">81
</span><span class="lnt">82
</span><span class="lnt">83
</span><span class="lnt">84
</span><span class="lnt">85
</span><span class="lnt">86
</span><span class="lnt">87
</span><span class="lnt">88
</span><span class="lnt">89
</span><span class="lnt">90
</span><span class="lnt">91
</span><span class="lnt">92
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;chrono&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstddef&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;functional&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iomanip&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Dew</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">Dew</span><span class="p">(</span><span class="kt">int</span> <span class="n">_a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">_b</span><span class="p">,</span> <span class="kt">int</span> <span class="n">_c</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="o">:</span> <span class="n">a</span><span class="p">(</span><span class="n">_a</span><span class="p">),</span> <span class="n">b</span><span class="p">(</span><span class="n">_b</span><span class="p">),</span> <span class="n">c</span><span class="p">(</span><span class="n">_c</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="k">const</span> <span class="n">Dew</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">(</span><span class="n">a</span> <span class="o">&lt;</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span><span class="p">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">               <span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span> <span class="o">&amp;&amp;</span> <span class="n">b</span> <span class="o">&lt;</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span><span class="p">)</span> <span class="o">||</span>
</span></span><span class="line"><span class="cl">               <span class="p">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">a</span> <span class="o">&amp;&amp;</span> <span class="n">b</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">b</span> <span class="o">&amp;&amp;</span> <span class="n">c</span> <span class="o">&lt;</span> <span class="n">other</span><span class="p">.</span><span class="n">c</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">constexpr</span> <span class="kt">int</span> <span class="n">nof_operations</span><span class="p">{</span><span class="mi">30</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_emplace</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">Dew</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nof_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nof_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nof_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">k</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="n">set</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">k</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_insert</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">Dew</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nof_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nof_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nof_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">k</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="n">set</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">Dew</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">k</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Overload operator&lt;&lt; for std::chrono::duration
</span></span></span><span class="line"><span class="cl"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Rep</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Period</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="n">Rep</span><span class="p">,</span> <span class="n">Period</span><span class="o">&gt;&amp;</span> <span class="n">duration</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="n">duration</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;seconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">milli</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;milliseconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">micro</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;microseconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">nano</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;nanoseconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">60</span><span class="o">&gt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;minutes&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">3600</span><span class="o">&gt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hours&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;custom time unit&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">os</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">time_it</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">()</span><span class="o">&gt;</span> <span class="n">set_test</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">what</span> <span class="o">=</span> <span class="s">&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">start</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">system_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">the_size</span> <span class="o">=</span> <span class="n">set_test</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">stop</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">system_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">milli</span><span class="o">&gt;</span> <span class="n">time</span> <span class="o">=</span> <span class="n">stop</span> <span class="o">-</span> <span class="n">start</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">what</span><span class="p">.</span><span class="n">empty</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="n">the_size</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">fixed</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setprecision</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                  <span class="o">&lt;&lt;</span> <span class="n">time</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; for &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">what</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_insert</span><span class="p">,</span> <span class="s">&#34;cache warming...&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_insert</span><span class="p">,</span> <span class="s">&#34;insert&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_insert</span><span class="p">,</span> <span class="s">&#34;insert&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace</span><span class="p">,</span> <span class="s">&#34;emplace&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace</span><span class="p">,</span> <span class="s">&#34;emplace&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>emplace_hint</strong> (C++11)      使用提示就地构造元素</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;chrono&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cstddef&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;functional&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iomanip&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">int</span> <span class="n">n_operations</span> <span class="o">=</span> <span class="mi">100050</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_emplace</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">set</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_emplace_hint</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">set</span><span class="p">.</span><span class="n">emplace_hint</span><span class="p">(</span><span class="n">it</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_emplace_hint_wrong</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">n_operations</span><span class="p">;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="o">--</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">set</span><span class="p">.</span><span class="n">emplace_hint</span><span class="p">(</span><span class="n">it</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_emplace_hint_corrected</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">n_operations</span><span class="p">;</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">;</span> <span class="o">--</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">set</span><span class="p">.</span><span class="n">emplace_hint</span><span class="p">(</span><span class="n">it</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">set_emplace_hint_closest</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n_operations</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">it</span> <span class="o">=</span> <span class="n">set</span><span class="p">.</span><span class="n">emplace_hint</span><span class="p">(</span><span class="n">it</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">set</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Rep</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Period</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span><span class="o">&amp;</span> <span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="n">Rep</span><span class="p">,</span> <span class="n">Period</span><span class="o">&gt;&amp;</span> <span class="n">duration</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="n">duration</span><span class="p">.</span><span class="n">count</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;seconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">milli</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;milliseconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">micro</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;microseconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">nano</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;nanoseconds&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">60</span><span class="o">&gt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;minutes&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="nf">constexpr</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Period</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">3600</span><span class="o">&gt;&gt;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;hours&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;custom time unit&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">os</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">double</span> <span class="nf">time_it</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">size_t</span><span class="p">()</span><span class="o">&gt;</span> <span class="n">set_test</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">               <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">what</span> <span class="o">=</span> <span class="k">nullptr</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">               <span class="kt">double</span> <span class="n">ratio</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">start</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">system_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">size_t</span> <span class="n">setsize</span> <span class="o">=</span> <span class="n">set_test</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">stop</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">system_clock</span><span class="o">::</span><span class="n">now</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">milli</span><span class="o">&gt;</span> <span class="n">time</span> <span class="o">=</span> <span class="n">stop</span> <span class="o">-</span> <span class="n">start</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">what</span> <span class="o">!=</span> <span class="k">nullptr</span> <span class="o">&amp;&amp;</span> <span class="n">setsize</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setw</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">time</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; for &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">what</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; (ratio: &#34;</span>
</span></span><span class="line"><span class="cl">                  <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">ratio</span> <span class="o">==</span> <span class="mf">0.0</span> <span class="o">?</span> <span class="mf">1.0</span> <span class="o">:</span> <span class="n">ratio</span> <span class="o">/</span> <span class="n">time</span><span class="p">.</span><span class="n">count</span><span class="p">())</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">time</span><span class="p">.</span><span class="n">count</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">fixed</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setprecision</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace</span><span class="p">);</span> <span class="c1">// cache warmup
</span></span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="k">auto</span> <span class="n">x</span> <span class="o">=</span> <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace</span><span class="p">,</span> <span class="s">&#34;plain emplace&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace_hint</span><span class="p">,</span> <span class="s">&#34;emplace with correct hint&#34;</span><span class="p">,</span> <span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace_hint_wrong</span><span class="p">,</span> <span class="s">&#34;emplace with wrong hint&#34;</span><span class="p">,</span> <span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace_hint_corrected</span><span class="p">,</span> <span class="s">&#34;corrected emplace&#34;</span><span class="p">,</span> <span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">time_it</span><span class="p">(</span><span class="n">set_emplace_hint_closest</span><span class="p">,</span> <span class="s">&#34;emplace using returned iterator&#34;</span><span class="p">,</span> <span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>erase</strong>      擦除元素</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">c</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">print</span> <span class="o">=</span> <span class="p">[</span><span class="o">&amp;</span><span class="n">c</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;c = { &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">n</span> <span class="p">:</span> <span class="n">c</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">n</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;}</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">print</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Erase all odd numbers:</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">it</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="n">it</span> <span class="o">!=</span> <span class="n">c</span><span class="p">.</span><span class="n">end</span><span class="p">();)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">it</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">it</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span>
</span></span><span class="line"><span class="cl">            <span class="o">++</span><span class="n">it</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">print</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Erase 1, erased count: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">c</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Erase 2, erased count: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">c</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Erase 2, erased count: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">c</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">print</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>swap</strong>      交换内容</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;functional&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">Os</span><span class="p">,</span> <span class="k">class</span> <span class="nc">Co</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="n">Os</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">Os</span><span class="o">&amp;</span> <span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">Co</span><span class="o">&amp;</span> <span class="n">co</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;{&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="k">const</span><span class="o">&amp;</span> <span class="nl">i</span> <span class="p">:</span> <span class="n">co</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; } &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">a1</span><span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">},</span> <span class="n">a2</span><span class="p">{</span><span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">it1</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">next</span><span class="p">(</span><span class="n">a1</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">it2</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">next</span><span class="p">(</span><span class="n">a2</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">ref1</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">a1</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">int</span><span class="o">&amp;</span> <span class="n">ref2</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">a2</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">a1</span> <span class="o">&lt;&lt;</span> <span class="n">a2</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">it1</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">it2</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">ref1</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">ref2</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">a1</span><span class="p">.</span><span class="n">swap</span><span class="p">(</span><span class="n">a2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">a1</span> <span class="o">&lt;&lt;</span> <span class="n">a2</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">it1</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">it2</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">ref1</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">ref2</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// Note that every iterator referring to an element in one container before the swap
</span></span></span><span class="line"><span class="cl">    <span class="c1">// refers to the same element in the other container after the swap. Same is true
</span></span></span><span class="line"><span class="cl">    <span class="c1">// for references.
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="nc">Cmp</span> <span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">less</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">id</span><span class="p">{};</span>
</span></span><span class="line"><span class="cl">        <span class="n">Cmp</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span> <span class="o">:</span> <span class="n">id</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">Cmp</span><span class="o">&gt;</span> <span class="n">s1</span><span class="p">{</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">},</span> <span class="n">Cmp</span><span class="p">{</span><span class="mi">6</span><span class="p">}},</span> <span class="n">s2</span><span class="p">{</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">},</span> <span class="n">Cmp</span><span class="p">{</span><span class="mi">9</span><span class="p">}};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">s1</span> <span class="o">&lt;&lt;</span> <span class="n">s2</span> <span class="o">&lt;&lt;</span> <span class="n">s1</span><span class="p">.</span><span class="n">key_comp</span><span class="p">().</span><span class="n">id</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">s2</span><span class="p">.</span><span class="n">key_comp</span><span class="p">().</span><span class="n">id</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">s1</span><span class="p">.</span><span class="n">swap</span><span class="p">(</span><span class="n">s2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">s1</span> <span class="o">&lt;&lt;</span> <span class="n">s2</span> <span class="o">&lt;&lt;</span> <span class="n">s1</span><span class="p">.</span><span class="n">key_comp</span><span class="p">().</span><span class="n">id</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">s2</span><span class="p">.</span><span class="n">key_comp</span><span class="p">().</span><span class="n">id</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// So, comparator objects (Cmp) are also exchanged after the swap.
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>extract</strong> (C++17)      从容器中提取节点</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string_view&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">print</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string_view</span> <span class="n">comment</span><span class="p">,</span> <span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">comment</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="nl">datum</span> <span class="p">:</span> <span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39; &#39;</span> <span class="o">&lt;&lt;</span> <span class="n">datum</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">cont</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">print</span><span class="p">(</span><span class="s">&#34;Start:&#34;</span><span class="p">,</span> <span class="n">cont</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// Extract node handle and change key
</span></span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">nh</span> <span class="o">=</span> <span class="n">cont</span><span class="p">.</span><span class="n">extract</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">nh</span><span class="p">.</span><span class="n">value</span><span class="p">()</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">print</span><span class="p">(</span><span class="s">&#34;After extract and before insert:&#34;</span><span class="p">,</span> <span class="n">cont</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// Insert node handle back
</span></span></span><span class="line"><span class="cl">    <span class="n">cont</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">nh</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">print</span><span class="p">(</span><span class="s">&#34;End:&#34;</span><span class="p">,</span> <span class="n">cont</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>merge</strong> (C++17)      从另一个容器拼接节点</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">// print out a container
</span></span></span><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">Os</span><span class="p">,</span> <span class="k">class</span> <span class="nc">K</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="n">Os</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">Os</span><span class="o">&amp;</span> <span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">K</span><span class="o">&gt;&amp;</span> <span class="n">v</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;[&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">v</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;] {&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="n">o</span><span class="p">{};</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span><span class="o">&amp;</span> <span class="nl">e</span> <span class="p">:</span> <span class="n">v</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="n">o</span> <span class="o">?</span> <span class="s">&#34;, &#34;</span> <span class="o">:</span> <span class="p">(</span><span class="n">o</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="s">&#34; &#34;</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="n">e</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; }</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="n">p</span><span class="p">{</span><span class="sc">&#39;C&#39;</span><span class="p">,</span> <span class="sc">&#39;B&#39;</span><span class="p">,</span> <span class="sc">&#39;B&#39;</span><span class="p">,</span> <span class="sc">&#39;A&#39;</span><span class="p">},</span> 
</span></span><span class="line"><span class="cl">        <span class="n">q</span><span class="p">{</span><span class="sc">&#39;E&#39;</span><span class="p">,</span> <span class="sc">&#39;D&#39;</span><span class="p">,</span> <span class="sc">&#39;E&#39;</span><span class="p">,</span> <span class="sc">&#39;C&#39;</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;p: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;q: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">q</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">p</span><span class="p">.</span><span class="n">merge</span><span class="p">(</span><span class="n">q</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;p.merge(q);</span><span class="se">\n</span><span class="s">&#34;</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;p: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;q: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">q</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h3 id="查找">查找</h3>
<ul>
<li><strong>count</strong>      返回匹配特定键的元素数量</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;functional&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">S</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">S</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span> <span class="o">:</span> <span class="n">x</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;S{&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;} &#34;</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="n">S</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">R</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">R</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span> <span class="o">:</span> <span class="n">x</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;R{&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;} &#34;</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="n">R</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">r</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">r</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="n">R</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">r</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">i</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">R</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">r</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">t</span><span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;, &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">t</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">S</span><span class="o">&gt;</span> <span class="n">s</span><span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;, &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">s</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Two temporary objects S{1} and S{2} were created.
</span></span></span><span class="line"><span class="cl">        <span class="c1">// Comparison function object is defaulted std::less&lt;S&gt;,
</span></span></span><span class="line"><span class="cl">        <span class="c1">// which is not transparent (has no is_transparent member type).
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">R</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">less</span><span class="o">&lt;&gt;&gt;</span> <span class="n">r</span><span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;: &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">r</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;, &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">r</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;.</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// C++14 heterogeneous lookup; temporary objects were not created.
</span></span></span><span class="line"><span class="cl">        <span class="c1">// Comparator std::less&lt;void&gt; has predefined is_transparent.
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>find</strong>      查找具有特定键的元素</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">LightKey</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">FatKey</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">data</span><span class="p">[</span><span class="mi">1000</span><span class="p">];</span> <span class="c1">// a heavy blob
</span></span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">// As detailed above, the container must use std::less&lt;&gt; (or other transparent
</span></span></span><span class="line"><span class="cl"><span class="c1">// Comparator) to access these overloads. This includes standard overloads,
</span></span></span><span class="line"><span class="cl"><span class="c1">// such as comparison between std::string and std::string_view.
</span></span></span><span class="line"><span class="cl"><span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="k">const</span> <span class="n">FatKey</span><span class="o">&amp;</span> <span class="n">fk</span><span class="p">,</span> <span class="k">const</span> <span class="n">LightKey</span><span class="o">&amp;</span> <span class="n">lk</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">fk</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">lk</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="k">const</span> <span class="n">LightKey</span><span class="o">&amp;</span> <span class="n">lk</span><span class="p">,</span> <span class="k">const</span> <span class="n">FatKey</span><span class="o">&amp;</span> <span class="n">fk</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">lk</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">fk</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kt">bool</span> <span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="k">const</span> <span class="n">FatKey</span><span class="o">&amp;</span> <span class="n">fk1</span><span class="p">,</span> <span class="k">const</span> <span class="n">FatKey</span><span class="o">&amp;</span> <span class="n">fk2</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">fk1</span><span class="p">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">fk2</span><span class="p">.</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Simple comparison demo.
</span></span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">example</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">search</span> <span class="o">=</span> <span class="n">example</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> <span class="n">search</span> <span class="o">!=</span> <span class="n">example</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Found &#34;</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="o">*</span><span class="n">search</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Not found</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// Transparent comparison demo.
</span></span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="n">FatKey</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">less</span><span class="o">&lt;&gt;&gt;</span> <span class="n">example2</span><span class="p">{{</span><span class="mi">1</span><span class="p">,</span> <span class="p">{}},</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="p">{}},</span> <span class="p">{</span><span class="mi">3</span><span class="p">,</span> <span class="p">{}},</span> <span class="p">{</span><span class="mi">4</span><span class="p">,</span> <span class="p">{}}};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">LightKey</span> <span class="n">lk</span> <span class="o">=</span> <span class="p">{</span><span class="mi">2</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">search</span> <span class="o">=</span> <span class="n">example2</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">lk</span><span class="p">);</span> <span class="n">search</span> <span class="o">!=</span> <span class="n">example2</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Found &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">search</span><span class="o">-&gt;</span><span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;\n&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span>
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Not found</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>contains</strong> (C++20)      检查容器是否包含具有特定键的元素</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">example</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">x</span> <span class="p">:</span> <span class="p">{</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">})</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">example</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;: Found</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;: Not found</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p><strong>equal_range</strong>      返回与特定键匹配的元素范围</p>
</li>
<li>
<p><strong>lower_bound</strong>      返回指向第一个不小于给定键的元素的迭代器</p>
</li>
<li>
<p><strong>upper_bound</strong>      返回指向第一个大于给定键的元素的迭代器</p>
</li>
</ul>
<hr>
<h3 id="观察器">观察器</h3>
<ul>
<li><strong>key_comp</strong>      返回比较键的函数</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;utility&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">// Example module 97 key compare function
</span></span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">ModCmp</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="nf">operator</span><span class="p">()(</span><span class="kt">int</span> <span class="n">lhs</span><span class="p">,</span> <span class="kt">int</span> <span class="n">rhs</span><span class="p">)</span> <span class="k">const</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">(</span><span class="n">lhs</span> <span class="o">%</span> <span class="mi">97</span><span class="p">)</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">rhs</span> <span class="o">%</span> <span class="mi">97</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">ModCmp</span><span class="o">&gt;</span> <span class="n">cont</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">comp_func</span> <span class="o">=</span> <span class="n">cont</span><span class="p">.</span><span class="n">key_comp</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="nl">key</span> <span class="p">:</span> <span class="n">cont</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">const</span> <span class="kt">bool</span> <span class="n">before</span> <span class="o">=</span> <span class="n">comp_func</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">const</span> <span class="kt">bool</span> <span class="n">after</span> <span class="o">=</span> <span class="n">comp_func</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="n">key</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;(&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">key</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;) &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">before</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">after</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;equivalent to key (100)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">before</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;goes before key (100)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">after</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;goes after key (100)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> 
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;unreachable</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// std::unreachable();
</span></span></span><span class="line"><span class="cl">            
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li><strong>value_comp</strong>      返回比较 value_type 类型对象中的键的函数</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;utility&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="c1">// Example module 97 key compare function
</span></span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">ModCmp</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">bool</span> <span class="nf">operator</span><span class="p">()(</span><span class="kt">int</span> <span class="n">lhs</span><span class="p">,</span> <span class="kt">int</span> <span class="n">rhs</span><span class="p">)</span> <span class="k">const</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">(</span><span class="n">lhs</span> <span class="o">%</span> <span class="mi">97</span><span class="p">)</span> <span class="o">&lt;</span> <span class="p">(</span><span class="n">rhs</span> <span class="o">%</span> <span class="mi">97</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">ModCmp</span><span class="o">&gt;</span> <span class="n">cont</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="c1">// Same behaviour as key_comp()
</span></span></span><span class="line"><span class="cl">    <span class="k">auto</span> <span class="n">comp_func</span> <span class="o">=</span> <span class="n">cont</span><span class="p">.</span><span class="n">value_comp</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="n">val</span><span class="p">{</span><span class="mi">100</span><span class="p">};</span> <span class="k">const</span> <span class="kt">int</span> <span class="nl">key</span> <span class="p">:</span> <span class="n">cont</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">const</span> <span class="kt">bool</span> <span class="n">before</span> <span class="o">=</span> <span class="n">comp_func</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">const</span> <span class="kt">bool</span> <span class="n">after</span> <span class="o">=</span> <span class="n">comp_func</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">key</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">        <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Key (&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">key</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;) &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">before</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">after</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;equivalent to key (&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">before</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;goes before key (&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">after</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;goes after key (&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;)</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span>
</span></span><span class="line"><span class="cl">            <span class="n">std</span><span class="o">::</span><span class="n">unreachable</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h3 id="非成员函数">非成员函数</h3>
<ul>
<li><code>operator==</code></li>
<li><code>operator!=</code>（在 C++20 中移除）</li>
<li><code>operator&lt;</code>（在 C++20 中移除）      按字典顺序比较两个 set 的值</li>
<li><code>operator&lt;=</code> （在 C++20 中移除）     </li>
<li><code>operator&gt;</code> （在 C++20 中移除）     （函数模板）</li>
<li><code>operator&gt;=</code> （在 C++20 中移除）</li>
<li><code>operator&lt;=&gt;</code> (C++20)</li>
</ul>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://cppreference.cn/w/cpp/container/set">cppreference.cn</a></li>
</ul>
]]></content:encoded></item><item><title>将数组分成最小总代价的子数组 II</title><link>https://farmer3-c.github.io/posts/min-cost-subarray-ii/</link><pubDate>Mon, 02 Feb 2026 05:23:35 +0800</pubDate><guid>https://farmer3-c.github.io/posts/min-cost-subarray-ii/</guid><description>&lt;h2 id="将数组分成最小总代价的子数组-ii"&gt;&lt;a href="https://leetcode.cn/problems/divide-an-array-into-subarrays-with-minimum-cost-ii/description/?envType=daily-question&amp;amp;envId=2026-02-02"&gt;将数组分成最小总代价的子数组 II&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;给你一个下标从 0 开始长度为 n 的整数数组 nums 和两个 正 整数 k 和 dist 。&lt;/p&gt;
&lt;p&gt;一个数组的 代价 是数组中的 第一个 元素。比方说，[1,2,3] 的代价为 1 ，[3,4,1] 的代价为 3 。&lt;/p&gt;
&lt;p&gt;你需要将 nums 分割成 k 个 连续且互不相交 的子数组，满足 第二 个子数组与第 k 个子数组中第一个元素的下标距离 不超过 dist 。换句话说，如果你将 nums 分割成子数组 $nums[0..(i_1 - 1)], nums[i_1..(i_2 - 1)], ..., nums[i_{k-1}..(n - 1)] ，$&lt;/p&gt;
&lt;p&gt;那么它需要满足&lt;/p&gt;
&lt;p&gt;$i_{k-1} - i_1 &lt;= dist$&lt;/p&gt;
&lt;p&gt;请你返回这些子数组的 &lt;strong&gt;最小&lt;/strong&gt; 总代价。&lt;/p&gt;
&lt;p&gt;提示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 &amp;lt;= n &amp;lt;= 105&lt;/li&gt;
&lt;li&gt;1 &amp;lt;= nums[i] &amp;lt;= 109&lt;/li&gt;
&lt;li&gt;3 &amp;lt;= k &amp;lt;= n&lt;/li&gt;
&lt;li&gt;k - 2 &amp;lt;= dist &amp;lt;= n - 2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;p&gt;从&lt;code&gt;将 nums 分割成 k 个 连续且互不相交 的子数组&lt;/code&gt;得到&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="将数组分成最小总代价的子数组-ii"><a href="https://leetcode.cn/problems/divide-an-array-into-subarrays-with-minimum-cost-ii/description/?envType=daily-question&amp;envId=2026-02-02">将数组分成最小总代价的子数组 II</a></h2>
<p>给你一个下标从 0 开始长度为 n 的整数数组 nums 和两个 正 整数 k 和 dist 。</p>
<p>一个数组的 代价 是数组中的 第一个 元素。比方说，[1,2,3] 的代价为 1 ，[3,4,1] 的代价为 3 。</p>
<p>你需要将 nums 分割成 k 个 连续且互不相交 的子数组，满足 第二 个子数组与第 k 个子数组中第一个元素的下标距离 不超过 dist 。换句话说，如果你将 nums 分割成子数组 $nums[0..(i_1 - 1)], nums[i_1..(i_2 - 1)], ..., nums[i_{k-1}..(n - 1)] ，$</p>
<p>那么它需要满足</p>
<p>$i_{k-1} - i_1 <= dist$</p>
<p>请你返回这些子数组的 <strong>最小</strong> 总代价。</p>
<p>提示：</p>
<ul>
<li>3 &lt;= n &lt;= 105</li>
<li>1 &lt;= nums[i] &lt;= 109</li>
<li>3 &lt;= k &lt;= n</li>
<li>k - 2 &lt;= dist &lt;= n - 2</li>
</ul>
<h2 id="思路">思路</h2>
<p>从<code>将 nums 分割成 k 个 连续且互不相交 的子数组</code>得到</p>
<p>$k-2<=i_{k-1} - i_1 <= dist$</p>
<p>因为0号在划分的第一个子数组的首位，nums[0]必然累加在最后的结果中。</p>
<p>原问题就转化为了对大小为<code>n-1</code>的数组进行大小为<code>dist+1</code>的滑动窗口查找，查找窗口内前k-1小的元素的最小和。</p>
<h4 id="两个有序集合维护前-k-1-小">两个有序集合维护前 k-1 小</h4>
<ul>
<li>初始化两个有序集合 L 和 R。注意：为方便计算，把 k 减一。</li>
<li>把 nums[1] 到 nums[dist+1] 加到 L 中。</li>
<li>保留 L 最小的 k 个数，把其余数丢到 R 中。</li>
<li>从 i=dist+2 开始滑窗。</li>
<li>先把 out=nums[i−dist−1] 移出窗口：如果 out 在 L 中，就从 L 中移除，否则从 R 中移除。</li>
<li>然后把 in=nums[i] 移入窗口：如果 in 小于 L 中的最大元素，则加入 L，否则加入 R。</li>
<li>上面两步做完后，如果 L 中的元素个数小于 k（等于 k−1），则从 R 中取一个最小元素加入 L；反之，如果 L 中的元素个数大于 k（等于 k+1），则从 L 中取一个最大元素加入 R。</li>
<li>上述过程维护 L 中元素之和 sumL，取 sumL 的最小值，即为答案。</li>
</ul>
<hr>
<p><strong>参考</strong></p>
<p><a href="https://leetcode.cn/problems/divide-an-array-into-subarrays-with-minimum-cost-ii/solutions/2614067/liang-ge-you-xu-ji-he-wei-hu-qian-k-1-xi-zdzx/">灵茶山艾府</a></p>
]]></content:encoded></item><item><title>开源软件导论</title><link>https://farmer3-c.github.io/posts/open-source-intro/</link><pubDate>Wed, 28 Jan 2026 21:03:52 +0800</pubDate><guid>https://farmer3-c.github.io/posts/open-source-intro/</guid><description>&lt;h2 id="第一章开源概述"&gt;第一章：开源概述&lt;/h2&gt;
&lt;h4 id="开源是什么"&gt;开源是什么&lt;/h4&gt;
&lt;p&gt;在 20 世纪 70 年代末，Richard Stallman 在 MIT 人工智能实验室安装了一台新的打印机，当时他在那里工作，这台打印机运行专有固件。打印机出现问题时，理查德·斯托曼很沮丧，因为他无法获得打印机软件的副本并编辑代码来解决。这种挫败感时自由与开源运动的起源。&lt;/p&gt;
&lt;p&gt;对于所有人而言，开源的好处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;获取任何给定工作的源代码、配置文件和文档。&lt;/li&gt;
&lt;li&gt;自由地使用、修改和分发这些代码。&lt;/li&gt;
&lt;li&gt;摆脱厂商的恶意绑定&lt;/li&gt;
&lt;li&gt;更高的合作程度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于开源的使用者而言，他们想要达成目标不会受到制约，最大程度地发挥自己的意愿。
对于开源的贡献者而言，他们可以在不付出实际代价的情况下，为开源软件做出贡献，在自己的简历中展示自己的能力。&lt;/p&gt;
&lt;h4 id="开源历史上的-6-个关键时刻"&gt;开源历史上的 6 个关键时刻&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;RMS 和打印机
在 20 世纪 70 年代末，Richard·M·Stallman（RMS）是麻省理工学院的一名员工程序员。他的部门像当时许多大学一样，共享一台 PDP-10 计算机和一台打印机。他们遇到的一个问题是，纸经常在打印机中卡住，导致一连串的打印任务堆积在队列中，直到有人修理好卡纸问题。为了解决这个问题，麻省理工学院的员工想出了一个很棒的社会性解决方案：他们编写了打印机驱动程序的代码，以便当打印机卡住时，会向所有当前等待打印任务的人发送一条消息：&amp;ldquo;打印机卡纸了，请修理。&amp;ldquo;这样，它就不会长时间卡住。&lt;/p&gt;
&lt;p&gt;1980 年，实验室接受了一台全新的激光打印机的捐赠。然而，当斯托曼要求获取打印机驱动程序的源代码，以便重新实现社会黑客技术，让系统在纸张卡住时通知用户时，他被告知这是专有信息。他听说另一所大学的一位研究员拥有一个研究项目的源代码，当机会出现时，他请求这位同事分享——而对方拒绝时他感到震惊。他们签署了保密协议（NDA），斯托曼认为这是对黑客文化的背叛。&lt;/p&gt;
&lt;p&gt;20 世纪 70 年代末至 80 年代初，软件被视为有价值，这种软件传统上与硬件一起以源代码形式提供。越来越多的麻省理工学院研究人员开始创办软件公司，而销售软件许可证是他们商业模式的关键。保密协议和专有软件许可证成为常态，最好的程序员被从麻省理工学院等大学招聘来参与私人开发项目，在那里他们无法再分享或合作。&lt;/p&gt;
&lt;p&gt;作为对此的反应，斯托曼决定创建一个完整的操作系统，它不会剥夺用户理解其工作原理的自由，并且如果他们愿意，还可以进行修改。这就是自由软件运动的诞生。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GNU 的创建和自由软件的兴起&lt;/p&gt;
&lt;p&gt;到 1983 年底，斯托曼准备好宣布他的项目并招募支持者和助手。1983 年 9 月，他宣布了 GNU 项目的创建（GNU 代表 Gnu&amp;rsquo;s Not Unix——一个递归缩写）。该项目的目标是克隆 Unix 操作系统，以创建一个赋予用户完全自由的系统。&lt;/p&gt;
&lt;p&gt;1984 年 1 月，他开始全职从事该项目，首先创建了一个编译器系统（GCC）和各种操作系统工具。1985 年初，他发布了《GNU 宣言》，号召程序员加入，并成立了自由软件基金会以接受捐赠来支持这项工作。这份文件是自由软件运动的创始章程。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;《GNU 通用公共许可证》的编写&lt;/p&gt;
&lt;p&gt;直到 1989 年，自由软件基金会和理查德·斯托曼（RMS）编写并发布的软件都没有统一的许可证。Emacs 在 Emacs 许可证下发布，GCC 在 GCC 许可证下发布，等等；然而，在一家名为 Unipress 的公司强迫斯托曼停止分发他们从詹姆斯·高斯林（Java 之父）那里获得的 Emacs 实现版本后，他意识到需要一种保护用户自由的许可证。&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="第一章开源概述">第一章：开源概述</h2>
<h4 id="开源是什么">开源是什么</h4>
<p>在 20 世纪 70 年代末，Richard Stallman 在 MIT 人工智能实验室安装了一台新的打印机，当时他在那里工作，这台打印机运行专有固件。打印机出现问题时，理查德·斯托曼很沮丧，因为他无法获得打印机软件的副本并编辑代码来解决。这种挫败感时自由与开源运动的起源。</p>
<p>对于所有人而言，开源的好处：</p>
<ul>
<li>获取任何给定工作的源代码、配置文件和文档。</li>
<li>自由地使用、修改和分发这些代码。</li>
<li>摆脱厂商的恶意绑定</li>
<li>更高的合作程度</li>
</ul>
<p>对于开源的使用者而言，他们想要达成目标不会受到制约，最大程度地发挥自己的意愿。
对于开源的贡献者而言，他们可以在不付出实际代价的情况下，为开源软件做出贡献，在自己的简历中展示自己的能力。</p>
<h4 id="开源历史上的-6-个关键时刻">开源历史上的 6 个关键时刻</h4>
<ul>
<li>
<p>RMS 和打印机
在 20 世纪 70 年代末，Richard·M·Stallman（RMS）是麻省理工学院的一名员工程序员。他的部门像当时许多大学一样，共享一台 PDP-10 计算机和一台打印机。他们遇到的一个问题是，纸经常在打印机中卡住，导致一连串的打印任务堆积在队列中，直到有人修理好卡纸问题。为了解决这个问题，麻省理工学院的员工想出了一个很棒的社会性解决方案：他们编写了打印机驱动程序的代码，以便当打印机卡住时，会向所有当前等待打印任务的人发送一条消息：&ldquo;打印机卡纸了，请修理。&ldquo;这样，它就不会长时间卡住。</p>
<p>1980 年，实验室接受了一台全新的激光打印机的捐赠。然而，当斯托曼要求获取打印机驱动程序的源代码，以便重新实现社会黑客技术，让系统在纸张卡住时通知用户时，他被告知这是专有信息。他听说另一所大学的一位研究员拥有一个研究项目的源代码，当机会出现时，他请求这位同事分享——而对方拒绝时他感到震惊。他们签署了保密协议（NDA），斯托曼认为这是对黑客文化的背叛。</p>
<p>20 世纪 70 年代末至 80 年代初，软件被视为有价值，这种软件传统上与硬件一起以源代码形式提供。越来越多的麻省理工学院研究人员开始创办软件公司，而销售软件许可证是他们商业模式的关键。保密协议和专有软件许可证成为常态，最好的程序员被从麻省理工学院等大学招聘来参与私人开发项目，在那里他们无法再分享或合作。</p>
<p>作为对此的反应，斯托曼决定创建一个完整的操作系统，它不会剥夺用户理解其工作原理的自由，并且如果他们愿意，还可以进行修改。这就是自由软件运动的诞生。</p>
</li>
<li>
<p>GNU 的创建和自由软件的兴起</p>
<p>到 1983 年底，斯托曼准备好宣布他的项目并招募支持者和助手。1983 年 9 月，他宣布了 GNU 项目的创建（GNU 代表 Gnu&rsquo;s Not Unix——一个递归缩写）。该项目的目标是克隆 Unix 操作系统，以创建一个赋予用户完全自由的系统。</p>
<p>1984 年 1 月，他开始全职从事该项目，首先创建了一个编译器系统（GCC）和各种操作系统工具。1985 年初，他发布了《GNU 宣言》，号召程序员加入，并成立了自由软件基金会以接受捐赠来支持这项工作。这份文件是自由软件运动的创始章程。</p>
</li>
<li>
<p>《GNU 通用公共许可证》的编写</p>
<p>直到 1989 年，自由软件基金会和理查德·斯托曼（RMS）编写并发布的软件都没有统一的许可证。Emacs 在 Emacs 许可证下发布，GCC 在 GCC 许可证下发布，等等；然而，在一家名为 Unipress 的公司强迫斯托曼停止分发他们从詹姆斯·高斯林（Java 之父）那里获得的 Emacs 实现版本后，他意识到需要一种保护用户自由的许可证。</p>
<p>GNU 通用公共许可证（General Public License ）的第一个版本于 1989 年发布，它包含了 Copyleft（一个双关语——版权的反面是什么？）的价值观：你可以使用、复制、分发和修改受许可证保护的软件，但如果你进行了修改，你必须与修改后的二进制文件一起分享修改后的源代码。分享修改后软件的简单要求，再加上 1990 年代互联网的出现，使得自由软件运动的去中心化协作开发模式得以蓬勃发展。</p>
</li>
<li>
<p>&ldquo;The Cathedral and the Bazaar&rdquo;</p>
<p>到 20 世纪 90 年代中期，Linux 开始兴起，自由软件逐渐成为主流——或者用&quot;不那么边缘化&quot;来形容可能更准确。Linux 内核的开发方式完全不同于以往所见，而且非常成功。在内核社区的混乱中，秩序和快速发展的项目应运而生。</p>
<p>1997 年，Eric·S·Raymond发表了具有里程碑意义的文章《大教堂与集市》，比较和对比了 GCC 和 Linux 内核的开发方法论及社会结构，并分享了他在 Fetchmail 项目上使用&quot;集市&quot;开发模型的个人经验。雷蒙德在这篇文章中描述的许多原则后来成为敏捷开发和 DevOps 运动的核心——&ldquo;尽早发布、频繁发布&rdquo;、代码重构以及将用户视为共同开发者，这些都是现代软件开发的基础。</p>
<p>这篇论文被认为将自由软件推广给了更广泛的受众，并说服了当时软件公司的领导层，让他们认为以自由软件许可证发布软件是正确的做法。雷蒙德后来在创造&quot;开源&quot;这一术语和创建开源研究所方面发挥了重要作用。</p>
<p>《大教堂与集市》被认为是 1998 年 Netscape 网络浏览器 Mozilla 源代码发布的关键文件。当时，这是首个将现有、广泛使用的桌面软件作为自由软件发布的大规模发布，使其进一步引起了公众的关注。</p>
</li>
<li>
<p>开源</p>
<p>早在 1985 年，RMS 本人就意识到用来描述软件自由的&quot;free&quot;一词具有模糊性。在《GNU 宣言》中，他将&quot;give away&quot;和&quot;for free&quot;视为容易混淆零价格和用户自由的概念。当自由软件在 1990 年代末进入主流受众时，&ldquo;Free as in freedom&rdquo;、&ldquo;Speech not beer&quot;等口号很常见，但许多知名社区人物认为需要一个更易于大众理解的概念术语。</p>
<p>1998 年， Netscape发布了 Mozilla 的源代码，包括 Eric Raymond、Bruce Perens、Michael Tiemann、Jon &ldquo;Maddog&rdquo; Hall 以及许多自由软件界的杰出人物在内的一群人聚集在帕洛阿尔托讨论一个替代术语。Christine Peterson 提出了&quot;开放源码&quot;这一术语来描述自由软件，后来 Bruce Perens 和 Eric Raymond 共同创立了开放源码研究所。他们认为，与专有软件的根本区别在于源代码的可用性，因此这是品牌推广中应该首先强调的重点。</p>
<p>同年，在 Tim O&rsquo;Reilly 组织的一次峰会上，当时自由软件领域一些最具影响力的人物聚集在一起，讨论各种新的自由软件品牌。最终，“开源”战胜了“源码”，开源开始被社区中的许多项目所采用。</p>
<p>然而，也存在一些分歧。理查德·斯托曼和自由软件基金会继续倡导“自由软件”这一术语，因为他们认为，与专有软件的根本区别在于用户自由，而源代码的可用性只是实现这一目标的手段。斯托曼认为，如果将重点从自由上移开，未来源代码可能会开放，但软件用户将无法享有修改软件的自由。随着网络部署的软件即服务以及嵌入设备的开源固件的出现，这场争论至今仍在继续。</p>
</li>
<li>
<p>企业对开源的投资—VA Linux、Red Hat、IBM</p>
<p>20 世纪 90 年代末，一系列备受瞩目的事件推动了自由和开源软件的专业化进程显著加速。其中，1999 年 VA Linux 和 Red Hat 的首次公开募股是最引人注目的事件。这两家公司作为上市公司在首日股价均大幅上涨，证明了开源软件如今已进入商业化并走向主流。</p>
<p>1999 年，IBM 宣布通过投资 10 亿美元支持 Linux 的开发，使传统企业用户使用它变得风险更低。次年，Sun Microsystems 发布了其跨平台办公套件 StarOffice 的源代码，并创建了 OpenOffice.org 项目。</p>
<p>硅谷对开源项目的巨额资金投入、华尔街对围绕开源软件建立的年轻公司的关注，以及像 IBM 和 Sun Microsystems 这样的科技巨头所带来的市场信誉，共同促成了开源的大规模采用，以及接纳了有助于其繁荣的开发模式，这些因素导致了 Linux 和开源在当今科技行业的统治地位。</p>
</li>
</ul>
<h4 id="为什么开源">为什么开源</h4>
<ul>
<li>
<p>微观经济动机</p>
<p>无论你是个人、公司、小企业、非营利组织还是政府机构，开源都符合你的最佳利益：</p>
<ul>
<li>
<p><strong>将开发者从低价值工作转移到高价值工作</strong>- 我们在开源中常说，所有简单的问题都已经被解决了。博客、内容管理和操作系统都是具有既定（且主流）开源解决方案的问题，仅举几例。虽然你的开发者可以花时间重新发明开源社区已经完善了的轮子，但使用世界上最好的轮子要远远好得多，尤其是当这个轮子对你来说没有成本时。这使开发者能够专注于尚未解决的问题，这些问题的类型是独特的，并且能为你的组织使命增加价值。为什么不站在科技巨人的肩膀上呢？</p>
</li>
<li>
<p><strong>降低 总拥有成本</strong>（TCO）- 与封闭源和专有软件相比，使用开源软件能带来更低的总拥有成本。采用开源软件通常具有更低的初始成本（因为软件通常免费或成本较低），并将成本中心从许可证（运营支出）转移到定制和实施（资本支出）。培训、维护和支持等额外成本是沉没成本。无论软件是开源还是封闭源，你都需要支付这些费用。对于商业现成软件（COTS），这些成本通常已经包含在许可证中。开源的独特之处在于，你不需要为使用底层知识产权支付费用。</p>
</li>
<li>
<p><strong>只要有足够多的人看，所有的错误都会变得浅显</strong>（林纳斯定律）—— 实践证明，开源软件通常比其专有或替代品产生更好的质量。当你编写闭源软件时，只有那些恰好受雇于发布该软件公司的开发者（或者更有可能的是，他们雇佣来构建软件的独立承包商）才能潜在地检测、诊断、分派处理和解决软件错误。开源提供了三个优势：首先，你有机会利用全世界最佳开发者的知识，而不仅仅是某个组织雇佣的开发者。其次，潜在贡献者的数量以及潜在的知识库要大得多。最后，开源软件会适应各种使用场景，而不仅仅是发布者最初打算的用途，这使得它比传统的、预测性的质量保证过程能更快地暴露错误和边缘情况。</p>
</li>
<li>
<p><strong>现代软件开发实践</strong> - 开源软件并不仅仅是“发布”的代码。你很难找到遵循过时、瀑布式或僵化的命令控制式开发理念的开源项目，这些理念在许多大型官僚机构中仍然普遍存在。由于开源项目具有分布式和不受政策或技术债务束缚的特点，它们几乎必然采用现代软件开发工作流程。这些工作流程是电子化的（意味着流程自然被捕获和展示）、异步的（意味着决策不受时间和地点的限制），并且无锁的（意味着贡献者可以快速实验而无需事先批准）。这三个工作流程特征意味着更快的开发周期和更频繁的发布，而不会牺牲质量。</p>
</li>
<li>
<p><strong>开源是未来</strong>——现在但凡能拿到风投、有投资价值的初创公司，几乎没有不做开源的，至少部分业务靠开源，很多甚至主要靠开源。开源不是一种潮流，也不是加州一群嬉皮士在传递扎染笔记本电脑，就像他们传递违禁品一样。开源是现代组织，以及越来越多的传统组织构建软件的方式。未来五年或十年，技术格局将更协作、更开放而非封闭的观点，将越来越难以成立。就连传统上最坚决反对开源的微软，也开源了其主要的开发框架（苹果和 Swift 也是如此）。如今，从 IBM、SAP 到 Adobe 等所有技术巨头都积极参与开源社区。说“开源是未来”略有失实。开源已经赢得了胜利。</p>
</li>
<li>
<p><strong>按自己的时间修复</strong> - 只要软件是由人类编写的，错误和安全漏洞就是不可避免的。当专有软件项目中发现漏洞时，你必须等待公司所在时区的工 作日开始，等待会议召开、任务分配和代码编写，所有这些完成之前，法律、销售和市场营销等支持团队还需要协调如何将修复程序纳入下一个定期计划发布。对于专有软件，错误和安全漏洞会影响公司底线，因此没有动力将漏洞细节广泛公开。对于开源软件，不仅更精简、更敏捷、非盈利导向的组织可以更快地行动，由于你可以访问源代码，你通常可以在自己方便的时候应用修复程序，无论是大是小，而不是在发布组织的发布周期方便的时候。</p>
</li>
</ul>
</li>
<li>
<p>宏观经济动机</p>
<p>通过结合和增强平行或相关的工作，开源使社会在产生更高质量的软件方面变得更加高效：</p>
<ul>
<li>
<p><strong>效率</strong> - 上述许多微观经济论点，在总体上具有宏观经济影响。当企业工作效率更高时，经济将生产更多（且更好）的软件，这些软件反过来又能改善人们的生活。如果你认为所有容易解决的问题都已经被解决了，那么在宏观经济层面，开源允许企业从较低层次的工作转向更高层次、尚未解决的问题。这种更高层次工作的成果往往是颠覆性的，而非迭代性的，从而创造了使经济充满活力的更替。如果每家科技公司都必须投入几年研发时间来解决同样的 5-10 个问题，这将延迟（或至少是将资本从）公司能够富有成效地生产对社会有价值的技术的能力，更不用说，它还提高了新市场进入者向成熟企业提供替代方案的成本。</p>
</li>
<li>
<p><strong>站在巨人的肩膀上</strong>——如今，创新技术，那些提升生活品质的技术，并非凭空创造。即使是闭源技术，从你口袋里的手机到你所驾驶的汽车，再到生产它们的《财富》500 强公司，都严重依赖开源（不信？看看你手机的“设置→关于”页面）。正如代数和三角学不受私营部门版权的束缚，从而催生了从微积分到量子物理的一切，开源让开发者能够将已解决的问题视为既定，依赖自己领域之外的专家知识，并释放他们创造新发明的潜力，否则这些发明将不可能实现。</p>
</li>
<li>
<p><strong>激发思想市场</strong>——软件不过是技术知识。曾有一段时期，炼金术士会隐瞒他们的研究成果，声称这些发现是专有的。每个人都不得不通过亲身体验来学习饮用铅对人体的影响。当这些炼金术士开始分享他们的工作时，我们开始称他们为科学家，科学革命也随之诞生。数学、文学和计算机软件也是如此。两个独立工作的开发者可能会针对同一个问题提出两种解决方案，但通过对话和协作，每个人贡献自己的知识和经验，可能会发现三个、五个甚至十个解决方案，而社会因此变得更好。</p>
</li>
</ul>
</li>
<li>
<p>道德动机
开源的正式名称是自由/免费开源软件（free/libre open source software）。因此，开源的动机具有强烈的道德成分：</p>
<ul>
<li><strong>自由如言论，而非如啤酒</strong>—开源软件并非没有成本。当开源软件被称为“免费”时，它指的是软件消费者所获得的权利，而非他们必须支付的成本。例如，Adobe 的 Flash 播放器在经济意义上是免费的，但仍然是专有（非自由）软件（和格式）的核心。具体来说，自由软件指的是四个核心自由：运行软件的自由、研究和修改软件的自由、分发软件的自由，以及分发你的修改的自由。
</br></li>
</ul>
<p>正如自由软件运动所主张的，非自由软件存在控制用户（由出版商控制软件）的风险。这可能导致软件成为不公正权力的工具。如今，专有软件监视用户（例如，向家中报告）、限制用户（例如，数字版权管理）、审查用户（例如，企业防火墙）或利用用户（例如，不可跳过的广告）的情况并不少见。随着物联网的兴起，这一风险变得更加重要，可能会将世界变成“营销人员的互联网”或“窥探者的互联网”。自由软件将权力交还给用户，确保用户控制他们使用的软件，而不是相反。
</br></p>
<ul>
<li>
<p><strong>回馈的义务</strong> - 开源就像一个“投币取款”的软件罐子。如果你使用开源软件，无论是服务器、桌面出版应用还是软件库，你都有义务回馈社区。毕竟，如果没有他人的贡献，微宏观经济动机将不再成立，我们所熟知的开源也将不复存在。这是黄金法则，用传统哲学术语来说，是一种绝对命令。</p>
</li>
<li>
<p><strong>政府应该将其开发成果交给为开发付费的人民</strong>——如果开发成本由政府支付，那么就有额外的理由将其回馈。政府通过税收来为民众提供服务。例如，美国联邦政府是根据其宪法由我们这些人民建立起来，以执行多项重要任务的。如果民众（我们这些人民）正在为软件的开发付费，那么我们理应获得我们所付费开发的成果，包括我们付费开发的软件。</p>
</li>
<li>
<p><strong>培养下一代</strong> - 如今行业内许多杰出的工程师都是通过学习开源项目成长起来的。当软件的底层代码可供审查时，消费者可以了解自己喜爱的软件是如何运作的，计算机科学课程也能分析行业尖端技术的构建方式。这为培养下一代软件工程师（如果没有开源，他们将只能猜测前代产品的内部机制）提供了极大的帮助。</p>
</li>
</ul>
</li>
<li>
<p>透明度动机</p>
<p>开源使得流程更加透明，无论是检查政府行为所需的透明度，还是私营公司软件的准政府职能。</p>
<ul>
<li>
<p><strong>展示你的工作</strong> - 随着政府越来越依赖技术来监管行业和提供公民服务，能够看到底层算法和流程对于检查政府的工作至关重要。如果使用闭源软件包来计算我的税款或分配广播频率，我如何知道这个过程，我们的过程，是公平和准确的？虽然人类流程不能被版权保护，但当是闭源时，这些流程就变成了一个黑箱，最大限度地减少了公民制衡的可能性。</p>
</li>
<li>
<p><strong>公共信任的职位</strong> - 随着私营公司生产的软件越来越多地被置于公共信任的职位，透明度义务也扩展到了私营部门。我的选票是否被投票机准确计数？当面临两难选择时，自动驾驶汽车是否遵循社区规范？例如，如果在一个犯罪现场使用闭源软件包来比较 DNA，与可以接受交叉询问的医学专家不同，那个专有算法受到版权（或专利）法的保护而不受审查。随着私营公司自动化准政府职能，至少部分特定组件的开放源代码将成为必不可少的。</p>
</li>
</ul>
</li>
<li>
<p>参与动机</p>
<p>开放源代码为软件利益相关者，包括技术和非技术方面，提供了塑造任何软件开发项目的机会：</p>
<ul>
<li>
<p><strong>直接民主</strong> - 真正的直接民主（即每位公民都对每个议题进行投票）在大多数民主国家因规模过大而不可行。同时，由于技术限制，公民也无法直接参与大多数议题。开源则改变了这一现状，它允许软件利益相关者直接参与软件开发过程（因为软件越来越多地被用来制定监管和服务提供偏好及规范）。想想购买医疗保健的过程是否令人困惑？那就提出一个议题。认为政府应该更多地使用开源软件，就提交一个拉取请求。白宫已经为许多以 IT 为中心的政策，如《数字服务手册》、HTTPS 和开放数据政策，采用了这种方式。</p>
</li>
<li>
<p><strong>用户反馈</strong> - 开源让消费者在私营部门发展过程中拥有一个结合的、强大的声音。把它想象成软件界的 Yelp。没有 Yelp，一家餐厅可以随意得罪一个顾客。最多，那些不满意的顾客可能会劝退 5-10 个潜在顾客。在一个 Yelp 时代，顾客会在选择去哪里之前阅读陌生人的评论。开源放大了软件消费者在消费者-发布者关系中的声音。更不用说，私营公司收到的反馈可以更好地为产品决策提供信息并改进整体产品。开源让公司可以直接接触到他们最狂热的顾客。</p>
</li>
</ul>
</li>
<li>
<p>个人动机</p>
<p>如果你是一名开发者（或渴望成为开发者），开源可以为你提供一条轻松（且免费）的途径，加入软件开发社区并实现个人成长：</p>
<ul>
<li>
<p><strong>学习编程</strong> - 开源是学习编程的绝佳方式。想知道你喜欢的网站是如何运作的吗？在网页浏览器中点击“查看源代码”就能为你指明方向。你可以阅读该软件的文档，甚至可能搭建一个自己的克隆版本。想了解更多？加入该框架或语言的本地交流会。更棒的是，向项目提交一个 pull 请求，修复一个小错误或添加一个新功能。虽然这其中必然涉及时间和机会成本，但所有这些都不需要准开发者直接付费，至少在软件方面是这样，而且与在专有社区中做同样的事情相比，这种方式包容性要强得多，尤其是对于外部人士而言。几乎所有非传统学术背景的当今编程学校都教授开源，这绝非偶然。</p>
</li>
<li>
<p><strong>很有趣</strong>——根据维基百科，开源是一种爱好。事实上，开源传统上被认为是业余爱好者的产物（尽管我(Ben Balter)认为现在这种情况不那么普遍了）。开源很有趣。如果你是个黑客，它就为你提供了无数不断变化的魔方，让你在周末去解决。就像谜题（无论是填字谜还是拼图）能提供小型的智力逃避一样，开源的秩序和对称性往往能成为一个代码的岩石园（尤其是对于那些对足球感到尴尬的人来说）。</p>
</li>
</ul>
</li>
</ul>
<h4 id="开源与闭源软件">开源与闭源软件</h4>
<style>
.center 
{
  width: auto;
  display: table;
  margin-left: auto;
  margin-right: auto;
}
</style>
<div class="center">
<table>
	<thead>
			<tr>
					<th>对比维度</th>
					<th>开源软件（Open Source）</th>
					<th>闭源软件（Closed Source）</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>源代码是否公开</strong></td>
					<td>完全公开，任何人可获取、阅读</td>
					<td>不公开，源码是厂商核心资产，严格保密</td>
			</tr>
			<tr>
					<td><strong>修改与定制</strong></td>
					<td>允许自由修改、二次开发、定制功能</td>
					<td>禁止修改源码，只能使用厂商提供的功能与接口</td>
			</tr>
			<tr>
					<td><strong>分发权限</strong></td>
					<td>通常允许自由复制、分发、再发布（依协议而定）</td>
					<td>禁止私自分发、逆向工程、反编译，受版权法保护</td>
			</tr>
			<tr>
					<td><strong>所有权与控制</strong></td>
					<td>版权归社区/作者，使用权归用户（依许可证）</td>
					<td>版权与控制权完全归开发公司/厂商所有</td>
			</tr>
			<tr>
					<td><strong>商业模式</strong></td>
					<td>靠服务、支持、定制、云服务、增值模块盈利</td>
					<td>靠售卖许可证、订阅、升级、技术支持收费</td>
			</tr>
			<tr>
					<td><strong>安全透明度</strong></td>
					<td>漏洞公开可见，社区共同审计、快速修复</td>
					<td>漏洞由厂商内部发现修复，公开前存在“静默期”风险</td>
			</tr>
			<tr>
					<td><strong>技术支持</strong></td>
					<td>社区支持为主，部分有商业公司提供付费支持</td>
					<td>官方技术支持、SLA、售后保障，响应更可控</td>
			</tr>
			<tr>
					<td><strong>更新与迭代</strong></td>
					<td>社区驱动，更新节奏灵活，功能迭代快</td>
					<td>厂商主导，更新节奏固定，功能发布受商业计划控制</td>
			</tr>
			<tr>
					<td><strong>厂商锁定风险</strong></td>
					<td>低，可自由迁移、fork、换服务商</td>
					<td>高，易形成 vendor lock-in，切换成本极高</td>
			</tr>
			<tr>
					<td><strong>使用成本</strong></td>
					<td>软件本身通常免费，成本主要在部署、维护、定制</td>
					<td>前期授权成本高，后期订阅/维护费持续产生</td>
			</tr>
	</tbody>
</table>
</div>
<h2 id="第二章开源许可证">第二章：开源许可证</h2>
<p>开源许可证是指符合开源定义的许可证——简而言之，它们允许软件自由使用、修改和共享。要获得开放源代码倡议组织（Open Source Initiative 简称 OSI）的批准，一个许可证必须经过开放源代码倡议组织的许可证审查流程。</p>
<p>基本上，许可协议是许可方和被许可人商定双方权利和义务的一种方式。与许可协议相关的权利和义务可以是任何事物——在法律允许的范围内。例如，许可方可能要求被许可人在使用其作品时注明其姓名。或者可以授权复制其作品，但不得以任何方式修改。甚至可以要求衍生作品在相同条款下发布，与原始作品相同。</p>
<p>另一方面，许可协议也是保护被许可人的一种方式。通过明确说明他如何使用你的作品，他不会面临意外要求因使用你的作品而支付版税或其他形式的补偿的风险。这对于你的作品采用至关重要。</p>
<h4 id="开源许可证的分类">开源许可证的分类</h4>
<p><code>International</code> : 国际</p>
<p><code>Non-Reusable</code> : 不可再使用</p>
<p><code>Other/Miscellaneous</code> : 其他</p>
<p><code>Popular / Strong</code> : 流行</p>
<p><code>Community</code> : 社区</p>
<p><code>Redundant with more popular</code> : 与流行许可证重复</p>
<p><code>Special Purpose</code> : 专用</p>
<p><code>Superseded</code> : 已被取代</p>
<p><code>Uncategorized</code> : 未分类</p>
<p><code>Voluntarily retired</code>: 自愿放弃</p>
<h4 id="开源许可证的选择">开源许可证的选择</h4>
<p>根据需要进行选择，下面可以参考的一些开源许可证的选择：</p>
<ul>
<li><a href="http://oss.ly/licdif">http://oss.ly/licdif</a></li>
<li><a href="https://choosealicense.com/">https://choosealicense.com/</a> / <a href="https://choosealicense.com/appendix/">https://choosealicense.com/appendix/</a></li>
<li><a href="https://opensource.org/licenses">https://opensource.org/licenses</a></li>
<li><a href="https://tldrlegal.com/">https://tldrlegal.com/</a></li>
<li><a href="https://opensource.guide/legal/">https://opensource.guide/legal/</a></li>
</ul>
<p>许可证将保护你的作品。将保护许可方。但也会保护你。我是指你个人。例如，通过限制许可方对其作品可能造成的损害的责任。</p>
<h2 id="第三章开源组织">第三章：开源组织</h2>
<h4 id="应该了解的开源组织">应该了解的开源组织</h4>
<p><a href="https://www.apache.org/foundation/">Apache 软件基金会</a></p>
<p>Apache 软件基金会为广泛的开源软件项目提供组织、法律和财务支持。该基金会为知识产权和财务捐赠提供了既定框架，同时限制捐助者的潜在法律风险。</p>
<p><a href="https://www.cncf.io/">云原生计算基金会</a></p>
<p>云原生计算基金会（CNCF）的使命是推动分布式计算和“云原生”系统的采用，其定义为容器封装、动态管理和微服务导向的系统。作为Linux基金会的一个项目，CNCF托管了Kubernetes云编排系统及其他云原生开源项目。</p>
<p><a href="https://digitalfreedomfund.org/">数字自由基金会</a></p>
<p>数字自由基金会每年举办活动，推广免费软件、硬件和内容。其活动包括软件自由日、文档自由日、硬件自由日和教育自由日。</p>
<p><a href="https://www.documentfoundation.org/">文档基金会</a></p>
<p>文档基金会是LibreOffice免费开源办公套件的所在地。它是一个独立、自治、精英主义的实体，由 OpenOffice.org 共同体的前领导人以德国法律（gemeinnützige rechtsfähige Stiftung des bürgerlichen Rechts）形式设立的慈善机构。</p>
<p><a href="https://www.drupal.org/association">Drupal协会</a></p>
<p>Drupal协会支持和支持Drupal内容管理软件项目。它为Drupal社区提供资金、基础设施、教育、推广、发行和在线协作。</p>
<p><a href="https://www.eclipse.org/">日蚀基金会</a></p>
<p>Eclipse基金会为我们的全球开发者和会员组织社区提供了一个友好的开源软件协作与创新环境。基金会是Eclipse IDE、Jakarta EE及开源项目的所在地，包括云和边缘应用、物联网、人工智能、汽车等的运行时、工具、规范和框架。</p>
<p><a href="https://www.fsf.org/about/">自由软件基金会</a></p>
<p>自由软件基金会（FSF）的使命是捍卫计算机用户的自由和权利。它推动“自由（即自由）软件和文档的开发与使用”，并反对数字权利管理、软件专利及其他对计算机用户自由的威胁。</p>
<p><a href="https://fsfe.org/about">欧洲自由软件基金会</a></p>
<p>欧洲自由软件基金会（FSFE）是FSF的姊妹组织。其目标是帮助人们理解自由软件如何促进自由、透明和自决。它促进自由软件的采用，鼓励人们使用和开发自由软件，并为所有人提供资源，帮助大家在欧洲进一步推广自由软件。</p>
<p><a href="https://www.gnome.org/foundation/">GNOME基金会</a></p>
<p>GNOME基金会是一个非营利组织，支持GNOME项目及其贡献者。基金会提供资源和基础设施，指导发布，决定项目中包含哪些软件，并作为项目的公众形象和声音。</p>
<p><a href="https://ev.kde.org/whatiskdeev.php">KDE电子台</a></p>
<p>KDE eingetragener Verein（德语意为“注册协会”）是一家非营利组织，代表开源KDE项目在法律和财务事务上运作。它拥有KDE商标及其他KDE社区资产，同时组织活动和获得赞助以支持KDE的发展。</p>
<p><a href="https://www.linuxfoundation.org/about">Linux 基金会</a></p>
<p>Linux 基金会成立于2000年，赞助了 Linux 创始人 Linus Torvalds 的工作，并得到了全球领先的科技公司和开发者的支持。Linux基金会是一个致力于促进Linux发展的非营利联盟。</p>
<p><a href="https://www.lpi.org/">Linux 专业学院</a></p>
<p>Linux 专业协会（LPI）成立于1999年，是一家加拿大非营利组织，致力于倡导并协助专业人士使用Linux、开源及自由软件。其宗旨是“通过使开源知识和技能认证普遍可及，为每个人创造经济和创造性的机会。”</p>
<p><a href="https://www.mozilla.org/en-US/foundation/">Mozilla基金会</a></p>
<p>Mozilla基金会致力于互联网必须始终保持为开放且可访问的全球公共资源，供所有人使用。作为一家社会企业，该基金会是Mozilla公司的唯一股东，该公司开发Firefox浏览器软件及其他开源工具。</p>
<p><a href="https://www.netbsd.org/foundation/">NetBSD</a></p>
<p>NetBSD 是一个免费且高度可移植的类 Unix 开源作系统。它适用于多种平台，从大型服务器和强大的桌面系统到手持和嵌入式设备，非常适合拯救老旧的“生命终结”硬件。</p>
<p><a href="https://www.oasis-open.org/">绿洲公开赛</a></p>
<p>OASIS Open是个人、组织和政府聚集在一起，通过开发开放代码和开放标准解决世界上一些最大的技术挑战的地方。</p>
<p><a href="https://www.open-bio.org/wiki/Main_Page">开放生物信息学基金会</a></p>
<p>开放生物信息学基金会在生物研究社区倡导开源软件。其活动包括支持会议、举办黑客马拉松，并参与谷歌代码夏季活动。</p>
<p><a href="https://www.oeconsortium.org/">开放教育联盟</a></p>
<p>开放教育联盟是一个由数百所大学及相关组织组成的全球社区，致力于推动高质量大学教育材料的免费开放数字发布，以提升教育的可及性和有效性。</p>
<p><a href="https://www.osadl.org/">开源自动化开发实验室</a></p>
<p>开源自动化开发实验室（OSADL）是一家总部位于德国的全球组织，致力于支持机械、机床和自动化行业的开源软件。OSADL代表其成员组织协调开源工业项目的开发和融资。</p>
<p><a href="https://www.osgeo.org/content/foundation/about.html">开源地理空间基金会</a></p>
<p>开源地理空间基金会（OSGeo）支持开源地理空间软件的协作开发。组织参与了与GIS相关的主要软件项目;此外，它还为开源GIS社区提供资金、组织和法律支持。</p>
<p><a href="https://opensourceforamerica.org/about-osfa/our-mission/">美国开源</a></p>
<p>美国开源组织（OSFA）致力于教育美国联邦政府的决策者了解自由和开源软件的益处。OSFA鼓励政府使用开源软件，并作为开源社区向联邦政府发声的声音。</p>
<p><a href="https://www.opensourcematters.org/">开源的重要性</a></p>
<p>开源事务（Open Source Matters，简称OSM）是一家在美国注册成立的非营利组织，旨在服务于Joomla项目的财务和法律利益。OSM定期进行自我评估，以确保对Joomla负责并以Joomla的利益为目标。</p>
<p><a href="https://www.opensource.org/">开源倡议</a></p>
<p>开源倡议（OSI）是一家非营利机构，旨在倡导开源的益处，并在开源社区中搭建桥梁。它维护开源定义并批准符合OCD的许可证。</p>
<p><a href="https://www.openstack.org/foundation">OpenStack 基金会</a>
OpenStack 基金会推动 OpenStack 云作系统的全球开发、分发和采用。作为OpenStack的全球独立基地，该基金会服务于来自全球180多个国家的6万多名个人会员。</p>
<p><a href="https://osuosl.org/about">俄勒冈州立大学（OSU）开源实验室</a></p>
<p>俄勒冈州立大学开源实验室是不断壮大、影响力高的开源社区的所在地。它托管了160多个开源项目，包括开源领导者如Apache软件基金会、Linux基金会和Drupal内容管理系统。</p>
<p><a href="https://sfconservancy.org/">软件自由保护协会</a></p>
<p>软件自由保护协会是一个非营利组织，致力于推广、改进、开发和捍卫自由、自由和开源软件（FLOSS）项目。通过提供基础设施和非开发支持服务，该组织使FLOSS开发者能够专注于他们的项目。</p>
<p><a href="https://www.softwarefreedom.org/">软件自由法律中心</a></p>
<p>软件自由法律中心为自由和开源项目提供免费法律服务，包括许可、版权、专利、商标和非营利治理，以及教育、咨询和培训。</p>
<p><a href="https://www.spi-inc.org/">公共利益下的软件</a></p>
<p>公共利益软件（SPI）是一个非营利组织，负责处理部分开源项目的非技术性行政任务，以便开发者专注于开发和分发开放硬件和软件。</p>
<h4 id="开源项目中的基础作用"><a href="https://livablesoftware.com/study-open-source-foundations/">开源项目中的基础作用</a></h4>
<hr>
<p><strong>参考</strong></p>
<p><a href="https://github.com/pingcap/talent-plan/blob/master/courses/tp101-intro-to-oss.md">Introduction to Open Source Software</a></p>
]]></content:encoded></item><item><title>go环境安装</title><link>https://farmer3-c.github.io/posts/go/</link><pubDate>Wed, 28 Jan 2026 13:17:03 +0800</pubDate><guid>https://farmer3-c.github.io/posts/go/</guid><description>&lt;h2 id="go-计算机编程语言"&gt;Go 计算机编程语言&lt;/h2&gt;
&lt;p&gt;Go（又称为Golang）是一种由Google开发的开源编程语言，于2009年首次公开发布。它旨在提供简洁、高效、可靠的软件开发解决方案。Go是一种静态强类型、编译型语言，具有很强的表达能力，得益于其并发机制，用它编写的程序能够非常有效地利用多核与联网的计算机。&lt;/p&gt;
&lt;h4 id="主要特点"&gt;主要特点&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Go语言的设计目标是将静态语言的安全性和性能与动态语言的易用性相结合。它在语言层面提供了对协程的支持，特别适合编写高并发的项目。以下是Go语言的一些主要特点：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;简洁、快速、安全：Go语言的语法接近C语言，但更简洁，编译速度非常快，且具有内置的垃圾回收功能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;并发支持：Go语言内置了轻量级进程（goroutine）、通道和select语句等并发原语，使得编写并发程序变得简单和高效。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;模块化：Go语言采用模块化的方式组织代码，易于维护和重用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;跨平台：Go语言支持跨平台编译，可以在不同的操作系统上进行开发和部署。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;在Windows中安装Go:&lt;/p&gt;
&lt;p&gt;安装包下载地址为：https://go.dev/dl/。&lt;/p&gt;
&lt;p&gt;如果打不开可以使用这个地址：https://golang.google.cn/dl/。&lt;/p&gt;
&lt;h2 id="运行第一个go程序"&gt;运行第一个go程序&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;保存为hello.go&lt;/p&gt;
&lt;h4 id="终端运行"&gt;终端运行&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go run hello.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, World!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在同一命令提示符窗口中，第一次运行这个程序时，会耗时较多，在我的电脑上大约需要2~3秒，之后再运行这个程序就会很快，但关闭这个窗口，隔一段时间下次运行情况如初。&lt;/p&gt;
&lt;p&gt;原因是这个命令会先编译 .go 文件，然后再运行编译后的可执行文件，所以第一次运行会比较慢。&lt;/p&gt;
&lt;p&gt;可以使用go build命令来编译程序，然后再运行编译后的可执行文件，这样就不会每次都重新编译了。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go build hello.go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hello, World!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="vs-code运行"&gt;VS Code运行&lt;/h4&gt;
&lt;p&gt;在VS Code中安装Go插件，然后打开hello.go文件，点击运行按钮，就可以运行这个程序了。&lt;/p&gt;
&lt;p&gt;我遇到了几个问题：&lt;/p&gt;
&lt;h6 id="1-vs-code-在安装-go-语言的核心工具gopls-和-dlv时无法连接到官方的-go-模块代理服务器proxygolangorg导致网络连接超时失败"&gt;1. VS Code 在安装 Go 语言的核心工具（gopls 和 dlv）时，无法连接到官方的 Go 模块代理服务器（proxy.golang.org），导致网络连接超时失败。&lt;/h6&gt;
&lt;p&gt;报错中有&lt;code&gt;dial tcp 142.251.45.145:443: connectex: A connection attempt failed&lt;/code&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="go-计算机编程语言">Go 计算机编程语言</h2>
<p>Go（又称为Golang）是一种由Google开发的开源编程语言，于2009年首次公开发布。它旨在提供简洁、高效、可靠的软件开发解决方案。Go是一种静态强类型、编译型语言，具有很强的表达能力，得益于其并发机制，用它编写的程序能够非常有效地利用多核与联网的计算机。</p>
<h4 id="主要特点">主要特点</h4>
<ul>
<li>
<p>Go语言的设计目标是将静态语言的安全性和性能与动态语言的易用性相结合。它在语言层面提供了对协程的支持，特别适合编写高并发的项目。以下是Go语言的一些主要特点：</p>
</li>
<li>
<p>简洁、快速、安全：Go语言的语法接近C语言，但更简洁，编译速度非常快，且具有内置的垃圾回收功能。</p>
</li>
<li>
<p>并发支持：Go语言内置了轻量级进程（goroutine）、通道和select语句等并发原语，使得编写并发程序变得简单和高效。</p>
</li>
<li>
<p>模块化：Go语言采用模块化的方式组织代码，易于维护和重用。</p>
</li>
<li>
<p>跨平台：Go语言支持跨平台编译，可以在不同的操作系统上进行开发和部署。</p>
</li>
</ul>
<h2 id="安装">安装</h2>
<p>在Windows中安装Go:</p>
<p>安装包下载地址为：https://go.dev/dl/。</p>
<p>如果打不开可以使用这个地址：https://golang.google.cn/dl/。</p>
<h2 id="运行第一个go程序">运行第一个go程序</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;fmt&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Hello, World!&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>保存为hello.go</p>
<h4 id="终端运行">终端运行</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ go run hello.go
</span></span><span class="line"><span class="cl">Hello, World!
</span></span></code></pre></td></tr></table>
</div>
</div><p>在同一命令提示符窗口中，第一次运行这个程序时，会耗时较多，在我的电脑上大约需要2~3秒，之后再运行这个程序就会很快，但关闭这个窗口，隔一段时间下次运行情况如初。</p>
<p>原因是这个命令会先编译 .go 文件，然后再运行编译后的可执行文件，所以第一次运行会比较慢。</p>
<p>可以使用go build命令来编译程序，然后再运行编译后的可执行文件，这样就不会每次都重新编译了。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ go build hello.go
</span></span><span class="line"><span class="cl">$ ./hello
</span></span><span class="line"><span class="cl">Hello, World!
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="vs-code运行">VS Code运行</h4>
<p>在VS Code中安装Go插件，然后打开hello.go文件，点击运行按钮，就可以运行这个程序了。</p>
<p>我遇到了几个问题：</p>
<h6 id="1-vs-code-在安装-go-语言的核心工具gopls-和-dlv时无法连接到官方的-go-模块代理服务器proxygolangorg导致网络连接超时失败">1. VS Code 在安装 Go 语言的核心工具（gopls 和 dlv）时，无法连接到官方的 Go 模块代理服务器（proxy.golang.org），导致网络连接超时失败。</h6>
<p>报错中有<code>dial tcp 142.251.45.145:443: connectex: A connection attempt failed</code></p>
<p>可以知道：</p>
<ul>
<li>由于网络环境限制，电脑无法访问谷歌的官方 Go 模块代理服务器</li>
<li>这是国内使用 Go 开发时非常常见的网络问题，并非代码或软件本身的故障</li>
</ul>
<p><strong>解决办法</strong></p>
<p>需要将 Go 的模块代理切换为国内的镜像源（如七牛云的 goproxy.cn），具体操作步骤如下：</p>
<p>按下 Win + R，输入 sysdm.cpl 并回车，打开系统属性，切换到「高级」标签页，点击「环境变量」</p>
<p>在「用户变量」区域，点击「新建」：
变量名：GOPROXY
变量值：https://goproxy.cn,direct</p>
<p>再新建一个变量（如果不存在）：
变量名：GO111MODULE
变量值：on
点击「确定」保存所有设置</p>
<p>重新安装 Go 工具
完成代理配置后，重启 VS Code，然后按以下步骤重新安装工具：
在 VS Code 中打开任意 .go 文件
右下角会提示「Install Go tools」，点击「Install」
或者按下 Ctrl+Shift+P（Mac 是 Cmd+Shift+P），输入 Go: Install/Update Tools
全选所有工具，点击「确定」开始安装</p>
<h6 id="2-运行时提示-initialization-failed-packagesload-error-err-exit-status-1-stderr-go-gomod-file-not-found-in-current-directory-or-any-parent-directory">2. 运行时提示：<code> &quot;initialization failed: packages.Load error: err: exit status 1: stderr: go: go.mod file not found in current directory or any parent directory&quot;</code></h6>
<p>从错误信息 go: go.mod file not found in current directory or any parent directory
可以知道：</p>
<ul>
<li>Go 1.11 及以上版本默认启用了模块（Modules） 机制，调试工具（dlv）在编译调试程序时，会要求项目必须是一个合法的 Go 模块（即存在 go.mod 文件）。</li>
<li>项目目录没有初始化 Go 模块，所以编译和调试都无法正常进行。</li>
</ul>
<p><strong>解决办法</strong></p>
<p>在项目目录下执行以下命令，初始化 Go 模块：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">go mod init &lt;module_name&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>其中，&lt;module_name&gt; 是你想要为项目指定的模块名称。</p>
<p>执行完命令后，会在项目目录下生成一个 go.mod 文件，该文件包含了项目的模块信息。</p>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://www.runoob.com/go/go-environment.html">菜鸟教程</a></li>
</ul>
]]></content:encoded></item><item><title>爬取中国工商银行人民币即期外汇牌价数据</title><link>https://farmer3-c.github.io/posts/post-2026-01-20/</link><pubDate>Tue, 20 Jan 2026 22:18:28 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2026-01-20/</guid><description>&lt;h2 id="爬取单日数据"&gt;爬取单日数据&lt;/h2&gt;
&lt;h4 id="前期准备"&gt;前期准备&lt;/h4&gt;
&lt;p&gt;我要爬取的网站是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://www.icbc.com.cn/ICBC/%e9%87%91%e8%9e%8d%e4%bf%a1%e6%81%af/%e8%a1%8c%e6%83%85%e6%95%b0%e6%8d%ae/%e4%ba%ba%e6%b0%91%e5%b8%81%e5%8d%b3%e6%9c%9f%e5%a4%96%e6%b1%87%e7%89%8c%e4%bb%b7/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数据是这样的：币种、银行买入价、银行卖出价、发布时间&lt;/p&gt;
&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://farmer3-c.github.io/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20114748.png"&gt;&lt;/p&gt;
&lt;p&gt;环境：python 3.12.2&lt;/p&gt;
&lt;h4 id="寻找网络请求接口"&gt;寻找网络请求接口&lt;/h4&gt;
&lt;p&gt;在浏览器中按F12打开开发者工具，然后点击Network，勾选 Preserve log&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;选择 Fetch / XHR&lt;/p&gt;
&lt;p&gt;&lt;code&gt;XMLHttpRequest (XHR)&lt;/code&gt; 和 &lt;code&gt;Fetch API&lt;/code&gt;都是网页向服务器发起 HTTP 请求的机制。Fetch API 是一种现代的、基于 Promise 的替代方案，用于取代老旧的、基于回调的 XHR，它提供了更简洁的语法和更适合现代网页开发的功能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;手动操作页面：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 选择一个日期（比如 2021-01-25）
点击【查询】
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Network 列表里 新出现的 POST 请求&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://farmer3-c.github.io/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20161550.png"&gt;
可以确定工商银行新版 PAPI 的“历史外汇牌价接口”：&lt;code&gt;POST https://papi.icbc.com.cn/exchanges/ns/history&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="如何使用接口"&gt;如何使用接口&lt;/h4&gt;
&lt;h6 id="请求方式"&gt;请求方式&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;POST&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Content-Type: application/json&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="请求体"&gt;请求体&lt;/h6&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;date&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2021-01-13&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;currType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;serverType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;👉 这个接口不支持“时间区间”&lt;/p&gt;
&lt;p&gt;👉 需要一天一天请求&lt;/p&gt;
&lt;h4 id="编写代码"&gt;编写代码&lt;/h4&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠代码&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://papi.icbc.com.cn/exchanges/ns/history&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Origin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://www.icbc.com.cn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Referer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://www.icbc.com.cn/ICBC/&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="si"&gt;%87%&lt;/span&gt;&lt;span class="s2"&gt;91&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="si"&gt;%9E&lt;/span&gt;&lt;span class="s2"&gt;%8D&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;4%BF%A1&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="si"&gt;%81%&lt;/span&gt;&lt;span class="s2"&gt;AF/&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;8%A1%8C&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="si"&gt;%83%&lt;/span&gt;&lt;span class="s2"&gt;85&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="si"&gt;%95%&lt;/span&gt;&lt;span class="s2"&gt;B0&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6%8D%AE/&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;4%BA%BA&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6%B0&lt;/span&gt;&lt;span class="si"&gt;%91%&lt;/span&gt;&lt;span class="s2"&gt;E5%B8&lt;/span&gt;&lt;span class="si"&gt;%81%&lt;/span&gt;&lt;span class="s2"&gt;E5%8D%B3&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6%9C&lt;/span&gt;&lt;span class="si"&gt;%9F%E&lt;/span&gt;&lt;span class="s2"&gt;5%A4&lt;/span&gt;&lt;span class="si"&gt;%96%&lt;/span&gt;&lt;span class="s2"&gt;E6%B1&lt;/span&gt;&lt;span class="si"&gt;%87%&lt;/span&gt;&lt;span class="s2"&gt;E7&lt;/span&gt;&lt;span class="si"&gt;%89%&lt;/span&gt;&lt;span class="s2"&gt;8C&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;4%BB%B7/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;date&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2021-01-13&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;currType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;serverType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h6 id="报错ssl-unsafe_legacy_renegotiation_disabled"&gt;报错：&lt;code&gt;[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED]&lt;/code&gt;&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;当前的 Python + OpenSSL 与工行 PAPI 服务器的 TLS 协商不兼容&lt;/li&gt;
&lt;li&gt;更准确地说：
请求触发了“不安全的旧式 TLS 重新协商”，而 Python 默认已经禁止它&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;为什么浏览器能访问，我的 Python 不能？&lt;/strong&gt;
浏览器（Chrome / Edge）：&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="爬取单日数据">爬取单日数据</h2>
<h4 id="前期准备">前期准备</h4>
<p>我要爬取的网站是</p>
<pre><code>https://www.icbc.com.cn/ICBC/%e9%87%91%e8%9e%8d%e4%bf%a1%e6%81%af/%e8%a1%8c%e6%83%85%e6%95%b0%e6%8d%ae/%e4%ba%ba%e6%b0%91%e5%b8%81%e5%8d%b3%e6%9c%9f%e5%a4%96%e6%b1%87%e7%89%8c%e4%bb%b7/
</code></pre>
<p>数据是这样的：币种、银行买入价、银行卖出价、发布时间</p>
<p><img alt="1" loading="lazy" src="/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20114748.png"></p>
<p>环境：python 3.12.2</p>
<h4 id="寻找网络请求接口">寻找网络请求接口</h4>
<p>在浏览器中按F12打开开发者工具，然后点击Network，勾选 Preserve log</p>
<ul>
<li>
<p>选择 Fetch / XHR</p>
<p><code>XMLHttpRequest (XHR)</code> 和 <code>Fetch API</code>都是网页向服务器发起 HTTP 请求的机制。Fetch API 是一种现代的、基于 Promise 的替代方案，用于取代老旧的、基于回调的 XHR，它提供了更简洁的语法和更适合现代网页开发的功能。</p>
</li>
<li>
<p>手动操作页面：</p>
<pre><code>  选择一个日期（比如 2021-01-25）

  点击【查询】
</code></pre>
</li>
<li>
<p>Network 列表里 新出现的 POST 请求</p>
<p><img loading="lazy" src="/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20161550.png">
可以确定工商银行新版 PAPI 的“历史外汇牌价接口”：<code>POST https://papi.icbc.com.cn/exchanges/ns/history</code></p>
</li>
</ul>
<h4 id="如何使用接口">如何使用接口</h4>
<h6 id="请求方式">请求方式</h6>
<ul>
<li>
<p>POST</p>
</li>
<li>
<p>Content-Type: application/json</p>
</li>
</ul>
<h6 id="请求体">请求体</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-01-13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>👉 这个接口不支持“时间区间”</p>
<p>👉 需要一天一天请求</p>
<h4 id="编写代码">编写代码</h4>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://papi.icbc.com.cn/exchanges/ns/history&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn/ICBC/</span><span class="si">%E</span><span class="s2">9</span><span class="si">%87%</span><span class="s2">91</span><span class="si">%E</span><span class="s2">8</span><span class="si">%9E</span><span class="s2">%8D</span><span class="si">%E</span><span class="s2">4%BF%A1</span><span class="si">%E</span><span class="s2">6</span><span class="si">%81%</span><span class="s2">AF/</span><span class="si">%E</span><span class="s2">8%A1%8C</span><span class="si">%E</span><span class="s2">6</span><span class="si">%83%</span><span class="s2">85</span><span class="si">%E</span><span class="s2">6</span><span class="si">%95%</span><span class="s2">B0</span><span class="si">%E</span><span class="s2">6%8D%AE/</span><span class="si">%E</span><span class="s2">4%BA%BA</span><span class="si">%E</span><span class="s2">6%B0</span><span class="si">%91%</span><span class="s2">E5%B8</span><span class="si">%81%</span><span class="s2">E5%8D%B3</span><span class="si">%E</span><span class="s2">6%9C</span><span class="si">%9F%E</span><span class="s2">5%A4</span><span class="si">%96%</span><span class="s2">E6%B1</span><span class="si">%87%</span><span class="s2">E7</span><span class="si">%89%</span><span class="s2">8C</span><span class="si">%E</span><span class="s2">4%BB%B7/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-01-13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<h6 id="报错ssl-unsafe_legacy_renegotiation_disabled">报错：<code>[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED]</code></h6>
<ul>
<li>当前的 Python + OpenSSL 与工行 PAPI 服务器的 TLS 协商不兼容</li>
<li>更准确地说：
请求触发了“不安全的旧式 TLS 重新协商”，而 Python 默认已经禁止它</li>
</ul>
<p><strong>为什么浏览器能访问，我的 Python 不能？</strong>
浏览器（Chrome / Edge）：</p>
<pre><code>自带 定制版 TLS 实现

对一些“历史遗留银行系统”做了兼容

会悄悄降级 / 特判
</code></pre>
<p>Python（requests / urllib3）：</p>
<pre><code>用的是 OpenSSL 官方实现

默认严格安全策略

直接拒绝这种 TLS 行为
</code></pre>
<p>👉 银行系统（尤其是国内）</p>
<p>👉 TLS 配置老 + 中间网关</p>
<p>👉 非常容易触发这个问题</p>
<h6 id="解决方案">解决方案</h6>
<ul>
<li>彻底禁用代理，哪怕不用代理工具，也很可能被环境变量污染。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTP_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTPS_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;ALL_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>requests 调用时显式指定代理</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">proxies</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;http&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;https&#34;</span><span class="p">:</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 或者直接在代码里禁用</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>SSL Adapter + verify=False</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># ===== 2. SSL Adapter：同时解决旧协议和证书验证冲突问题 =====</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">LegacySSLAdapter</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">HTTPAdapter</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">init_poolmanager</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connections</span><span class="p">,</span> <span class="n">maxsize</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 创建 SSL 上下文</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span> <span class="o">=</span> <span class="n">create_urllib3_context</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 解决旧版 SSL 协商问题</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">|=</span> <span class="mh">0x4</span>  <span class="c1"># OP_LEGACY_SERVER_CONNECT</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 关闭证书验证（对应 verify=False）</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span>  <span class="c1"># 先关闭主机名检查</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>  <span class="c1"># 再关闭证书验证</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">poolmanager</span> <span class="o">=</span> <span class="n">PoolManager</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">num_pools</span><span class="o">=</span><span class="n">connections</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">maxsize</span><span class="o">=</span><span class="n">maxsize</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ssl_context</span><span class="o">=</span><span class="n">ctx</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">ssl</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.poolmanager</span> <span class="kn">import</span> <span class="n">PoolManager</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.util.ssl_</span> <span class="kn">import</span> <span class="n">create_urllib3_context</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 1. 彻底禁用代理 =====</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTP_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTPS_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;ALL_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 2. SSL Adapter：同时解决旧协议和证书验证冲突问题 =====</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">LegacySSLAdapter</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">HTTPAdapter</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">init_poolmanager</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connections</span><span class="p">,</span> <span class="n">maxsize</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 创建 SSL 上下文</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span> <span class="o">=</span> <span class="n">create_urllib3_context</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 解决旧版 SSL 协商问题</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">|=</span> <span class="mh">0x4</span>  <span class="c1"># OP_LEGACY_SERVER_CONNECT</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 关闭证书验证（对应 verify=False）</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span>  <span class="c1"># 先关闭主机名检查</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>  <span class="c1"># 再关闭证书验证</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">poolmanager</span> <span class="o">=</span> <span class="n">PoolManager</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">num_pools</span><span class="o">=</span><span class="n">connections</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">maxsize</span><span class="o">=</span><span class="n">maxsize</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ssl_context</span><span class="o">=</span><span class="n">ctx</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://papi.icbc.com.cn/exchanges/ns/history&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn/ICBC/</span><span class="si">%E</span><span class="s2">9</span><span class="si">%87%</span><span class="s2">91</span><span class="si">%E</span><span class="s2">8</span><span class="si">%9E</span><span class="s2">%8D</span><span class="si">%E</span><span class="s2">4%BF%A1</span><span class="si">%E</span><span class="s2">6</span><span class="si">%81%</span><span class="s2">AF/</span><span class="si">%E</span><span class="s2">8%A1%8C</span><span class="si">%E</span><span class="s2">6</span><span class="si">%83%</span><span class="s2">85</span><span class="si">%E</span><span class="s2">6</span><span class="si">%95%</span><span class="s2">B0</span><span class="si">%E</span><span class="s2">6%8D%AE/</span><span class="si">%E</span><span class="s2">4%BA%BA</span><span class="si">%E</span><span class="s2">6%B0</span><span class="si">%91%</span><span class="s2">E5%B8</span><span class="si">%81%</span><span class="s2">E5%8D%B3</span><span class="si">%E</span><span class="s2">6%9C</span><span class="si">%9F%E</span><span class="s2">5%A4</span><span class="si">%96%</span><span class="s2">E6%B1</span><span class="si">%87%</span><span class="s2">E7</span><span class="si">%89%</span><span class="s2">8C</span><span class="si">%E</span><span class="s2">4%BB%B7/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-01-13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">session</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">session</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s2">&#34;https://&#34;</span><span class="p">,</span> <span class="n">LegacySSLAdapter</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">proxies</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;http&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;https&#34;</span><span class="p">:</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 这里移除了 verify=False，因为已经在适配器里统一配置了</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">url</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">timeout</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">proxies</span><span class="o">=</span><span class="n">proxies</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">status_code</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<p><strong>结果：</strong>
<img alt="2" loading="lazy" src="/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20163806.png"></p>
<h2 id="爬取近五年数据">爬取近五年数据</h2>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">ssl</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.poolmanager</span> <span class="kn">import</span> <span class="n">PoolManager</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.util.ssl_</span> <span class="kn">import</span> <span class="n">create_urllib3_context</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 1. 彻底禁用代理</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTP_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTPS_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;ALL_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 2. SSL Adapter（银行专用）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">LegacySSLAdapter</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">HTTPAdapter</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">init_poolmanager</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connections</span><span class="p">,</span> <span class="n">maxsize</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span> <span class="o">=</span> <span class="n">create_urllib3_context</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">|=</span> <span class="mh">0x4</span>  <span class="c1"># OP_LEGACY_SERVER_CONNECT</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">poolmanager</span> <span class="o">=</span> <span class="n">PoolManager</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">num_pools</span><span class="o">=</span><span class="n">connections</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">maxsize</span><span class="o">=</span><span class="n">maxsize</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ssl_context</span><span class="o">=</span><span class="n">ctx</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 3. 请求基础配置</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">URL</span> <span class="o">=</span> <span class="s2">&#34;https://papi.icbc.com.cn/exchanges/ns/history&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">HEADERS</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn/ICBC/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">PROXIES</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;http&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="s2">&#34;https&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 4. 创建 Session</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">session</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">session</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s2">&#34;https://&#34;</span><span class="p">,</span> <span class="n">LegacySSLAdapter</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 5. 单日抓取函数（带重试）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fetch_one_day</span><span class="p">(</span><span class="n">date_str</span><span class="p">,</span> <span class="n">max_retry</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="n">date_str</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">attempt</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">max_retry</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">r</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                <span class="n">URL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">headers</span><span class="o">=</span><span class="n">HEADERS</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">timeout</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">proxies</span><span class="o">=</span><span class="n">PROXIES</span>
</span></span><span class="line"><span class="cl">            <span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">r</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">data</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;code&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="n">data</span><span class="p">[</span><span class="s2">&#34;data&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;[WARN] </span><span class="si">{</span><span class="n">date_str</span><span class="si">}</span><span class="s2"> 返回异常 code: </span><span class="si">{</span><span class="n">data</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;[RETRY </span><span class="si">{</span><span class="n">attempt</span><span class="si">}</span><span class="s2">] </span><span class="si">{</span><span class="n">date_str</span><span class="si">}</span><span class="s2"> 失败: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">attempt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 6. 时间范围（近 5 年）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">end_date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">today</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">start_date</span> <span class="o">=</span> <span class="n">end_date</span> <span class="o">-</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span> <span class="o">*</span> <span class="mi">365</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 7. 主循环</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">all_rows</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">missing_dates</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">current</span> <span class="o">=</span> <span class="n">start_date</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">current</span> <span class="o">&lt;=</span> <span class="n">end_date</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">date_str</span> <span class="o">=</span> <span class="n">current</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y-%m-</span><span class="si">%d</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;📅 抓取 </span><span class="si">{</span><span class="n">date_str</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">day_data</span> <span class="o">=</span> <span class="n">fetch_one_day</span><span class="p">(</span><span class="n">date_str</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">day_data</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">missing_dates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">date_str</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">day_data</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">all_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="n">date_str</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;currencyENName&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;currencyENName&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;currencyCHName&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;currencyCHName&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;reference&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;reference&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;foreignBuy&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;foreignBuy&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;foreignSell&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;foreignSell&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;cashBuy&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;cashBuy&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;cashSell&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;cashSell&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>  <span class="c1"># 银行接口，别太猛</span>
</span></span><span class="line"><span class="cl">    <span class="n">current</span> <span class="o">+=</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 8. DataFrame &amp; CSV</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">all_rows</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">csv_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s2">&#34;icbc_exchange_5y.csv&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">to_csv</span><span class="p">(</span><span class="n">csv_path</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&#34;utf-8-sig&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">✅ 数据抓取完成&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;📄 CSV 文件：</span><span class="si">{</span><span class="n">csv_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;📊 总记录数：</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">df</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">missing_dates</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;⚠️ 缺失日期 (</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">missing_dates</span><span class="p">)</span><span class="si">}</span><span class="s2">):&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">missing_dates</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;🎉 无缺失日期&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
]]></content:encoded></item><item><title>翻转树上最少边</title><link>https://farmer3-c.github.io/posts/flip-tree-min-edge/</link><pubDate>Mon, 19 Jan 2026 14:30:47 +0800</pubDate><guid>https://farmer3-c.github.io/posts/flip-tree-min-edge/</guid><description>&lt;h2 id="翻转树上最少边"&gt;&lt;a href="https://leetcode.cn/problems/minimum-edge-toggles-on-a-tree/"&gt;翻转树上最少边&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;给你一棵包含 n 个节点的 无向树，节点编号从 0 到 n - 1。该树由长度为 n - 1 的二维整数数组 edges 表示，其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。&lt;/p&gt;
&lt;p&gt;另外给你两个长度为 n 的 二进制 字符串 start 和 target。对于每个节点 x，start[x] 是其初始颜色，而 target[x] 是其目标颜色。&lt;/p&gt;
&lt;p&gt;在一次操作中，你可以选择下标为 i 的一条边并 翻转 它的两个端点。也就是说，如果这条边是 [u, v]，那么节点 u 和 v 的颜色 各自 从 &amp;lsquo;0&amp;rsquo; 变为 &amp;lsquo;1&amp;rsquo;，或者从 &amp;lsquo;1&amp;rsquo; 变为 &amp;lsquo;0&amp;rsquo;。&lt;/p&gt;
&lt;p&gt;返回一个边下标数组，执行这些边对应的操作可以将 start 转换为 target。在所有有效序列中找出 长度最短 的序列，以 升序 返回边下标。&lt;/p&gt;
&lt;p&gt;如果无法将 start 转换为 target，则返回一个仅包含单个元素 -1 的数组。&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="翻转树上最少边"><a href="https://leetcode.cn/problems/minimum-edge-toggles-on-a-tree/">翻转树上最少边</a></h2>
<p>给你一棵包含 n 个节点的 无向树，节点编号从 0 到 n - 1。该树由长度为 n - 1 的二维整数数组 edges 表示，其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。</p>
<p>另外给你两个长度为 n 的 二进制 字符串 start 和 target。对于每个节点 x，start[x] 是其初始颜色，而 target[x] 是其目标颜色。</p>
<p>在一次操作中，你可以选择下标为 i 的一条边并 翻转 它的两个端点。也就是说，如果这条边是 [u, v]，那么节点 u 和 v 的颜色 各自 从 &lsquo;0&rsquo; 变为 &lsquo;1&rsquo;，或者从 &lsquo;1&rsquo; 变为 &lsquo;0&rsquo;。</p>
<p>返回一个边下标数组，执行这些边对应的操作可以将 start 转换为 target。在所有有效序列中找出 长度最短 的序列，以 升序 返回边下标。</p>
<p>如果无法将 start 转换为 target，则返回一个仅包含单个元素 -1 的数组。</p>
<h2 id="思路">思路</h2>
<p>树的题目一般都可以用dfs来解决。</p>
<h4 id="方法一自底向上的-dfs">方法一：自底向上的 DFS</h4>
<p>把问题看成：
<strong>每条边最多翻转一次</strong>，翻转后会影响这条边两端节点的颜色。对于每个节点，只关心它“最终是否需要被翻转奇数次”。</p>
<p>在树上做 <strong>DFS 后序遍历</strong>：</p>
<p>先处理子树</p>
<p>再决定是否通过“连接父亲的那条边”来修正当前节点</p>
<p>叶子节点的颜色如果与目标颜色不同，那么就一定要翻转和它相连接的两个节点，同时将边加入答案。移除原来的叶子节点，对新的叶子节点进行同样的操作。</p>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">minimumFlips</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;&amp;</span> <span class="n">edges</span><span class="p">,</span> <span class="n">string</span> <span class="n">start</span><span class="p">,</span> <span class="n">string</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;&gt;&gt;</span> <span class="n">g</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">x</span><span class="o">=</span><span class="n">edges</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span><span class="n">y</span><span class="o">=</span><span class="n">edges</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="n">g</span><span class="p">[</span><span class="n">x</span><span class="p">].</span><span class="n">emplace_back</span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">g</span><span class="p">[</span><span class="n">y</span><span class="p">].</span><span class="n">emplace_back</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">       <span class="n">std</span><span class="o">::</span> <span class="n">function</span> <span class="o">&lt;</span><span class="kt">bool</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="p">)</span><span class="o">&gt;</span> <span class="n">dfs</span><span class="o">=</span><span class="p">[</span><span class="o">&amp;</span><span class="p">](</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span><span class="kt">int</span> <span class="n">fa</span><span class="p">)</span><span class="o">-&gt;</span><span class="kt">bool</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">bool</span> <span class="n">rev</span><span class="o">=</span><span class="n">start</span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="o">!=</span><span class="n">target</span><span class="p">[</span><span class="n">x</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="p">[</span><span class="n">y</span><span class="p">,</span><span class="n">i</span><span class="p">]</span><span class="o">:</span><span class="n">g</span><span class="p">[</span><span class="n">x</span><span class="p">]){</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span><span class="p">(</span><span class="n">y</span><span class="o">!=</span><span class="n">fa</span><span class="o">&amp;&amp;</span><span class="n">dfs</span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="n">x</span><span class="p">)){</span>
</span></span><span class="line"><span class="cl">                    <span class="n">ans</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="n">rev</span><span class="o">=!</span><span class="n">rev</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">rev</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="n">dfs</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">)){</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">{</span><span class="o">-</span><span class="mi">1</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">sort</span><span class="p">(</span><span class="n">ans</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="n">ans</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<p><strong>正确性说明</strong></p>
<pre><code>树结构保证：

    每个节点（除根）只有一条父边可以“补救”它

贪心是最优的：

    子节点问题必须在子树处理完后才能处理

    父边是唯一能影响子节点的外部操作
</code></pre>
<p>时间复杂度：O(n)，其中n为节点个数。
空间复杂度：O(n)，其中n为节点个数。
排序答案：O(n log n)</p>
<h4 id="方法二树上异或差分思想等价但更直观">方法二：树上“异或差分”思想（等价但更直观）</h4>
<p><strong>核心思想</strong></p>
<pre><code>把每个节点需要的变化看成一个值：

need[x] = (start[x] != target[x]) ? 1 : 0;


翻转一条边 (u, v)：

相当于：need[u] ^= 1, need[v] ^= 1

目标：通过选一些边，使得所有 need[x] = 0
</code></pre>
<p><strong>树上贪心策略</strong></p>
<pre><code>从叶子向根 DFS

如果某个子节点 y 的 need[y] == 1

那么必须翻转父边 (x, y)

否则 y 永远无法变成 0

翻转后：

need[y] = 0;
need[x] ^= 1;
</code></pre>
<p>算法流程</p>
<pre><code>DFS 返回后，子节点要么是 0，要么已经通过父边解决

最终检查根节点：

need[root] == 0 → 可行

否则 → 无解
</code></pre>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">minimumFlips</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;&amp;</span> <span class="n">edges</span><span class="p">,</span> <span class="n">string</span> <span class="n">start</span><span class="p">,</span> <span class="n">string</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="kt">int</span><span class="o">&gt;&gt;&gt;</span> <span class="n">g</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">u</span> <span class="o">=</span> <span class="n">edges</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">v</span> <span class="o">=</span> <span class="n">edges</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="n">g</span><span class="p">[</span><span class="n">u</span><span class="p">].</span><span class="n">push_back</span><span class="p">({</span><span class="n">v</span><span class="p">,</span><span class="n">i</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">            <span class="n">g</span><span class="p">[</span><span class="n">v</span><span class="p">].</span><span class="n">push_back</span><span class="p">({</span><span class="n">u</span><span class="p">,</span><span class="n">i</span><span class="p">});</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">need</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="n">n</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
</span></span><span class="line"><span class="cl">            <span class="n">need</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">start</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">!=</span> <span class="n">target</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">auto</span> <span class="n">dfs</span> <span class="o">=</span> <span class="p">[</span><span class="o">&amp;</span><span class="p">](</span><span class="k">this</span> <span class="k">auto</span><span class="o">&amp;&amp;</span> <span class="n">dfs</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">fa</span><span class="p">)</span><span class="o">-&gt;</span><span class="kt">void</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="p">[</span><span class="n">y</span><span class="p">,</span> <span class="n">id</span><span class="p">]</span> <span class="o">:</span> <span class="n">g</span><span class="p">[</span><span class="n">x</span><span class="p">]){</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span><span class="p">(</span><span class="n">y</span> <span class="o">==</span> <span class="n">fa</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">dfs</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span><span class="p">(</span><span class="n">need</span><span class="p">[</span><span class="n">y</span><span class="p">]){</span>
</span></span><span class="line"><span class="cl">                    <span class="n">ans</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">id</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="n">need</span><span class="p">[</span><span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="n">need</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">^=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">dfs</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="n">need</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">return</span> <span class="p">{</span><span class="o">-</span><span class="mi">1</span><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">sort</span><span class="p">(</span><span class="n">ans</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">ans</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://leetcode.cn/problems/minimum-edge-toggles-on-a-tree/solutions/3883163/dfspythonjavacgo-by-endlesscheng-5m1i/">灵茶山艾府</a></li>
</ul>
]]></content:encoded></item><item><title>交替按位异或分割的数目</title><link>https://farmer3-c.github.io/posts/post-2026-01-19/</link><pubDate>Mon, 19 Jan 2026 14:28:02 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2026-01-19/</guid><description>&lt;h2 id="3811交替按位异或分割的数目"&gt;&lt;a href="https://leetcode.cn/problems/number-of-alternating-xor-partitions/description/"&gt;3811.交替按位异或分割的数目&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;给你一个整数数组 nums 以及两个 互不相同 的整数 target1 和 target2。nums 的一个 分割 是指将其划分为一个或多个 连续且非空 的块，这些块在不重叠的情况下覆盖整个数组。&lt;/p&gt;
&lt;p&gt;如果一个分割中各块元素的 按位异或 结果在 target1 和 target2 之间 交替 出现，且以 target1 开始，则称该分割是 有效的。&lt;/p&gt;
&lt;p&gt;形式上，对于块 b1, b2, &amp;hellip; ：&lt;/p&gt;
&lt;p&gt;XOR(b1) = target1
XOR(b2) = target2（如果存在）
XOR(b3) = target1，以此类推。
返回 nums 的有效分割方案数，结果对 $10^9 $+ 7 取余。&lt;/p&gt;
&lt;p&gt;注意： 如果单个块的 按位异或 结果等于 target1，则该分割也是有效的。&lt;/p&gt;
&lt;p&gt;1 &amp;lt;= nums.length &amp;lt;= $10^5$
0 &amp;lt;= nums[i], target1, target2 &amp;lt;= $10^5$
target1 != target2&lt;/p&gt;
&lt;h2 id="思路"&gt;思路&lt;/h2&gt;
&lt;h4 id="方法一递归记忆化搜索"&gt;方法一：递归+记忆化搜索&lt;/h4&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠代码&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c++" data-lang="c++"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Solution&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1e9&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;alternatingXOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;target1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;target2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;时间复杂度：O(n)，其中n为数组nums的长度。
空间复杂度：O(n)，需要使用一个二维数组memo来存储中间结果。
不足以通过所有测试用例，超时。&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="3811交替按位异或分割的数目"><a href="https://leetcode.cn/problems/number-of-alternating-xor-partitions/description/">3811.交替按位异或分割的数目</a></h2>
<p>给你一个整数数组 nums 以及两个 互不相同 的整数 target1 和 target2。nums 的一个 分割 是指将其划分为一个或多个 连续且非空 的块，这些块在不重叠的情况下覆盖整个数组。</p>
<p>如果一个分割中各块元素的 按位异或 结果在 target1 和 target2 之间 交替 出现，且以 target1 开始，则称该分割是 有效的。</p>
<p>形式上，对于块 b1, b2, &hellip; ：</p>
<p>XOR(b1) = target1
XOR(b2) = target2（如果存在）
XOR(b3) = target1，以此类推。
返回 nums 的有效分割方案数，结果对 $10^9 $+ 7 取余。</p>
<p>注意： 如果单个块的 按位异或 结果等于 target1，则该分割也是有效的。</p>
<p>1 &lt;= nums.length &lt;= $10^5$
0 &lt;= nums[i], target1, target2 &lt;= $10^5$
target1 != target2</p>
<h2 id="思路">思路</h2>
<h4 id="方法一递归记忆化搜索">方法一：递归+记忆化搜索</h4>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span>  <span class="n">mod</span> <span class="o">=</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="mi">7</span><span class="p">,</span> <span class="n">t</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;&gt;</span> <span class="n">memo</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">long</span> <span class="kt">long</span> <span class="nf">dfs</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="kt">int</span> <span class="n">state</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">nums</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">state</span><span class="p">]</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">state</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="kt">long</span> <span class="kt">long</span> <span class="n">res</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">cur</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">cur</span> <span class="o">^=</span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="n">t</span><span class="p">[</span><span class="n">state</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">==</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">res</span> <span class="o">=</span> <span class="p">(</span><span class="n">res</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="k">else</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="n">res</span> <span class="o">=</span> <span class="p">(</span><span class="n">res</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">state</span> <span class="o">^</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nums</span><span class="p">))</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">memo</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">state</span><span class="p">]</span><span class="o">=</span><span class="n">res</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">alternatingXOR</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">target1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">target2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">memo</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">long</span> <span class="kt">long</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nf">dfs</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">nums</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<p>时间复杂度：O(n)，其中n为数组nums的长度。
空间复杂度：O(n)，需要使用一个二维数组memo来存储中间结果。
不足以通过所有测试用例，超时。</p>
<h4 id="方法二动态规划">方法二：动态规划</h4>
<ul>
<li>定义两个哈希表f1和f2，分别用于存储当前遍历到的位置i时，前缀异或值为target1和target2的分割方案数。</li>
<li>初始化f2[0] = 1，表示前缀异或值为0的分割方案数为1。</li>
<li>遍历数组nums，对于每个位置i，计算当前位置的前缀异或值pre。</li>
<li>计算以位置i结尾的分割方案数，即f1[target1 ^ pre] + f2[target2 ^ pre]。</li>
<li>如果当前位置是数组的最后一个元素，返回计算出的分割方案数。</li>
<li>更新f1[pre]和f2[pre]，分别加上以位置i结尾的分割方案数。</li>
<li>返回计算出的分割方案数。</li>
<li>时间复杂度：O(n)，其中n为数组nums的长度。</li>
<li>空间复杂度：O(n)，需要使用两个哈希表来存储分割方案数。</li>
</ul>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">Solution</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">alternatingXOR</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">nums</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">mod</span> <span class="o">=</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="mi">7</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">f1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">f2</span> <span class="o">=</span> <span class="p">{</span> <span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">}</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">pre</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">pre</span> <span class="o">^=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">l1</span> <span class="o">=</span> <span class="n">f2</span><span class="p">[</span><span class="n">target1</span> <span class="o">^</span> <span class="n">pre</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="kt">int</span> <span class="n">l2</span> <span class="o">=</span> <span class="n">f1</span><span class="p">[</span><span class="n">target2</span> <span class="o">^</span> <span class="n">pre</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="p">(</span><span class="n">l1</span> <span class="o">+</span> <span class="n">l2</span><span class="p">)</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="n">f1</span><span class="p">[</span><span class="n">pre</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">l1</span> <span class="o">+</span> <span class="n">f1</span><span class="p">[</span><span class="n">pre</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">f2</span><span class="p">[</span><span class="n">pre</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">l2</span> <span class="o">+</span> <span class="n">f2</span><span class="p">[</span><span class="n">pre</span><span class="p">])</span> <span class="o">%</span> <span class="n">mod</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://leetcode.cn/problems/number-of-alternating-xor-partitions/solutions/3883194/he-fa-zi-xu-lie-dppythonjavacgo-by-endle-ivxh/">灵茶山艾府</a></li>
</ul>
]]></content:encoded></item><item><title>查找并重命名文件</title><link>https://farmer3-c.github.io/posts/unix/</link><pubDate>Tue, 13 Jan 2026 10:44:47 +0800</pubDate><guid>https://farmer3-c.github.io/posts/unix/</guid><description>&lt;p&gt;&lt;strong&gt;下面是实现查找并重命名文件的C程序，使用了&lt;code&gt;apue.h&lt;/code&gt;库中的函数和数据结构。
该程序支持查找指定目录下的所有文件，并将指定文件名的文件重命名为&amp;quot;pass&amp;quot;。
程序会输出重命名的文件数量。&lt;/strong&gt;&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠代码&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt; 10
&lt;/span&gt;&lt;span class="lnt"&gt; 11
&lt;/span&gt;&lt;span class="lnt"&gt; 12
&lt;/span&gt;&lt;span class="lnt"&gt; 13
&lt;/span&gt;&lt;span class="lnt"&gt; 14
&lt;/span&gt;&lt;span class="lnt"&gt; 15
&lt;/span&gt;&lt;span class="lnt"&gt; 16
&lt;/span&gt;&lt;span class="lnt"&gt; 17
&lt;/span&gt;&lt;span class="lnt"&gt; 18
&lt;/span&gt;&lt;span class="lnt"&gt; 19
&lt;/span&gt;&lt;span class="lnt"&gt; 20
&lt;/span&gt;&lt;span class="lnt"&gt; 21
&lt;/span&gt;&lt;span class="lnt"&gt; 22
&lt;/span&gt;&lt;span class="lnt"&gt; 23
&lt;/span&gt;&lt;span class="lnt"&gt; 24
&lt;/span&gt;&lt;span class="lnt"&gt; 25
&lt;/span&gt;&lt;span class="lnt"&gt; 26
&lt;/span&gt;&lt;span class="lnt"&gt; 27
&lt;/span&gt;&lt;span class="lnt"&gt; 28
&lt;/span&gt;&lt;span class="lnt"&gt; 29
&lt;/span&gt;&lt;span class="lnt"&gt; 30
&lt;/span&gt;&lt;span class="lnt"&gt; 31
&lt;/span&gt;&lt;span class="lnt"&gt; 32
&lt;/span&gt;&lt;span class="lnt"&gt; 33
&lt;/span&gt;&lt;span class="lnt"&gt; 34
&lt;/span&gt;&lt;span class="lnt"&gt; 35
&lt;/span&gt;&lt;span class="lnt"&gt; 36
&lt;/span&gt;&lt;span class="lnt"&gt; 37
&lt;/span&gt;&lt;span class="lnt"&gt; 38
&lt;/span&gt;&lt;span class="lnt"&gt; 39
&lt;/span&gt;&lt;span class="lnt"&gt; 40
&lt;/span&gt;&lt;span class="lnt"&gt; 41
&lt;/span&gt;&lt;span class="lnt"&gt; 42
&lt;/span&gt;&lt;span class="lnt"&gt; 43
&lt;/span&gt;&lt;span class="lnt"&gt; 44
&lt;/span&gt;&lt;span class="lnt"&gt; 45
&lt;/span&gt;&lt;span class="lnt"&gt; 46
&lt;/span&gt;&lt;span class="lnt"&gt; 47
&lt;/span&gt;&lt;span class="lnt"&gt; 48
&lt;/span&gt;&lt;span class="lnt"&gt; 49
&lt;/span&gt;&lt;span class="lnt"&gt; 50
&lt;/span&gt;&lt;span class="lnt"&gt; 51
&lt;/span&gt;&lt;span class="lnt"&gt; 52
&lt;/span&gt;&lt;span class="lnt"&gt; 53
&lt;/span&gt;&lt;span class="lnt"&gt; 54
&lt;/span&gt;&lt;span class="lnt"&gt; 55
&lt;/span&gt;&lt;span class="lnt"&gt; 56
&lt;/span&gt;&lt;span class="lnt"&gt; 57
&lt;/span&gt;&lt;span class="lnt"&gt; 58
&lt;/span&gt;&lt;span class="lnt"&gt; 59
&lt;/span&gt;&lt;span class="lnt"&gt; 60
&lt;/span&gt;&lt;span class="lnt"&gt; 61
&lt;/span&gt;&lt;span class="lnt"&gt; 62
&lt;/span&gt;&lt;span class="lnt"&gt; 63
&lt;/span&gt;&lt;span class="lnt"&gt; 64
&lt;/span&gt;&lt;span class="lnt"&gt; 65
&lt;/span&gt;&lt;span class="lnt"&gt; 66
&lt;/span&gt;&lt;span class="lnt"&gt; 67
&lt;/span&gt;&lt;span class="lnt"&gt; 68
&lt;/span&gt;&lt;span class="lnt"&gt; 69
&lt;/span&gt;&lt;span class="lnt"&gt; 70
&lt;/span&gt;&lt;span class="lnt"&gt; 71
&lt;/span&gt;&lt;span class="lnt"&gt; 72
&lt;/span&gt;&lt;span class="lnt"&gt; 73
&lt;/span&gt;&lt;span class="lnt"&gt; 74
&lt;/span&gt;&lt;span class="lnt"&gt; 75
&lt;/span&gt;&lt;span class="lnt"&gt; 76
&lt;/span&gt;&lt;span class="lnt"&gt; 77
&lt;/span&gt;&lt;span class="lnt"&gt; 78
&lt;/span&gt;&lt;span class="lnt"&gt; 79
&lt;/span&gt;&lt;span class="lnt"&gt; 80
&lt;/span&gt;&lt;span class="lnt"&gt; 81
&lt;/span&gt;&lt;span class="lnt"&gt; 82
&lt;/span&gt;&lt;span class="lnt"&gt; 83
&lt;/span&gt;&lt;span class="lnt"&gt; 84
&lt;/span&gt;&lt;span class="lnt"&gt; 85
&lt;/span&gt;&lt;span class="lnt"&gt; 86
&lt;/span&gt;&lt;span class="lnt"&gt; 87
&lt;/span&gt;&lt;span class="lnt"&gt; 88
&lt;/span&gt;&lt;span class="lnt"&gt; 89
&lt;/span&gt;&lt;span class="lnt"&gt; 90
&lt;/span&gt;&lt;span class="lnt"&gt; 91
&lt;/span&gt;&lt;span class="lnt"&gt; 92
&lt;/span&gt;&lt;span class="lnt"&gt; 93
&lt;/span&gt;&lt;span class="lnt"&gt; 94
&lt;/span&gt;&lt;span class="lnt"&gt; 95
&lt;/span&gt;&lt;span class="lnt"&gt; 96
&lt;/span&gt;&lt;span class="lnt"&gt; 97
&lt;/span&gt;&lt;span class="lnt"&gt; 98
&lt;/span&gt;&lt;span class="lnt"&gt; 99
&lt;/span&gt;&lt;span class="lnt"&gt;100
&lt;/span&gt;&lt;span class="lnt"&gt;101
&lt;/span&gt;&lt;span class="lnt"&gt;102
&lt;/span&gt;&lt;span class="lnt"&gt;103
&lt;/span&gt;&lt;span class="lnt"&gt;104
&lt;/span&gt;&lt;span class="lnt"&gt;105
&lt;/span&gt;&lt;span class="lnt"&gt;106
&lt;/span&gt;&lt;span class="lnt"&gt;107
&lt;/span&gt;&lt;span class="lnt"&gt;108
&lt;/span&gt;&lt;span class="lnt"&gt;109
&lt;/span&gt;&lt;span class="lnt"&gt;110
&lt;/span&gt;&lt;span class="lnt"&gt;111
&lt;/span&gt;&lt;span class="lnt"&gt;112
&lt;/span&gt;&lt;span class="lnt"&gt;113
&lt;/span&gt;&lt;span class="lnt"&gt;114
&lt;/span&gt;&lt;span class="lnt"&gt;115
&lt;/span&gt;&lt;span class="lnt"&gt;116
&lt;/span&gt;&lt;span class="lnt"&gt;117
&lt;/span&gt;&lt;span class="lnt"&gt;118
&lt;/span&gt;&lt;span class="lnt"&gt;119
&lt;/span&gt;&lt;span class="lnt"&gt;120
&lt;/span&gt;&lt;span class="lnt"&gt;121
&lt;/span&gt;&lt;span class="lnt"&gt;122
&lt;/span&gt;&lt;span class="lnt"&gt;123
&lt;/span&gt;&lt;span class="lnt"&gt;124
&lt;/span&gt;&lt;span class="lnt"&gt;125
&lt;/span&gt;&lt;span class="lnt"&gt;126
&lt;/span&gt;&lt;span class="lnt"&gt;127
&lt;/span&gt;&lt;span class="lnt"&gt;128
&lt;/span&gt;&lt;span class="lnt"&gt;129
&lt;/span&gt;&lt;span class="lnt"&gt;130
&lt;/span&gt;&lt;span class="lnt"&gt;131
&lt;/span&gt;&lt;span class="lnt"&gt;132
&lt;/span&gt;&lt;span class="lnt"&gt;133
&lt;/span&gt;&lt;span class="lnt"&gt;134
&lt;/span&gt;&lt;span class="lnt"&gt;135
&lt;/span&gt;&lt;span class="lnt"&gt;136
&lt;/span&gt;&lt;span class="lnt"&gt;137
&lt;/span&gt;&lt;span class="lnt"&gt;138
&lt;/span&gt;&lt;span class="lnt"&gt;139
&lt;/span&gt;&lt;span class="lnt"&gt;140
&lt;/span&gt;&lt;span class="lnt"&gt;141
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;#34;apue.h&amp;#34;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;dirent.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;limits.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Myfunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Myfunc&lt;/span&gt; &lt;span class="n"&gt;myfunc_rename&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;dopath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Myfunc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;myftw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Myfunc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 存储文件完整路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;target_filename&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 要查找并重命名的目标文件名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;rename_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 成功重命名的文件数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 文件类型标记
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define FTW_F 1 &lt;/span&gt;&lt;span class="cm"&gt;/* 普通文件 */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define FTW_D 2 &lt;/span&gt;&lt;span class="cm"&gt;/* 目录 */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define FTW_DNR 3 &lt;/span&gt;&lt;span class="cm"&gt;/* 不可读目录 */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define FTW_NS 4 &lt;/span&gt;&lt;span class="cm"&gt;/* 无法stat的文件 */&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 校验参数：支持 myfind &amp;lt;指定目录&amp;gt; &amp;lt;要改名的文件名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;err_quit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;usage: myfind &amp;lt;target_directory&amp;gt; &amp;lt;filename_to_rename&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;target_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rename_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;myftw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;myfunc_rename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rename_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;未找到名为 &amp;#39;%s&amp;#39; 的文件，无需重命名&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;成功将 %d 个文件重命名为 &amp;#39;pass&amp;#39;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rename_count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;myftw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Myfunc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fullpath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;path_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 从apue库获取路径缓冲区
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strncpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 确保字符串终止
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dopath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;dopath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Myfunc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;dirent&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dirp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DIR&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 获取文件属性失败
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lstat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FTW_NS&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 如果是普通文件，执行重命名逻辑
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;S_ISDIR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;st_mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FTW_F&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 如果是目录，先执行回调（无实际操作）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FTW_D&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 拼接子目录路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fullpath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 打开目录失败
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;opendir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statbuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FTW_DNR&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 遍历目录下的所有文件/子目录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;dirp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 跳过.和..
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;d_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;d_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;..&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 拼接子文件路径
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dirp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;d_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 递归处理子文件/子目录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dopath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 恢复路径（移除最后拼接的子文件名）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 关闭目录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;closedir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;err_ret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;无法关闭目录: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fullpath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 查找目标文件并将其重命名为pass
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;myfunc_rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;statptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 仅处理普通文件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;FTW_F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 提取文件名（路径最后一个/后的部分）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;strrchr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 无/，直接是文件名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 跳过/，指向实际文件名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 匹配到目标文件，执行重命名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 拼接新路径：原目录 + /pass
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;new_path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PATH_MAX&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strncpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;strrchr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;strcat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;pass&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 执行重命名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;成功重命名: %s -&amp;gt; %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rename_count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;err_ret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;重命名失败: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h1 id="unix系统中路径的操作与修改"&gt;UNIX系统中路径的操作与修改&lt;/h1&gt;
&lt;p&gt;这个程序实现了在指定目录下查找并重命名特定文件的功能，展示了多种路径操作技术。&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>下面是实现查找并重命名文件的C程序，使用了<code>apue.h</code>库中的函数和数据结构。
该程序支持查找指定目录下的所有文件，并将指定文件名的文件重命名为&quot;pass&quot;。
程序会输出重命名的文件数量。</strong></p>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;apue.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;dirent.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;limits.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/stat.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sys/types.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">typedef</span> <span class="kt">int</span> <span class="nf">Myfunc</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">stat</span> <span class="o">*</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="n">Myfunc</span> <span class="n">myfunc_rename</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">dopath</span><span class="p">(</span><span class="n">Myfunc</span> <span class="o">*</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">myftw</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">,</span> <span class="n">Myfunc</span> <span class="o">*</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fullpath</span><span class="p">;</span>          <span class="c1">// 存储文件完整路径
</span></span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="n">target_filename</span><span class="p">;</span>   <span class="c1">// 要查找并重命名的目标文件名
</span></span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="n">rename_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>    <span class="c1">// 成功重命名的文件数
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 文件类型标记
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FTW_F    1    </span><span class="cm">/* 普通文件 */</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FTW_D    2    </span><span class="cm">/* 目录 */</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FTW_DNR  3    </span><span class="cm">/* 不可读目录 */</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#define FTW_NS   4    </span><span class="cm">/* 无法stat的文件 */</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 校验参数：支持 myfind &lt;指定目录&gt; &lt;要改名的文件名&gt;
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">err_quit</span><span class="p">(</span><span class="s">&#34;usage: myfind &lt;target_directory&gt; &lt;filename_to_rename&gt;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">target_filename</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="n">rename_count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ret</span> <span class="o">=</span> <span class="nf">myftw</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">myfunc_rename</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">rename_count</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;未找到名为 &#39;%s&#39; 的文件，无需重命名</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">target_filename</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;成功将 %d 个文件重命名为 &#39;pass&#39;</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">rename_count</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">exit</span><span class="p">(</span><span class="n">ret</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">myftw</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">pathname</span><span class="p">,</span> <span class="n">Myfunc</span> <span class="o">*</span><span class="n">func</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">size_t</span> <span class="n">len</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">fullpath</span> <span class="o">=</span> <span class="nf">path_alloc</span><span class="p">(</span><span class="o">&amp;</span><span class="n">len</span><span class="p">);</span>  <span class="c1">// 从apue库获取路径缓冲区
</span></span></span><span class="line"><span class="cl">    <span class="nf">strncpy</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="n">pathname</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">fullpath</span><span class="p">[</span><span class="n">len</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>          <span class="c1">// 确保字符串终止
</span></span></span><span class="line"><span class="cl">    <span class="k">return</span><span class="p">(</span><span class="nf">dopath</span><span class="p">(</span><span class="n">func</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">dopath</span><span class="p">(</span><span class="n">Myfunc</span> <span class="o">*</span><span class="n">func</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">stat</span> <span class="n">statbuf</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">struct</span> <span class="n">dirent</span> <span class="o">*</span><span class="n">dirp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">DIR</span> <span class="o">*</span><span class="n">dp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 获取文件属性失败
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">lstat</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">statbuf</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">(</span><span class="nf">func</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">statbuf</span><span class="p">,</span> <span class="n">FTW_NS</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 如果是普通文件，执行重命名逻辑
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">S_ISDIR</span><span class="p">(</span><span class="n">statbuf</span><span class="p">.</span><span class="n">st_mode</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">(</span><span class="nf">func</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">statbuf</span><span class="p">,</span> <span class="n">FTW_F</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 如果是目录，先执行回调（无实际操作）
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">((</span><span class="n">ret</span> <span class="o">=</span> <span class="nf">func</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">statbuf</span><span class="p">,</span> <span class="n">FTW_D</span><span class="p">))</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">(</span><span class="n">ret</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 拼接子目录路径
</span></span></span><span class="line"><span class="cl">    <span class="n">ptr</span> <span class="o">=</span> <span class="n">fullpath</span> <span class="o">+</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">fullpath</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="n">ptr</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;/&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 打开目录失败
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">((</span><span class="n">dp</span> <span class="o">=</span> <span class="nf">opendir</span><span class="p">(</span><span class="n">fullpath</span><span class="p">))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">(</span><span class="nf">func</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">statbuf</span><span class="p">,</span> <span class="n">FTW_DNR</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 遍历目录下的所有文件/子目录
</span></span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">dirp</span> <span class="o">=</span> <span class="nf">readdir</span><span class="p">(</span><span class="n">dp</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 跳过.和..
</span></span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nf">strcmp</span><span class="p">(</span><span class="n">dirp</span><span class="o">-&gt;</span><span class="n">d_name</span><span class="p">,</span> <span class="s">&#34;.&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nf">strcmp</span><span class="p">(</span><span class="n">dirp</span><span class="o">-&gt;</span><span class="n">d_name</span><span class="p">,</span> <span class="s">&#34;..&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// 拼接子文件路径
</span></span></span><span class="line"><span class="cl">        <span class="nf">strcpy</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">dirp</span><span class="o">-&gt;</span><span class="n">d_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 递归处理子文件/子目录
</span></span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">((</span><span class="n">ret</span> <span class="o">=</span> <span class="nf">dopath</span><span class="p">(</span><span class="n">func</span><span class="p">))</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 恢复路径（移除最后拼接的子文件名）
</span></span></span><span class="line"><span class="cl">    <span class="n">ptr</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 关闭目录
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">closedir</span><span class="p">(</span><span class="n">dp</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nf">err_ret</span><span class="p">(</span><span class="s">&#34;无法关闭目录: %s&#34;</span><span class="p">,</span> <span class="n">fullpath</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span><span class="p">(</span><span class="n">ret</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 查找目标文件并将其重命名为pass
</span></span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">int</span> <span class="nf">myfunc_rename</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">pathname</span><span class="p">,</span> <span class="k">const</span> <span class="k">struct</span> <span class="n">stat</span> <span class="o">*</span><span class="n">statptr</span><span class="p">,</span> <span class="kt">int</span> <span class="n">type</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 仅处理普通文件
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">type</span> <span class="o">!=</span> <span class="n">FTW_F</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 提取文件名（路径最后一个/后的部分）
</span></span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="o">*</span><span class="n">filename</span> <span class="o">=</span> <span class="nf">strrchr</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="sc">&#39;/&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">filename</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">filename</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">pathname</span><span class="p">;</span>  <span class="c1">// 无/，直接是文件名
</span></span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">filename</span><span class="o">++</span><span class="p">;</span>  <span class="c1">// 跳过/，指向实际文件名
</span></span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 匹配到目标文件，执行重命名
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">strcmp</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">target_filename</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// 拼接新路径：原目录 + /pass
</span></span></span><span class="line"><span class="cl">        <span class="kt">char</span> <span class="n">new_path</span><span class="p">[</span><span class="n">PATH_MAX</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="nf">strncpy</span><span class="p">(</span><span class="n">new_path</span><span class="p">,</span> <span class="n">pathname</span><span class="p">,</span> <span class="nf">strrchr</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="sc">&#39;/&#39;</span><span class="p">)</span> <span class="o">-</span> <span class="n">pathname</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">strcat</span><span class="p">(</span><span class="n">new_path</span><span class="p">,</span> <span class="s">&#34;pass&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// 执行重命名
</span></span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nf">rename</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="n">new_path</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;成功重命名: %s -&gt; %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">pathname</span><span class="p">,</span> <span class="n">new_path</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="n">rename_count</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nf">err_ret</span><span class="p">(</span><span class="s">&#34;重命名失败: %s&#34;</span><span class="p">,</span> <span class="n">pathname</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<h1 id="unix系统中路径的操作与修改">UNIX系统中路径的操作与修改</h1>
<p>这个程序实现了在指定目录下查找并重命名特定文件的功能，展示了多种路径操作技术。</p>
<h2 id="一unix路径的基本表示">一、UNIX路径的基本表示</h2>
<p>在UNIX系统中，路径是用于标识文件或目录位置的字符串：</p>
<ul>
<li>使用正斜杠 <code>/</code> 作为路径分隔符</li>
<li>绝对路径从根目录 <code>/</code> 开始</li>
<li>相对路径从当前工作目录开始</li>
<li><code>.</code> 表示当前目录，<code>..</code> 表示父目录</li>
</ul>
<h2 id="二程序中的路径操作技术">二、程序中的路径操作技术</h2>
<h3 id="1-路径缓冲区管理">1. 路径缓冲区管理</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fullpath</span><span class="p">;</span>  <span class="c1">// 存储文件完整路径
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>程序使用 <code>fullpath</code> 变量存储文件的完整路径，通过 <code>path_alloc</code> 函数（来自apue库）安全地分配足够大的缓冲区：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="n">fullpath</span> <span class="o">=</span> <span class="nf">path_alloc</span><span class="p">(</span><span class="o">&amp;</span><span class="n">len</span><span class="p">);</span>  <span class="c1">// 从apue库获取路径缓冲区
</span></span></span><span class="line"><span class="cl"><span class="nf">strncpy</span><span class="p">(</span><span class="n">fullpath</span><span class="p">,</span> <span class="n">pathname</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="n">fullpath</span><span class="p">[</span><span class="n">len</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>          <span class="c1">// 确保字符串终止
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>这确保了路径操作时有足够的空间，避免缓冲区溢出。</p>
<h3 id="2-目录遍历与路径构建">2. 目录遍历与路径构建</h3>
<p>程序使用深度优先遍历（DFS）方式遍历目录树：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 拼接子目录路径
</span></span></span><span class="line"><span class="cl"><span class="n">ptr</span> <span class="o">=</span> <span class="n">fullpath</span> <span class="o">+</span> <span class="nf">strlen</span><span class="p">(</span><span class="n">fullpath</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="o">*</span><span class="n">ptr</span><span class="o">++</span> <span class="o">=</span> <span class="sc">&#39;/&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 遍历目录下的所有文件/子目录
</span></span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="p">((</span><span class="n">dirp</span> <span class="o">=</span> <span class="nf">readdir</span><span class="p">(</span><span class="n">dp</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 跳过.和..
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nf">strcmp</span><span class="p">(</span><span class="n">dirp</span><span class="o">-&gt;</span><span class="n">d_name</span><span class="p">,</span> <span class="s">&#34;.&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nf">strcmp</span><span class="p">(</span><span class="n">dirp</span><span class="o">-&gt;</span><span class="n">d_name</span><span class="p">,</span> <span class="s">&#34;..&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">continue</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// 拼接子文件路径
</span></span></span><span class="line"><span class="cl">    <span class="nf">strcpy</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">dirp</span><span class="o">-&gt;</span><span class="n">d_name</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 递归处理子文件/子目录
</span></span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">((</span><span class="n">ret</span> <span class="o">=</span> <span class="nf">dopath</span><span class="p">(</span><span class="n">func</span><span class="p">))</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 恢复路径（移除最后拼接的子文件名）
</span></span></span><span class="line"><span class="cl"><span class="n">ptr</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这段代码展示了如何动态构建和恢复路径：</p>
<ul>
<li>先获取当前路径长度，在末尾添加 <code>/</code></li>
<li>将子文件名拼接到路径末尾</li>
<li>递归处理后，通过将最后一个 <code>/</code> 设为 <code>\0</code> 恢复路径</li>
</ul>
<h3 id="3-文件名提取">3. 文件名提取</h3>
<p>程序使用 <code>strrchr</code> 函数提取路径中的文件名：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 提取文件名（路径最后一个/后的部分）
</span></span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="o">*</span><span class="n">filename</span> <span class="o">=</span> <span class="nf">strrchr</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="sc">&#39;/&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">filename</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">filename</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">pathname</span><span class="p">;</span>  <span class="c1">// 无/，直接是文件名
</span></span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">filename</span><span class="o">++</span><span class="p">;</span>  <span class="c1">// 跳过/，指向实际文件名
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>strrchr</code> 函数查找字符串中最后一次出现指定字符（这里是 <code>/</code>）的位置，通过这种方式可以从完整路径中分离出文件名。</p>
<h3 id="4-文件重命名操作">4. 文件重命名操作</h3>
<p>程序使用 <code>rename</code> 函数进行文件重命名，这涉及到路径的修改：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="c1">// 拼接新路径：原目录 + /pass
</span></span></span><span class="line"><span class="cl"><span class="kt">char</span> <span class="n">new_path</span><span class="p">[</span><span class="n">PATH_MAX</span><span class="p">];</span>
</span></span><span class="line"><span class="cl"><span class="nf">strncpy</span><span class="p">(</span><span class="n">new_path</span><span class="p">,</span> <span class="n">pathname</span><span class="p">,</span> <span class="nf">strrchr</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="sc">&#39;/&#39;</span><span class="p">)</span> <span class="o">-</span> <span class="n">pathname</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="nf">strcat</span><span class="p">(</span><span class="n">new_path</span><span class="p">,</span> <span class="s">&#34;pass&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 执行重命名
</span></span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nf">rename</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="n">new_path</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;成功重命名: %s -&gt; %s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">pathname</span><span class="p">,</span> <span class="n">new_path</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="n">rename_count</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nf">err_ret</span><span class="p">(</span><span class="s">&#34;重命名失败: %s&#34;</span><span class="p">,</span> <span class="n">pathname</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这段代码实现了如何构建新路径：</p>
<ul>
<li>首先复制原路径中目录部分（从开头到最后一个 <code>/</code>）</li>
<li>然后在目录路径后拼接新的文件名 &ldquo;pass&rdquo;</li>
<li>使用 <code>rename</code> 函数将原文件路径修改为新路径</li>
</ul>
<h2 id="总结">总结</h2>
<p>UNIX系统中路径的操作和修改是通过字符串处理函数、目录操作函数和文件系统调用的组合实现的。程序展示了如何构建路径、遍历目录树并修改文件路径。</p>
<p>通过学习这些技术，我们可以更好地理解UNIX系统中文件系统的组织方式，以及如何在程序中有效地操作和修改路径。</p>
]]></content:encoded></item><item><title>判断质数汇编程序编写</title><link>https://farmer3-c.github.io/posts/post-2026-01-12/</link><pubDate>Mon, 12 Jan 2026 17:54:28 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2026-01-12/</guid><description>&lt;p&gt;以下面的代码为例，说明如何用汇编语言判断一个数是否为素数，从而进行汇编语言的学习。&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠代码&lt;/summary&gt;
&lt;pre&gt;&lt;code class="language-asm"&gt;
.MODEL SMALL
.STACK 100H
&lt;p&gt;.DATA
msg_input DB &amp;lsquo;Please input a number: $'
msg_prime DB 0DH, 0AH, 'It is a prime number.$&amp;rsquo;
msg_not DB 0DH, 0AH, &amp;lsquo;It is not a prime number.$&amp;rsquo;
num DW 0&lt;/p&gt;
&lt;p&gt;.CODE
START:
MOV AX, @DATA
MOV DS, AX&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;; 1. 显示输入提示
LEA DX, msg_input
MOV AH, 09H
INT 21H
; 2. 读取数字 (读取一个十进制数)
CALL READ_NUM
MOV num, AX
; 3. 判断素数逻辑
; 如果 n &amp;lt; 2，不是素数
CMP AX, 2
JL NOT_PRIME
JE IS_PRIME ; 2 是素数
; 循环判断: 从 2 到 n-1
MOV CX, 2 ; CX 是除数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CHECK_LOOP:
MOV AX, num
XOR DX, DX ; 清除高位
DIV CX ; AX / CX, 余数在 DX&lt;/p&gt;</description><content:encoded><![CDATA[<p>以下面的代码为例，说明如何用汇编语言判断一个数是否为素数，从而进行汇编语言的学习。</p>
<details>
<summary>点击展开/折叠代码</summary>
<pre><code class="language-asm">
.MODEL SMALL
.STACK 100H
<p>.DATA
msg_input  DB &lsquo;Please input a number: $'
    msg_prime  DB 0DH, 0AH, 'It is a prime number.$&rsquo;
msg_not    DB 0DH, 0AH, &lsquo;It is not a prime number.$&rsquo;
num        DW 0</p>
<p>.CODE
START:
MOV AX, @DATA
MOV DS, AX</p>
<pre><code>; 1. 显示输入提示  
LEA DX, msg_input
MOV AH, 09H
INT 21H

; 2. 读取数字 (读取一个十进制数)
CALL READ_NUM
MOV num, AX

; 3. 判断素数逻辑
; 如果 n &lt; 2，不是素数
CMP AX, 2
JL  NOT_PRIME
JE  IS_PRIME      ; 2 是素数

; 循环判断: 从 2 到 n-1
MOV CX, 2         ; CX 是除数
</code></pre>
<p>CHECK_LOOP:
MOV AX, num
XOR DX, DX        ; 清除高位
DIV CX            ; AX / CX, 余数在 DX</p>
<pre><code>CMP DX, 0         ; 如果余数为 0，说明被整除
JZ  NOT_PRIME

INC CX
MOV AX, CX
MUL AX            ; 计算 CX * CX
CMP AX, num       ; 只需检查到 根号 n 即可优化
JA  IS_PRIME      ; 如果 CX*CX &gt; num 还没除尽，就是素数

JMP CHECK_LOOP
</code></pre>
<p>IS_PRIME:
LEA DX, msg_prime
JMP DISPLAY</p>
<p>NOT_PRIME:
LEA DX, msg_not</p>
<p>DISPLAY:
MOV AH, 09H
INT 21H</p>
<pre><code>; 4. 退出程序
MOV AH, 4CH
INT 21H
</code></pre>
<p>; &mdash; 子程序：读取十进制数字 &mdash;
READ_NUM PROC
XOR BX, BX
READ_CHAR:
MOV AH, 01H       ; 读取字符到 AL
INT 21H
CMP AL, 0DH       ; 回车键退出
JZ  DONE_READ
SUB AL, &lsquo;0&rsquo;       ; 转换为数字
JL  DONE_READ
CMP AL, 9
JG  DONE_READ</p>
<pre><code>MOV AH, 0
PUSH AX
MOV AX, 10
MUL BX            ; BX = BX * 10
POP DX
ADD AX, DX
MOV BX, AX
JMP READ_CHAR
</code></pre>
<p>DONE_READ:
MOV AX, BX
RET
READ_NUM ENDP</p>
<p>END START
</code></pre></p>
</details>
<ul>
<li>
<p>首先是汇编程序的整体结构。</p>
<ul>
<li><code>.MODEL SMALL</code>：指定了程序的内存模型为 16 位。</li>
<li><code>.STACK 100H</code>：定义了堆栈段的大小为 100H。</li>
<li><code>.DATA</code>：定义了数据段，用于存储程序中的变量和常量。</li>
<li><code>.CODE</code>：定义了代码段，用于存储程序的指令。</li>
<li><code>START</code>：程序的入口点。</li>
<li><code>END START</code>：结束程序的定义。</li>
</ul>
</li>
<li>
<p>数据段：</p>
<ul>
<li><code>msg_input</code>：提示用户输入的字符串。</li>
<li><code>msg_prime</code>：输出素数的字符串。</li>
<li><code>msg_not</code>：输出非素数的字符串。</li>
<li><code>num</code>：用于存储用户输入的数字。</li>
</ul>
</li>
<li>
<p>代码段：</p>
<ul>
<li><code>START</code>：程序的入口点。</li>
<li><code>MOV AX, @DATA</code>：将数据段的地址加载到 AX 寄存器中。</li>
<li><code>MOV DS, AX</code>：将 AX 寄存器中的地址加载到 DS 寄存器中，设置数据段。</li>
<li>显示输入提示：
<ul>
<li><code>LEA DX, msg_input</code>：将 <code>msg_input</code> 的地址加载到 DX 寄存器中。</li>
<li><code>MOV AH, 09H</code>：设置 AH 寄存器为 09H，用于显示字符串。</li>
<li><code>INT 21H</code>：调用中断 21H，执行显示字符串的操作。</li>
</ul>
</li>
<li>读取数字：
<ul>
<li>调用 <code>READ_NUM</code> 子程序，将用户输入的数字存储在 <code>num</code> 中。</li>
</ul>
</li>
<li>判断素数逻辑：
<ul>
<li><code>CMP AX, 2</code>：比较 <code>AX</code> 寄存器中的值和 2。</li>
<li><code>JL NOT_PRIME</code>：如果 <code>AX</code> 小于 2，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li><code>JE IS_PRIME</code>：如果 <code>AX</code> 等于 2，跳转到 <code>IS_PRIME</code> 标签。</li>
<li>循环判断：
<ul>
<li><code>MOV CX, 2</code>：将 2 加载到 CX 寄存器中，作为除数。</li>
<li><code>CHECK_LOOP</code>：循环标签。</li>
<li><code>MOV AX, num</code>：将 <code>num</code> 中的值加载到 AX 寄存器中。</li>
<li><code>XOR DX, DX</code>：将 DX 寄存器清零，用于存储余数。</li>
<li><code>DIV CX</code>：将 AX 寄存器中的值除以 CX 寄存器中的值，余数存储在 DX 寄存器中。</li>
<li><code>CMP DX, 0</code>：比较 DX 寄存器中的值和 0。</li>
<li><code>JZ NOT_PRIME</code>：如果 DX 等于 0，说明被整除，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li><code>INC CX</code>：将 CX 寄存器中的值加 1。</li>
<li><code>MOV AX, CX</code>：将 CX 寄存器中的值加载到 AX 寄存器中。</li>
<li><code>MUL AX</code>：将 AX 寄存器中的值乘以自身，结果存储在 AX 寄存器中。</li>
<li><code>CMP AX, num</code>：比较 AX 寄存器中的值和 <code>num</code> 中的值。</li>
<li><code>JA IS_PRIME</code>：如果 AX 大于 <code>num</code>，跳转到 <code>IS_PRIME</code> 标签。</li>
<li><code>JMP CHECK_LOOP</code>：跳转到 <code>CHECK_LOOP</code> 标签，继续循环。</li>
</ul>
</li>
<li><code>IS_PRIME</code>：如果是素数，跳转到 <code>IS_PRIME</code> 标签。</li>
<li><code>NOT_PRIME</code>：如果不是素数，跳转到 <code>NOT_PRIME</code> 标签。</li>
</ul>
</li>
<li>显示结果：
<ul>
<li>根据判断结果，加载相应的字符串到 DX 寄存器中。</li>
<li><code>MOV AH, 09H</code>：设置 AH 寄存器为 09H，用于显示字符串。</li>
<li><code>INT 21H</code>：调用中断 21H，执行显示字符串的操作。</li>
</ul>
</li>
<li>退出程序：
<ul>
<li><code>MOV AH, 4CH</code>：设置 AH 寄存器为 4CH，用于退出程序。</li>
<li><code>INT 21H</code>：调用中断 21H，执行退出程序的操作。</li>
</ul>
</li>
</ul>
</li>
<li>
<p>子程序：</p>
<ul>
<li><code>READ_NUM</code>：用于读取用户输入的数字。
<ul>
<li><code>XOR BX, BX</code>：将 BX 寄存器清零，用于存储数字。</li>
<li><code>READ_CHAR</code>：循环标签。</li>
<li><code>MOV AH, 01H</code>：设置 AH 寄存器为 01H，用于读取字符。</li>
<li><code>INT 21H</code>：调用中断 21H，执行读取字符的操作。</li>
<li><code>CMP AL, 0DH</code>：比较 AL 寄存器中的值和回车键的 ASCII 码。</li>
<li><code>JZ DONE_READ</code>：如果 AL 等于回车键的 ASCII 码，跳转到 <code>DONE_READ</code> 标签。</li>
<li><code>SUB AL, '0'</code>：将 AL 寄存器中的值减去 &lsquo;0&rsquo; 的 ASCII 码，转换为数字。</li>
<li><code>CMP AL, 9</code>：比较 AL 寄存器中的值和 9。</li>
<li><code>JG DONE_READ</code>：如果 AL 大于 9，跳转到 <code>DONE_READ</code> 标签。</li>
<li><code>MOV AH, 0</code>：将 AH 寄存器清零。</li>
<li><code>PUSH AX</code>：将 AX 寄存器中的值压入堆栈。</li>
<li><code>MOV AX, 10</code>：将 10 加载到 AX 寄存器中。</li>
<li><code>MUL BX</code>：将 BX 寄存器中的值乘以 AX 寄存器中的值，结果存储在 AX 寄存器中。</li>
<li><code>POP DX</code>：将堆栈中的值弹出到 DX 寄存器中。</li>
<li><code>ADD AX, DX</code>：将 AX 寄存器中的值加上 DX 寄存器中的值，结果存储在 AX 寄存器中。</li>
<li><code>MOV BX, AX</code>：将 AX 寄存器中的值加载到 BX 寄存器中。</li>
<li><code>JMP READ_CHAR</code>：跳转到 <code>READ_CHAR</code> 标签，继续循环。</li>
<li><code>DONE_READ</code>：读取数字完成，跳转到 <code>DONE_READ</code> 标签。</li>
<li><code>MOV AX, BX</code>：将 BX 寄存器中的值加载到 AX 寄存器中。</li>
<li><code>RET</code>：返回。</li>
</ul>
</li>
</ul>
</li>
<li>
<p>总结：</p>
<ul>
<li>该程序实现了判断一个数是否为素数的功能。</li>
<li>首先，程序显示输入提示，然后调用 <code>READ_NUM</code> 子程序读取用户输入的数字。</li>
<li>接下来，程序判断输入的数字是否小于 2，如果是，则不是素数，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li>如果输入的数字等于 2，则是素数，跳转到 <code>IS_PRIME</code> 标签。</li>
<li>如果输入的数字大于 2，则进入循环判断。</li>
<li>在循环中，程序将输入的数字除以从 2 到 <code>num-1</code> 的每个数，如果存在能整除的数，则不是素数，跳转到 <code>NOT_PRIME</code> 标签。</li>
<li>如果循环结束后没有找到能整除的数，则是素数，跳转到 <code>IS_PRIME</code> 标签。</li>
<li>在 <code>IS_PRIME</code> 标签中，程序显示素数的字符串，并跳转到 <code>DISPLAY</code> 标签。</li>
<li>在 <code>NOT_PRIME</code> 标签中，程序显示非素数的字符串，并跳转到 <code>DISPLAY</code> 标签。</li>
<li>在 <code>DISPLAY</code> 标签中，程序调用中断 21H，执行显示字符串的操作。</li>
<li>最后，程序调用中断 21H，执行退出程序的操作。</li>
<li>该程序使用了堆栈来存储临时变量，以及一些寄存器来保存中间结果。</li>
<li>该程序的时间复杂度为 O(sqrt(n))，其中 n 为输入的数字。</li>
<li>该程序的空间复杂度为 O(1)，因为只使用了常数个变量。</li>
</ul>
</li>
</ul>
<p>设计编写汇编程序要注意的是合理分配堆栈空间，避免栈溢出。同时，要注意寄存器的使用，避免寄存器冲突。另外，要注意程序的可读性和可维护性，避免出现冗余代码。</p>
<hr>
<h2 id="参考">参考</h2>
<p><a href="/pdf/%E7%8E%8B%E7%88%BD%E7%BD%91%E8%AF%BEPPT.pdf">王爽网课</a></p>
]]></content:encoded></item><item><title>convex review</title><link>https://farmer3-c.github.io/posts/convex-review/</link><pubDate>Thu, 11 Dec 2025 12:00:19 +0800</pubDate><guid>https://farmer3-c.github.io/posts/convex-review/</guid><description>&lt;h1 id="lecture-1-unconstrained-optimization-for-differentiable-functions"&gt;Lecture 1: Unconstrained Optimization for Differentiable Functions&lt;/h1&gt;
&lt;h4 id="几个无限制可微问题的优化"&gt;几个无限制可微问题的优化：&lt;/h4&gt;
&lt;p&gt;对于一般的函数求极值问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个变量的函数可以求导，极值一般在导函数的零点。
如：求极小值$f(x)=x^2-1$&lt;/li&gt;
&lt;li&gt;多个变量的函数可以求偏导，极值一般在偏导函数的零点。
如：求极值$f(x,y)=x^3-y^3+3x^2+3y^2-9x$
对得到的四个驻点进行的二阶导数检验（Hessian 判别法）&lt;/li&gt;
&lt;/ul&gt;
$$|H|=f_{xx}f_{yy}-(f_{xy})^2$$&lt;p&gt;令$a=f_{xx}$&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 若 ∣H∣&amp;gt;0且 a&amp;gt;0 → 局部极小值（Ext. small）
若 ∣H∣&amp;gt;0 且 a&amp;lt;0 → 局部极大值（Ext. large）
若 ∣H∣&amp;lt;0 → 鞍点（uncertain，即非极值点）
若 ∣H∣=0 → 无法判断（需要更高阶检验）
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="梯度下降求极大极小值"&gt;梯度下降求极大/极小值：&lt;/h4&gt;
&lt;p&gt;对一个复杂的函数求极值是一件困难的事，梯度下降可以使它变得简单。&lt;/p&gt;
$$
\begin{aligned}
f(x) &amp;\approx f(x_0)+(x-x_0)f'(x_0) \\
f(x) &amp;= f(x_0)-\Delta xf'(x_0)
\end{aligned}
$$&lt;p&gt;$\implies x=x_0-\Delta x$&lt;/p&gt;
&lt;p&gt;设置一个学习率a,或者叫步长，&lt;/p&gt;
&lt;p&gt;$\Delta x=a f'(x_0)$&lt;/p&gt;
&lt;p&gt;然后就是一个迭代的过程：&lt;/p&gt;
&lt;p&gt;$x_{k+1}=x_k-\Delta x_k$&lt;/p&gt;
&lt;p&gt;$f'(x_k)=0$时到达极值点。&lt;/p&gt;
&lt;h4 id="牛顿法-i解决等式限制的优化"&gt;牛顿法-I解决等式限制的优化：&lt;/h4&gt;
&lt;p&gt;思想也是迭代。&lt;/p&gt;
&lt;p&gt;如：$e^x-2x^2+3x-4=0$&lt;/p&gt;
&lt;p&gt;迭代$(x_n,f(x_n))$&lt;/p&gt;
&lt;p&gt;${y=f'(x_n)(x-x_n)+f(x_n)} \xrightarrow {\text{y → 0}}{x=x_n-\frac{f(x_n)}{f'(x_n)}}$&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="lecture-1-unconstrained-optimization-for-differentiable-functions">Lecture 1: Unconstrained Optimization for Differentiable Functions</h1>
<h4 id="几个无限制可微问题的优化">几个无限制可微问题的优化：</h4>
<p>对于一般的函数求极值问题：</p>
<ul>
<li>一个变量的函数可以求导，极值一般在导函数的零点。
如：求极小值$f(x)=x^2-1$</li>
<li>多个变量的函数可以求偏导，极值一般在偏导函数的零点。
如：求极值$f(x,y)=x^3-y^3+3x^2+3y^2-9x$
对得到的四个驻点进行的二阶导数检验（Hessian 判别法）</li>
</ul>
$$|H|=f_{xx}f_{yy}-(f_{xy})^2$$<p>令$a=f_{xx}$</p>
<pre><code>    若 ∣H∣&gt;0且 a&gt;0 → 局部极小值（Ext. small）

    若 ∣H∣&gt;0 且 a&lt;0 → 局部极大值（Ext. large）

    若 ∣H∣&lt;0 → 鞍点（uncertain，即非极值点）

    若 ∣H∣=0 → 无法判断（需要更高阶检验）
</code></pre>
<h4 id="梯度下降求极大极小值">梯度下降求极大/极小值：</h4>
<p>对一个复杂的函数求极值是一件困难的事，梯度下降可以使它变得简单。</p>
$$
\begin{aligned}
f(x) &\approx f(x_0)+(x-x_0)f'(x_0) \\
f(x) &= f(x_0)-\Delta xf'(x_0)
\end{aligned}
$$<p>$\implies x=x_0-\Delta x$</p>
<p>设置一个学习率a,或者叫步长，</p>
<p>$\Delta x=a f'(x_0)$</p>
<p>然后就是一个迭代的过程：</p>
<p>$x_{k+1}=x_k-\Delta x_k$</p>
<p>$f'(x_k)=0$时到达极值点。</p>
<h4 id="牛顿法-i解决等式限制的优化">牛顿法-I解决等式限制的优化：</h4>
<p>思想也是迭代。</p>
<p>如：$e^x-2x^2+3x-4=0$</p>
<p>迭代$(x_n,f(x_n))$</p>
<p>${y=f'(x_n)(x-x_n)+f(x_n)} \xrightarrow {\text{y → 0}}{x=x_n-\frac{f(x_n)}{f'(x_n)}}$</p>
<p>所以：</p>
<p>$x_{k+1}=x_k-\frac{f(x_k)}{f'(x_k)}$</p>
<p>当$f'(x_k) or f(x_k) $接近0时，停止迭代。</p>
<h4 id="牛顿法-ii解决求极小值优化">牛顿法-II解决求极小值优化：</h4>
<p>定义$f(x),x_k,t$,t是一个很小的数。</p>
<p>泰勒展开：</p>
<p>$f(x_k+t)=f(x_k)+t f'(x_k)+f''(x_k)(t^2)$</p>
<p>对t求导：</p>
<p>$f'(x_k+t)=f'(x_k)+t f''(x_k)$</p>
<p>$t=-f'(x_k)/f''(x_k)$</p>
<p>故迭代：</p>
<p>$x_{k+1}=x_0$</p>
<p>$x_{k+1}=x_k+t$</p>
<h1 id="lecture-2-introduction-to-linear-programing">Lecture 2: Introduction to Linear Programing</h1>
<h4 id="线性规划的问题">线性规划的问题</h4>
<p>一般的，线性规划问题包含目的，也就是求最大值还是最小值，</p>
<p>约束条件，也就是变量的取值范围，</p>
<p>目标函数，也就是变量的取值。</p>
<p>如：</p>
<p>$max. f(x)$</p>
<p>$s.t. Ax=b$</p>
<p>$x \in R^n$</p>
<p>建立了类似上面的模型之后，我们可以用线性规划的方法来求解。有可行解时，可行解域常常是一个凸集，最优解在可行解域的边界上（顶点）。</p>
<h4 id="线性规划的数值解">线性规划的数值解</h4>
<p>• In the year of 1939, L. Kantorovich proposed LP</p>
<p>• In the year of 1947, G. Danzig invented “Simplex” method</p>
<p>• In the year of 1944, John V. Neumann proposed game theory</p>
<p>• In 1984, Narendra Karmarkar proposed “inner-point” method of LP</p>
<p>• “Inner-point” guarantees to solve LP in polynomial time complexity</p>
<p>LP问题在$s.t. Ax \leq b$时，可以引入松弛变量使得形如$s.t. Ax+S=b$</p>
<h1 id="lecture-3-simplex-method">Lecture 3: Simplex Method</h1>
<h4 id="用单纯形表解线性规划">用单纯形表解线性规划</h4>
<p>通常给定形式如下：</p>
<p>$max. f(x)$</p>
<p>$s.t. Ax \leq b$</p>
<p>$x \geq 0$</p>
<p>我们可以将其转化为标准形式：</p>
<p>$max. Z= f(x)$</p>
<p>$s.t. Ax+S=b$</p>
<p>$x \geq 0$</p>
<p>然后我们可以用单纯形表来求解。</p>
<p>$Z- f(x)=0$</p>
<p>$s.t. Ax+S=b$</p>
<p>$x \geq 0，s \geq 0$</p>
<p>1.选择在目标函数行（第 0 行）中，系数最负的项，作为入基变量。</p>
<p>2.选择在约束条件列中，解最小的项，作为出基变量。</p>
<p>3.将出基变量的系数化为 1，其余列系数化为 0。</p>
<p>4.将目标函数行中，系数最负的项系数化为 0。</p>
<p>5.重复 1-4 步，直到对应于非基变量的底部行（目标函数行，通常标记为&rsquo;z&rsquo;）的所有项都是非负的（&gt;=0）。</p>
<p>特殊情况及停止条件：</p>
<p>1.无界解：如果选择一个进入变量（最大化时 z 行中为正，最小化时为负），但该变量在约束行中的所有项为零或负，则问题无界。</p>
<p>2.退化/停滞：可能在非基变量的 z 行中有一个零，但无法进行出基操作（离开变量的正比没有正值）。这并不总是最终停止的信号，但可能表示存在替代最优解或潜在的循环。</p>
<p>3.本质上，只要能够改进目标函数，就继续出基操作；一旦无法改进，就找到了最优解（或无界条件）。</p>
<h4 id="收敛和复杂度">收敛和复杂度</h4>
<p>如果单纯形法是非退化的（预期），顶点数量有限，那么最终会收敛到一个最优解。</p>
<p>但是，给定一个线性规划问题，令有n个变量，m个约束条件，从m个约束条件中选择n个来求一个基本解</p>
<p>$A \subset R^{m \times n},m \leq n$</p>
<p>在寻找基本解时，我们会从 n 列中选出 m 列，构成一个 m×m 的非奇异矩阵 B，这 m 列对应的变量叫做基变量，其他变量设为 0，解得到一组基变量的值，这组解称为一个基本解（如果满足非负约束，就是基本可行解）。</p>
<p>选择基变量就是选择 m 个列（从 n 列中选出），所以可能的基的数目为组合数：</p>
<p>$\begin{pmatrix}
n \newline
m
\end{pmatrix}$=$\frac{n!}{m!(n-m)!}$</p>
<p>这个数字可能会很大，所以单纯形法的复杂度是指数级别的。</p>
<h4 id="矩阵操作的单纯形法">矩阵操作的单纯形法</h4>
<p>大的LP问题应该用矩阵操作的单纯形法来求解。</p>
$$
\begin{aligned}
AX &= b \\
f &= CX \\
A &= [B \ N],\ C=[C_B \ C_N],\ X=[X_B \ X_N]^T \\
AX = b &\to X_B^T = B^{-1}b - B^{-1}NX_N^T \\
f &= C_BB^{-1}b - (C_BB^{-1}N - C_N)X_N^T \\
X_N = 0: &f \text{ is called the basic solution} \\
\text{if } X_N \text{ is negtive, } &\text{this basic solution can be improved}
\end{aligned}
$$<p>核心思想就是将变量分为基变量和非基变量，从而得到基矩阵和非基矩阵，然后用基矩阵的逆来求解非基变量的值，从而得到基本解。在基本解的基础上，我们可以通过矩阵操作来得到更优的基本解，直到基本解的非基变量的值都为非负，具体而言，通过对变量进行出基入基让基本解加的值尽可能大。</p>
<h1 id="lecture-4-two-phase-method-duality-for-lp">Lecture 4: Two-Phase Method, Duality for LP</h1>
<h4 id="两阶段单纯形法">两阶段单纯形法</h4>
<p>引入人工变量和松弛变量，一阶段问题是一个单纯形问题，二阶段问题是一个单纯形问题。</p>
<p>原问题的目标函数是：</p>
<p>$max. Z= f(x)$</p>
<p>$s.t. A_1 x \leq b$</p>
<p>$A_nx \geq b$</p>
<p>$x \geq 0$</p>
<p>引入人工变量和松弛变量，</p>
<p>$max. Z= f(x)$</p>
<p>$s.t. A_1 x +S_1= b$</p>
<p>&hellip;</p>
<p>$A_nx -S_n+a_n= b$</p>
<p>$x \geq 0，s \geq 0, a \geq0$</p>
<p>一阶段问题的目标函数是：</p>
<p>$min. z'=\sum_{i=1}^{n} a_i \ or\ max. z'=-\sum_{i=1}^{n} a_i$</p>
<p>$s.t. A_1 x +S_1= b$</p>
<p>&hellip;</p>
<p>$A_nx -S_n+a_n= b$</p>
<p>$x \geq 0，s \geq 0, a \geq0$</p>
<p>消掉$a_i$,继续使用单纯形法求解。</p>
<p>如果最小z&rsquo;=0，那么原问题有解，否则原问题无解。第二阶段则使用第一阶段得到的可行解和原始目标函数来找到原始问题的实际最优解。</p>
<p>二阶段问题的目标函数是：</p>
<p>$max. Z= f(x)$</p>
<p>$s.t. Ax+S=b$</p>
<p>$x \geq 0，s \geq 0$</p>
<p>可以证明：一阶段最优解为0$\iff$原问题有可行解</p>
<p>保持基变量在目标函数行系数为 0</p>
<h4 id="两阶段单纯形法的矩阵操作">两阶段单纯形法的矩阵操作</h4>
<p>与前一步类似</p>
<h4 id="无解和无界的问题">无解和无界的问题</h4>
<p>无解：不能找到一阶段最优解为0</p>
<p>无界：</p>
<ol>
<li>
<p>存在一个变量在目标函数行系数为正，但是在约束行中所有项都为零或负</p>
</li>
<li>
<p>存在一个变量在目标函数行系数为负，但是在约束行中所有项都为零或正</p>
</li>
</ol>
<h4 id="退化线性规划">退化线性规划</h4>
<p>如果有一个基变量为0，LP问题可能会退化</p>
<h4 id="线性规划中的对偶">线性规划中的对偶</h4>
<p>求max与求min是等价的，原计算矩阵转置即可</p>
<h4 id="网格最大流问题">网格最大流问题</h4>
<p>一条路径上的最小流量就是这条路径的最大流</p>
<h1 id="lecture-5-introduction-to-qp-and-convex-set">Lecture 5: Introduction to QP and Convex Set</h1>
<h4 id="例子">例子</h4>
<p>一段绳子，长度为8，分成3段，每段围成一个圆形，求最小面积和，</p>
$$
\begin{aligned}
\text{Min. } &x_1^2 + x_2^2 + x_3^2 \\
\text{s.t. } &x_1 + x_2 + x_3 = 8
\end{aligned}
$$<p>更一般的，</p>
$$
\begin{aligned}
\text{Min. } &\frac{1}{2}x^THx + c^Tx \\
\text{s.t. } &Ax = b
\end{aligned}
$$<p>定义lagrange函数
$L(x,\lambda)=x^THx+c^Tx+\lambda(Ax-b)$
对x，$\lambda$求导</p>
$$
\begin{aligned}
Hx + c + A\lambda &= 0 \\
Ax - b &= 0
\end{aligned}
$$<p>这两个方程就是原问题的约束条件，一般用拉格朗日乘子法来求解</p>
<p>二次规划问题：</p>
<ul>
<li>
<p>目标函数是二次函数</p>
</li>
<li>
<p>约束条件是线性函数</p>
</li>
</ul>
$$
\begin{aligned}
\text{Min. } &x^THx + c^Tx \\
\text{s.t. } &Ax = b \\
&x \geq 0
\end{aligned}
$$<p>Define Lagrangian function</p>
<p>$L(x,\lambda,\beta)=x^THx+c^Tx+\lambda(Ax-b)+\beta(x-0)$</p>
<p>This problem cannot be solved in the analytic way</p>
<h4 id="凸集">凸集</h4>
<p>凸集定义：</p>
<p>如果对于所有的x,y$\in C$，都有$0 \leq \alpha \leq 1$，都有$\alpha x+(1-\alpha)y \in C$，那么C就是一个凸集。</p>
<p>可以进行相关的灵活证明。</p>
<p>凸包定义：</p>
<p>对于一个集合C，它的凸包就是所有包含C的凸集的交集。</p>
<h4 id="保持集合凸性的操作">保持集合凸性的操作</h4>
<ol>
<li>
<p>凸集的凸包是凸集</p>
</li>
<li>
<p>凸集的交集也是凸集</p>
</li>
<li>
<p>凸集的并集也是凸集</p>
</li>
</ol>
<p>证明时想办法将一个集合变成凸集，依靠上面的操作。</p>
<h1 id="lecture-6-convex-fucntions">Lecture 6: Convex Fucntions</h1>
<h4 id="凸函数的定义">凸函数的定义</h4>
<p>对于一个函数$f(x)$，如果对于所有的x,y$\in C$，都有$f(\alpha x+(1-\alpha)y) \leq \alpha f(x)+(1-\alpha)f(y)$，那么$f(x)$就是一个凸函数。对应的，有凹函数（concave）。</p>
<p>函数可微，函数是凸函数$\iff$函数定义域是凸集，$\forall x,y\in R^n,f(y)\geq f(x)+\nabla f^T(x)(y-x)$</p>
<p>可以借助导数的定义证明上面的充分必要</p>
<h4 id="凸函数">凸函数</h4>
$$f(x)=x^TPx+q^Tx+r$$<p>定义域是凸集时，P是半正定矩阵 $\iff$ f(x)是凸函数</p>
<p><img alt="3" loading="lazy" src="/img/in-post/formula/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-26%20221103.png"></p>
<h4 id="变换保持凸性">变换保持凸性</h4>
<p>积分、仿射变换、指数变换、对数变换、幂次变换，可以使用求导证明凸性。</p>
<p>共轭函数：$f^*(y)=sup_{x\in domf}(y^Tx-f(x))$</p>
<p>原函数是否凸决定于共轭函数是否凸。</p>
<p>求上确界$f^*(y)$：</p>
<p>$f(x)=x^2$</p>
<p>对x求导：</p>
<p><img alt="4" loading="lazy" src="/img/in-post/formula/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-26%20221359.png"></p>
<h4 id="维持函数凸性的同时扩展">维持函数凸性的同时扩展</h4>
<p>将定义域之外的函数值设为+∞。</p>
<h1 id="lecture-7-convex-problems">Lecture 7: Convex Problems</h1>
$$
\begin{aligned}
\text{max. } &f_0(x) \\
\text{s.t. } &f_i(x) \leq 0 \\
&h_j(x) = 0
\end{aligned}
$$<p>优化问题是凸问题的定义：</p>
<ul>
<li>
<p>目标函数是凸函数</p>
</li>
<li>
<p>约束条件是凸函数</p>
</li>
<li>
<p>定义域是凸集</p>
</li>
</ul>
<h1 id="lecture-8-lagrangian-multiplier">Lecture 8: Lagrangian Multiplier</h1>
<p>拉格朗日算子：适用非凸优化、非线性优化、非二次优化</p>
<h4 id="例子-1">例子</h4>
$$
\min_{\substack{x_1, x_2 }} \left( x_1 + x_2  \right)\\
s.t. x_1^2 + x_2^2 -1\leq 0\\
\Downarrow \\
\min_{\substack{x_1, x_2 }} \left( x_1 + x_2 +P(x_1^2 + x_2^2 -1)  \right)
$$<p>
如果x1,x2超出限制，就赋给P一个大值。单纯的大值不可微，所以可以用拉格朗日算子。</p>
<p>$P(y)=\lambda y$
原例可转化为：
</p>
$$
\underset{x_1, x_2}{\text{Min.}} \, x_1 + x_2 + \underset{\lambda \geq 0}{\text{Max.}} \, \lambda(x_1^2 + x_2^2 - 1)\\
\Downarrow \\
\underset{\lambda \geq 0}{\text{Max.}} \,\underset{x_1, x_2}{\text{Min.}} \, x_1 + x_2 +  \lambda(x_1^2 + x_2^2 - 1)\\
\Downarrow \\
$$<p>
max和min可以交换计算的先后顺序，不影响。之后就是求导计算。</p>
<h4 id="拉格朗日算子">拉格朗日算子</h4>
<p>中心思想是将约束条件转化为目标函数的一部分，然后对目标函数求导。
</p>
$$
\begin{align}
\begin{split}
&\text{Max. } f(x,y,z) = 4y - 2z \\
&\text{s.t. } 
\begin{cases} 
2x - y - z = 1\\ 
x^2 + y^2 = 1 
\end{cases}\\
&\Rightarrow \\
&\begin{cases} 
g(x,y,z) = 2x - y - z - 1 = 0\\ 
h(x,y,z) = x^2 + y^2 - 1 = 0 
\end{cases}\\
&\Rightarrow \\
&L(x,y,z) = f(x,y,z) + \lambda g(x,y,z) + \mu h(x,y,z)
\end{split}
\end{align}
$$<p>Take partial derivative on $x$, $y$, $z$, $\lambda$, $\mu$,</p>
$$
\begin{align}
\begin{cases} 
L_x = f_x + \lambda g_x + \mu h_x = 0\\ 
L_y = f_y + \lambda g_y + \mu h_y = 0\\ 
L_z = f_z + \lambda g_z + \mu h_z = 0\\ 
L_\lambda = g_x = 0\\ 
L_\mu = h_x = 0 
\end{cases}
\Rightarrow
\begin{cases} 
2\lambda + 2x\mu = 0\\ 
4 - \lambda + 2y\mu = 0\\ 
-2 - \lambda = 0 
\end{cases}
\end{align}
$$$$
\begin{align}
\Rightarrow \quad \lambda = -2,\; x\mu = 2,\; y\mu = -3
\end{align}
$$$$\begin{align}
(x\mu)^2 + (y\mu)^2 = \mu^2(x^2 + y^2) = \mu^2 = 13
\end{align}$$$$\begin{align}
\begin{split}
&(1)\; \mu = -\sqrt{13}:\; 
x = -\frac{2}{\sqrt{13}},\; y = \frac{3}{\sqrt{13}},\; z = -\frac{7}{\sqrt{13}} - 1,\; f = 2\sqrt{13} + 2\\
&(2)\; \mu = \sqrt{13}:\; 
x = \frac{2}{\sqrt{13}},\; y = -\frac{3}{\sqrt{13}},\; z = \frac{7}{\sqrt{13}} - 1,\; f = 2 - 2\sqrt{13}
\end{split}
\end{align}
$$<p>So, maximize of $f$ is $2\sqrt{13} + 2$.</p>
<h1 id="lecture-9-lagrangian-dual-and-kkt-condition">Lecture 9: Lagrangian Dual and KKT Condition</h1>
<p>lagrange原问题：</p>
$$
L(\lambda, \mu) = f(x) + \sum_{i=1}^{m} \lambda_i g_i(x) + \sum_{j=1}^{p} \mu_j h_j(x)
$$<p>最优解为$p^*$</p>
<p>拉格朗日对偶定义为G：</p>
$$G(\lambda, \mu) = \inf_{\substack{x \in \mathcal{D}}} (x,\lambda, \mu) =\inf_{\substack{x \in \mathcal{D}}} f(x)+ \sum_{i=1}^{m} \lambda_i g_i(x) + \sum_{j=1}^{p} \mu_j h_j(x)$$<p>最优解为$d^*$</p>
<p>$p* \geq d^*$</p>
<h4 id="例子-2">例子</h4>
$$\underset{x}{\text{Min.}}\,c^Tx\\
s.t. \ Ax=b \ x \succeq 0$$$$lagrange\ function: L(x,\lambda,\mu)=c^Tx+\lambda(Ax-b)-\mu x\\
=-b^T\mu+(c+A^T\lambda-\mu)^Tx\\
\Downarrow\\
G(\lambda,\mu) =\inf_{\substack{x}}L(x,\lambda,\mu)=
 \left\{
 \begin{aligned}
 & -b^T\mu      & \text{if } A^T\mu-\lambda+c \\
 & -\infty       & \text{if } x = 0 \\
 \end{aligned}
 \right.\\
 p^* \geq d^* =-b^T\mu \ if \ A^T+v \succeq 0 
$$<h4 id="kkt条件">KKT条件</h4>
<ul>
<li>原问题的最优解是对偶问题的可行解</li>
<li>原问题的可行解是对偶问题的最优解

$$
L(\lambda, \mu) = f(x) + \sum_{i=1}^{m} \lambda_i g_i(x) + \sum_{j=1}^{p} \mu_j h_j(x)
$$</li>
</ul>
$$x^*,\lambda^*,\mu^*$$<p>是上问题的最优解</p>
<p>有</p>
$$
\frac{\partial L(x,\lambda^*,\mu^*)}{\partial x}\bigg|_{x=x^*} = \nabla f(x^*) + \sum_{i=1}^{m} \lambda_i^* \nabla g_i(x^*) + \sum_{j=1}^{p} \mu_j^* \nabla h_j(x^*) = 0
$$<h1 id="lecture-10-interior-point-method">Lecture 10: Interior Point Method</h1>
<h1 id="lecture-11-portfolio-problem">Lecture 11: Portfolio Problem</h1>
<h1 id="lecture-12-support-vector-machine">Lecture 12: Support Vector Machine</h1>
<h4 id="1-svm定义">1. SVM定义</h4>
<ul>
<li>一种<strong>监督学习分类模型</strong>，用于解决<strong>二分类问题</strong></li>
<li>目标是找到一个<strong>超平面</strong>，将两类数据分开，且<strong>间隔最大</strong></li>
</ul>
<h4 id="2-核心思想是最大化间隔">2. <strong>核心思想是最大化间隔</strong></h4>
<h6 id="函数间隔定义">函数间隔定义：</h6>
$$\gamma^{(i)} = y^{(i)}(w^T x^{(i)} + b)$$<h6 id="几何间隔">几何间隔：</h6>
$$
r^{(i)} = \frac{y^{(i)}(w^T x^{(i)} + b)}{\|w\|_2} = y^{(i)}\left(\frac{w^T}{\|w\|_2} x^{(i)} + \frac{b}{\|w\|_2}\right)
$$<h6 id="目标函数">目标函数：</h6>
$$
\max_{w,b} \min_{i=1,\ldots,m} r^{(i)}
$$<h4 id="3-模型建立过程">3. <strong>模型建立过程</strong></h4>
<h6 id="原始优化问题">原始优化问题：</h6>
$$
\begin{aligned}
\max_{w,b,\gamma} &\quad \gamma \\
\text{s.t.} &\quad y^{(i)}(w^T x^{(i)} + b) \geq \gamma, \quad i = 1,\ldots,m \\
&\quad \|w\|_2 = 1
\end{aligned}
$$<h6 id="转化为等价的凸优化问题">转化为等价的凸优化问题：</h6>
$$
\begin{aligned}
\min_{w,b} &\quad \frac{1}{2} \|w\|^2 \\
\text{s.t.} &\quad y^{(i)}(w^T x^{(i)} + b) \geq 1, \quad i = 1,\ldots,m
\end{aligned}
$$<h4 id="4-求解方法拉格朗日对偶">4. <strong>求解方法：拉格朗日对偶</strong></h4>
<h6 id="拉格朗日函数">拉格朗日函数：</h6>
$$
L(w,b,\alpha) = \frac{1}{2} \|w\|^2 - \sum_{i=1}^m \alpha_i \left[y^{(i)}(w^T x^{(i)} + b) - 1\right]
$$<p>
其中 </p>
$$\alpha_i \geq 0$$<p> 是拉格朗日乘子。</p>
<h6 id="对--和--求导">对 \(w\) 和 \(b\) 求导：</h6>
$$
\nabla_w L = w - \sum_{i=1}^m \alpha_i y^{(i)} x^{(i)} = 0 \quad \Rightarrow \quad w = \sum_{i=1}^m \alpha_i y^{(i)} x^{(i)}
$$$$
\frac{\partial L}{\partial b} = -\sum_{i=1}^m \alpha_i y^{(i)} = 0 \quad \Rightarrow \quad \sum_{i=1}^m \alpha_i y^{(i)} = 0
$$<h6 id="对偶问题">对偶问题：</h6>
<p>将 $ w$  的表达式代回拉格朗日函数，得到对偶问题：
</p>
$$
\begin{aligned}
\max_{\alpha} &\quad G(\alpha) = \sum_{i=1}^m \alpha_i - \frac{1}{2} \sum_{i,j=1}^m y^{(i)} y^{(j)} \alpha_i \alpha_j \langle x^{(i)}, x^{(j)} \rangle \\
\text{s.t.} &\quad \alpha_i \geq 0, \quad i = 1,\ldots,m \\
&\quad \sum_{i=1}^m \alpha_i y^{(i)} = 0
\end{aligned}
$$<h4 id="5-求解与解释">5. <strong>求解与解释</strong></h4>
<h6 id="求解方法">求解方法：</h6>
<ul>
<li>常用<strong>坐标上升法</strong>（Coordinate Ascent）</li>
<li>每次更新两个变量 $\alpha_i$ 和 $\alpha_j$</li>
</ul>
<h6 id="支持向量">支持向量：</h6>
<ul>
<li>$\alpha_i > 0$ 对应的样本称为<strong>支持向量</strong></li>
<li>最终分类超平面由支持向量决定</li>
</ul>
<h6 id="参数计算">参数计算：</h6>
$$
w = \sum_{i=1}^m \alpha_i y^{(i)} x^{(i)}
$$$$
b = -\frac{\max_{i:y^{(i)}=-1} w^T x^{(i)} + \min_{i:y^{(i)}=1} w^T x^{(i)}}{2}
$$<h4 id="历史">历史</h4>
<ul>
<li><strong>提出者</strong>：Vladimir Vapnik（1936-）和 Alexey Chervonenkis（1938-2014）</li>
<li><strong>地位</strong>：深度学习兴起前<strong>最流行的分类器</strong></li>
</ul>
<h1 id="lecture-13-integer-programming">Lecture 13: Integer Programming</h1>
<p>整数规划要求解得变量为整数，比LP限制多。</p>
<h4 id="典型问题">典型问题</h4>
<ul>
<li>
<p>Given variable x1, x2, x3, and x4 ∈ {0, 1}</p>
</li>
<li>
<p>The objective is to maximize 8x1 + 11x2 + 6x3 + 4x4</p>
</li>
<li>
<p>It is subjective to 5x1 + 7x2 + 4x3 + 3x4 ≤ 14</p>
</li>
</ul>
<h4 id="剪枝法">剪枝法</h4>
<p>原问题与LP相同，加入整数限制，先按LP计算得到解，IP得到的z值一定不大于LP得到的z值。
选择一个非整数变量（选择最接近x.5的变量）进行向上取整向下取整分情况讨论，对更大的z值进行继续讨论。</p>
<h4 id="切平面法">切平面法</h4>
<p>find out the cutting plane, namely the valid inequality.
如果变量非整数，可以加入新的松弛变量对原有的松弛变量约束。</p>
<ul>
<li>选择换出行：右端项为负（最负的）作为换出行</li>
<li>选择换入列：选择换入变量时，是用 R0 行的检验数（≥0）除以换出行中负系数的绝对值（或者说除以负数），然后选最小比值（绝对值最小）对应的变量换入。</li>
<li>选择换入变量：比值绝对值最小的变量换入</li>
</ul>
<p>另一种理解：</p>
<ul>
<li>对原问题进行lp求解，在对更接近x.5的变量$x_i$进行分析:
<ul>
<li>
<p>假设原等式：
$k_ix_i+a_is_i=\frac{4}{3} $</p>
<p>分解
$k_i,a_i$
得到
</p>
$$k_i=k_i^*+k_x,0<k_x<1,a_i=a_i^*+a_s,0<a_s<1$$<p>得到</p>
$$k_i^*x_i+a_i^*x_i-1=\frac{1}{3}-k_xs_i-a_sx_s$$<p>因为
</p>
$$\frac{1}{3}<1,0<a_s<1,0<k_x<1,x_i,s_i\geq 0\\
		k_i^*x_i+a_i^*x_i-1 \in I\\
		so \ \frac{1}{3}-k_xs_i-a_sx_s \in I \to \frac{1}{3}-k_xs_i-a_sx_s \leq 0$$<p>加入这个条件到原问题中，得到解，否则重复上述过程。</p>
<p>所以，对更接近x.5的变量$x_i$进行分析，得到的解一定是整数解。</p>
</li>
</ul>
</li>
</ul>
<h1 id="lecture-14-stochastic-programming">Lecture 14: Stochastic Programming</h1>
]]></content:encoded></item><item><title>matlab tutorial</title><link>https://farmer3-c.github.io/posts/matlab-tutorial/</link><pubDate>Sat, 22 Nov 2025 08:50:29 +0800</pubDate><guid>https://farmer3-c.github.io/posts/matlab-tutorial/</guid><description>matlab</description><content:encoded><![CDATA[<h1 id="1basic-arithmetic">1.Basic Arithmetic</h1>
<p>直接在命令行输入算式，结果存入ans变量中
如：</p>
<pre tabindex="0"><code>&gt;&gt; 1+2

ans =

     3
</code></pre><h1 id="2variables">2.Variables</h1>
<p>设置变量的值，存入系统中，之后可以调用</p>
<pre tabindex="0"><code>&gt;&gt; x=7

x =

     7

&gt;&gt; x+3

ans =

    10

&gt;&gt; 
</code></pre><h1 id="3change-format">3.Change Format</h1>
<p><strong>format [数据类型]</strong> 可以改变运算的结果数据类型</p>
<pre tabindex="0"><code>&gt;&gt; 1/3

ans =

    0.3333

&gt;&gt; format short
&gt;&gt; 1/3

ans =

    0.3333

&gt;&gt; format long
&gt;&gt; 1/3

ans =

   0.333333333333333

&gt;&gt; 
</code></pre><h1 id="4remove-variables">4.Remove Variables</h1>
<p><strong>clear [变量名]</strong> 用于清楚变量</p>
<pre tabindex="0"><code>&gt;&gt; x

x =

     7

&gt;&gt; clear x
&gt;&gt; x
函数或变量 &#39;x&#39; 无法识别。
 
&gt;&gt; 
</code></pre><h1 id="5clear-specific-variables">5.Clear Specific Variables</h1>
<p>高级一点的Remove Variables之类的用法</p>
<pre tabindex="0"><code>
&gt;&gt; x3=3

x3 =

     3

&gt;&gt; 
&gt;&gt; clear x*
&gt;&gt; x3=3

x3 =

     3

&gt;&gt; who

您的变量为:

ans  x3   

&gt;&gt; whos
  Name      Size            Bytes  Class     Attributes

  ans       1x1                 8  double              
  x3        1x1                 8  double              

&gt;&gt; 
</code></pre><h1 id="6-pre-defined-constants">6. Pre-Defined Constants</h1>
<p>系统中预定义的变量</p>
<pre tabindex="0"><code>&gt;&gt; pi

ans =

   3.141592653589793

&gt;&gt; format short
&gt;&gt; pi

ans =

    3.1416

&gt;&gt; inf

ans =

   Inf

&gt;&gt; nan

ans =

   NaN

&gt;&gt; i

ans =

   0.0000 + 1.0000i
</code></pre><h1 id="7-operational-operators">7. Operational Operators</h1>
<p>操作运算符</p>
<pre tabindex="0"><code>&gt;&gt; 2&gt;3

ans =

  logical

   0

&gt;&gt; 3&gt;2

ans =

  logical

   1

&gt;&gt; 2&gt;2

ans =

  logical

   0

&gt;&gt; 2&gt;=2

ans =

  logical

   1
</code></pre><h1 id="8-built-in-functions">8. Built-In Functions</h1>
<p>内置函数</p>
<pre tabindex="0"><code>&gt;&gt; sin(3.14)

ans =

    0.0016

&gt;&gt; cos(0)

ans =

     1

&gt;&gt; exp(1)

ans =

    2.7183

&gt;&gt; log(10)

ans =

    2.3026

&gt;&gt; abs(-2)

ans =

     2

&gt;&gt; 
</code></pre><h1 id="9-vectors--matrices">9. Vectors &amp; Matrices</h1>
<p>关于向量和矩阵的使用</p>
<pre tabindex="0"><code>&gt;&gt; a=[1 2 3 ;4 5 6 ;7 8 9]

a =

     1     2     3
     4     5     6
     7     8     9

&gt;&gt; whos
  Name      Size            Bytes  Class     Attributes

  a         3x3                72  double              
  ans       1x1                 8  double              
  x3        1x1                 8  double              

&gt;&gt; b=[1 2 3];
&gt;&gt; c=b&#39;

c =

     1
     2
     3

&gt;&gt; whos
  Name      Size            Bytes  Class     Attributes

  a         3x3                72  double              
  ans       1x1                 8  double              
  b         1x3                24  double              
  c         3x1                24  double              
  x3        1x1                 8  double              

&gt;&gt; 
</code></pre><h1 id="10-indexing">10. Indexing</h1>
<p>矩阵、向量的操作</p>
<pre tabindex="0"><code>&gt;&gt; a=[1 2 3;4 5 6;7 8 9]

a =

     1     2     3
     4     5     6
     7     8     9

&gt;&gt; b=a(:,1)

b =

     1
     4
     7

&gt;&gt; a(end,3)=0

a =

     1     2     3
     4     5     6
     7     8     0

&gt;&gt; a(end,:)=0

a =

     1     2     3
     4     5     6
     0     0     0

&gt;&gt; x=[1:5;6:9]
错误使用 vertcat
要串联的数组的维度不一致。
 
&gt;&gt; x=[1:5;6:10]

x =

     1     2     3     4     5
     6     7     8     9    10

&gt;&gt; a1=ones(1,size(a,1))

a1 =

     1     1     1
&gt;&gt; zeros(5)

ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0

&gt;&gt; zeros(1,5)

ans =

     0     0     0     0     0

&gt;&gt; eye(3)

ans =

     1     0     0
     0     1     0
     0     0     1

&gt;&gt; a(1,2)

ans =

     2

&gt;&gt; a(2,2)=10

a =

     1     2     3
     4    10     6
     0     0     0
</code></pre><h1 id="11-other-keywords">11. Other Keywords</h1>
<p>其他的一些关键字</p>
<pre tabindex="0"><code>&gt;&gt; length(a)

ans =

     3

&gt;&gt; size(a)

ans =

     3     3

&gt;&gt; numel(a)

ans =

     9

&gt;&gt; trace(a)

ans =

    11

&gt;&gt; eig(a)

ans =

    0.1849
   10.8151
         0

&gt;&gt; a

a =

     1     2     3
     4    10     6
     0     0     0

&gt;&gt; a=[1:3;4:6;7:9]

a =

     1     2     3
     4     5     6
     7     8     9

&gt;&gt; inv(a)
警告: 矩阵接近奇异值，或者缩放不良。结果可能不准确。RCOND =  1.541976e-18。 
 

ans =

   1.0e+16 *

   -0.4504    0.9007   -0.4504
    0.9007   -1.8014    0.9007
   -0.4504    0.9007   -0.4504

&gt;&gt; det(a)

ans =

   6.6613e-16
</code></pre><h1 id="12-matrix-operations">12. Matrix Operations</h1>
<pre tabindex="0"><code>&gt;&gt; a=rand(5)

a =

    0.2760    0.4984    0.7513    0.9593    0.8407
    0.6797    0.9597    0.2551    0.5472    0.2543
    0.6551    0.3404    0.5060    0.1386    0.8143
    0.1626    0.5853    0.6991    0.1493    0.2435
    0.1190    0.2238    0.8909    0.2575    0.9293

&gt;&gt; b=rand(5)

b =

    0.3500    0.3517    0.2858    0.0759    0.1299
    0.1966    0.8308    0.7572    0.0540    0.5688
    0.2511    0.5853    0.7537    0.5308    0.4694
    0.6160    0.5497    0.3804    0.7792    0.0119
    0.4733    0.9172    0.5678    0.9340    0.3371

&gt;&gt; a+b

ans =

    0.6260    0.8500    1.0371    1.0351    0.9706
    0.8763    1.7906    1.0123    0.6012    0.8231
    0.9062    0.9256    1.2597    0.6694    1.2837
    0.7787    1.1350    1.0795    0.9285    0.2554
    0.5923    1.1410    1.4587    1.1915    1.2664
&gt;&gt; a&gt;b

ans =

  5×5 logical 数组

   1   0   0   0   1
   1   1   1   1   0
   0   1   1   1   1
   1   1   0   0   1
   1   1   1   1   0
&gt;&gt; a.*b

ans =

    0.6173    0.0689    0.1298    0.0623    0.3212
    0.6731    0.0089    0.6744    0.1609    0.0159
    0.0498    0.1514    0.3035    0.7010    0.5488
    0.5987    0.0442    0.4612    0.6300    0.6625
    0.1083    0.0937    0.0276    0.1793    0.5122
&gt;&gt; a^2

ans =

    1.3164    0.9614    0.9676    1.0427    1.2492
    1.5213    1.1350    1.5754    1.5032    1.8462
    2.0937    2.3843    2.5910    2.6654    2.3472
    2.9873    2.2809    2.6699    2.5017    2.4191
    2.7964    2.3417    2.8111    2.6409    2.4855

&gt;&gt; a.^2

ans =

    0.6638    0.0095    0.0248    0.0201    0.4300
    0.8205    0.0776    0.9421    0.1779    0.0013
    0.0161    0.2991    0.9162    0.8386    0.7210
    0.8343    0.9168    0.2356    0.6276    0.8723
    0.3999    0.9310    0.6404    0.9206    0.4607
</code></pre><h1 id="13-solve-system-of-equations">13. Solve System of Equations</h1>
<pre tabindex="0"><code>&gt;&gt; a=[1 2 3;4 5 6;7 8 9]

a =

     1     2     3
     4     5     6
     7     8     9

&gt;&gt; b=[1 1 1]

b =

     1     1     1

&gt;&gt; a\b
错误使用  \ 
矩阵维度必须一致。
 
&gt;&gt; b=b&#39;

b =

     1
     1
     1

&gt;&gt; a\b
警告: 矩阵接近奇异值，或者缩放不良。结果可能不准确。RCOND =  1.541976e-18。 
 

ans =

   -2.5000
    4.0000
   -1.5000
&gt;&gt; x=a\b
警告: 矩阵接近奇异值，或者缩放不良。结果可能不准确。RCOND =  1.541976e-18。 
 

x =

   -2.5000
    4.0000
   -1.5000

&gt;&gt; a*x

ans =

     1
     1
     1
</code></pre><h1 id="14-m-file-scripts">14. M-File Scripts</h1>
<p>matlab文件的使用</p>
<pre tabindex="0"><code>%% matlab tutorial
% December 2025
</code></pre><h1 id="3-magic-cs">3 Magic C’s</h1>
<pre tabindex="0"><code>%% matlab tutorial
% December 2025

clear all
close all
clc
</code></pre><h1 id="15-loops">15. Loops</h1>
<pre tabindex="0"><code>%% matlab tutorial
% December 2025

clear all
close all
clc

counter=10;
% for i=1:5
%     counter=counter+1;
%     disp(counter)
% end

while counter&gt;=5;
    counter=counter-1;
    disp(counter)
end
</code></pre><h1 id="16-plotting">16. Plotting</h1>
<pre tabindex="0"><code>%% matlab tutorial
% December 2025

clear all
close all
clc

counter=10;
% for i=1:5
%     counter=counter+1;
%     disp(counter)
% end

while counter&gt;=5;
    counter=counter-1;
    disp(counter)
end


%% plotting

x=0:0.1:5;
y=x.^2;
plot(x,y,&#39;r+&#39;)
title(&#39;my first plot&#39;)

xlabel(&#39;x_value&#39;)
ylabel(&#39;y_value&#39;)

grid on
hold
y2=x.^3;
y3=x.^4;
plot(x,y2,&#39;g*&#39;)
plot(x,y3)
hold off
legend(&#39;plot1&#39;,&#39;plot2&#39;,&#39;plot3&#39;)

%% subplotting
subplot(311)
plot(x,y)
subplot(312)
plot(x,y2)
subplot(313)
plot(x,y3)
</code></pre><p><img alt="pic1" loading="lazy" src="/img/in-post/matlab_p1.png"></p>
<h1 id="17-functions">17. Functions</h1>
<pre tabindex="0"><code>function a=triangle_area(w,h)
    a=0.5*w*h;
end
</code></pre><h1 id="18-debugging">18. Debugging</h1>
<p>可以设置断点，类似调试c/c++</p>
<hr>
<h1 id="reference">Reference</h1>
<p><a href="https://www.youtube.com/watch?v=tBWMn4y1Yfo&amp;t=1479s">Learn MATLAB in ONE Video!&ndash;by Jousef Murad | Deep Dive</a></p>
]]></content:encoded></item><item><title>静态随机存储器</title><link>https://farmer3-c.github.io/posts/post-2025-11-05/</link><pubDate>Wed, 05 Nov 2025 16:45:31 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-11-05/</guid><description>计组实验</description><content:encoded><![CDATA[<h2 id="静态随机存储器实验">静态随机存储器实验</h2>
<h4 id="实验目的">实验目的</h4>
<p>(1)	掌握静态随机存储器 RAM 工作特性及数据的读写方法。
(2)	基于信号时序图，了解读写静态随机存储器的原理。</p>
<h4 id="实验设备">实验设备</h4>
<p>PC 机一台，TDX-CMX 实验系统一套。</p>
<h4 id="实验原理">实验原理</h4>
<p>实验所用的静态存储器由一片 6116（2K×8bit）构成（位于 MEM 单元），如图 2-1-1 所示。 6116 有三个控制线：CS（片选线）、OE（读线）、WE（写线），其功能如表 2-1-1 所示，当片选有效（CS=0）时，OE=0 时进行读操作，WE=0 时进行写操作，本实验将 CS 常接地。
<img alt="2.1.1" loading="lazy" src="/img/stu_exp/opcc1.png"></p>
<p><img alt="2.1.1.2" loading="lazy" src="/img/stu_exp/opcc2.png"></p>
<p>实验原理图如图 2-1-2 所示，存储器数据线接至 CPU 内总线，内总线上接有 8 个 LED 灯显示 D7…D0 的内容。地址线接至地址总线，地址总线上接有 8 个 LED 灯显示 A7…A0 的内容，地址由地址锁存器（74LS273，内嵌于 ABI 单元）给出。数据开关（位于 CON 单元的 SD17..SD10）经一个三态门（74LS245）连至 CPU 内总线，分时给出地址和数据。地址寄存器为 8 位，接入存储器的地址 A7…A0，高三位地址 A10…A8 接地，所以其实际容量为 256 字节。</p>
<p><img alt="2.1.2" loading="lazy" src="/img/stu_exp/opcc3.png"></p>
<p>实验箱中所有单元的时序都连接至时序与操作台单元，CLR 都连接至 CON 单元的 CLR 按钮。实验时 T3 由时序单元给出，其余信号由 CON 单元的对应二进制开关模拟给出，其中 RD、 WR 低有效，SW_B 低有效，LDAR 高有效。</p>
<h4 id="实验步骤">实验步骤</h4>
<p>本实验支持两种方式运行：本机运行（不需电脑）和联机运行（需要电脑）。其中联机运行方式既支持数据通路图的观测，也支持信号时序图的观测。</p>
<blockquote>
<p>本文只介绍本机运行</p>
</blockquote>
<h6 id="本机运行">本机运行</h6>
<p>(1)	关闭实验系统电源，把时序与操作台单元的“MODE”用短路块短接，使系统工作在四节拍模式，JP2 用短路块将 1、2 短接，按图 2-1-3 连接实验电路，并检查无误，图中将用户需要连接的信号用圆圈标明。
(2)	将时序与操作台单元的开关 KK1、KK3 置为运行档、开关 KK2 置为‘单拍’档
(3)将 CON 单元的 K7 开关（SW_B）置为 1（使 SD17..SD10 开关组无输出），打开电源开关，如果听到有‘嘀’报警声，说明有总线竞争现象，应立即关闭电源，重新检查接线，直到错误排除</p>
<p><img alt="2.1.3" loading="lazy" src="/img/stu_exp/opcc4.png"></p>
<p>(4)	给存储器的 00H、01H 地址单元中分别写入数据 11H、12H。由前面的存储器实验原理图（图 2-1-2）可以看出，由于数据和地址由同一个数据开关给出，因此数据和地址要分时写入。
先写地址：按动 2 次时序单元的 ST 按钮，产生 T1、T2 节拍后，先关掉存储器的读写（WR=1， RD=1），开关 SD17..SD10 输出地址 00H（SD17..SD10=0000 0000B，K7=0），然后打开地址寄存器门控信号（LDAR=1），按动 1 次 ST 产生 T3 脉冲，即将地址 00H 打入到 AR 中，按动 1 次 ST 产生 T4 脉冲，第 1 个机器周期结束。
再写数据： 按动 2 次时序单元的 ST 按钮，产生 T1、T2 节拍后，先关掉地址寄存器门控信号（LDAR=0），数据开关输出要写入的数据 11H（SD17..SD10=0001 0001B），打开三态门（K7=0），然后使存储器处于写状态（WR=0，RD=1），按动 1 次 ST 产生 T3 脉冲，即将数据11H 打入到存储器 00H 地址中，按动 1 次 ST 产生 T4 脉冲，第 2 个机器周期结束。
重复上述操作，向 01H 地址单元中写入数据 12H。写存储器的流程如图 2-1-4 所示（以向00 地址单元写入 11H 为例）：
<img alt="2.1.4" loading="lazy" src="/img/stu_exp/opcc5.png">
(5)	读出 00H 地址单元中的内容，观察单元中的内容是否与前面写入的一致。
先写地址：按动 2 次时序单元的 ST 按钮，产生 T1、T2 节拍后，先关掉存储器的读写（WR=1， RD=1），开关 SD17..SD10 输出地址 00H（SD17..SD10=0000 0000B，K7=0），然后打开地址寄存器门控信号（LDAR=1），按动 1 次 ST 产生 T3 脉冲，即将地址 00H 打入到 AR 中，按动 1 次 ST 产生 T4 脉冲，一个机器周期结束。
再读数据： 按动 2 次时序单元的 ST 按钮，产生 T1、T2 节拍后，先关掉地址寄存器门控信号（LDAR=0），关闭开关 SD17..SD10 输出（SW_B=1），然后使存储器处于读状态（WR=1， RD=0），此时数据总线上的数即为从存储器当前地址中读出的数据内容。按动 2 次 ST 产生 T3、 T4 脉冲，一个机器周期结束。</p>
<p>读存储器的流程如图 2-1-5 所示（以从 00 地址单元读出 11H 为例）：
<img alt="2.1.5" loading="lazy" src="/img/stu_exp/opcc6.png"></p>
<h6 id="注意事项">注意事项</h6>
<ul>
<li>数据线要检查两端信号顺序是否对齐；</li>
<li>IN单元IN_B、RD即为三态门的两个输入信号，或非门连接。当RD=IN_B=0时，三态门控制端为0，允许数据输出
*当三态门打开时，输入端的数据就可以送到输出端，而三态门关闭时，输入端的数据就无法到达输出端</li>
<li>针脚悬空表示高电平（实验有的针脚悬空表示低电平？）</li>
<li>一个针脚输入信号的就接在CON单元的 <strong>一开关</strong> ——  <strong>一针脚状态</strong> 上</li>
</ul>
]]></content:encoded></item><item><title>线段树</title><link>https://farmer3-c.github.io/posts/post-2025-10-20/</link><pubDate>Mon, 20 Oct 2025 23:27:41 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-10-20/</guid><description>Segment Tree</description><content:encoded><![CDATA[<blockquote>
<p>线段树是一种特殊的数据结构，它可以在 $O(\log n)$ 的时间复杂度内实现单点修改、区间修改、区间查询（区间求和，求区间最大值，求区间最小值）等操作。</p>
</blockquote>
<h4 id="最简单的线段树的构建">最简单的线段树的构建：</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 定义线段树的节点
</span></span></span><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">Node</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">;</span> <span class="c1">// 左右子节点的下标
</span></span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">sum</span><span class="p">;</span> <span class="c1">// 区间和
</span></span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">vector</span><span class="o">&lt;</span><span class="n">Node</span><span class="o">&gt;</span> <span class="n">tree</span><span class="p">;</span> <span class="c1">// 存储线段树的数组
</span></span></span><span class="line"><span class="cl"><span class="c1">// 构建线段树
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">build</span><span class="p">(</span><span class="kt">int</span> <span class="n">l</span><span class="p">,</span> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">l</span> <span class="o">=</span> <span class="n">l</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">r</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">l</span> <span class="o">==</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 叶子节点
</span></span></span><span class="line"><span class="cl">        <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">sum</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">l</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="n">r</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">build</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">index</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="n">nums</span><span class="p">);</span> <span class="c1">// 构建左子树
</span></span></span><span class="line"><span class="cl">    <span class="n">build</span><span class="p">(</span><span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">index</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nums</span><span class="p">);</span> <span class="c1">// 构建右子树
</span></span></span><span class="line"><span class="cl">    <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">sum</span> <span class="o">=</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">2</span><span class="p">].</span><span class="n">sum</span> <span class="o">+</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">].</span><span class="n">sum</span><span class="p">;</span> <span class="c1">// 计算区间和
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 区间查询
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">query</span><span class="p">(</span><span class="kt">int</span> <span class="n">l</span><span class="p">,</span> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">l</span> <span class="o">&gt;=</span> <span class="n">l</span> <span class="o">&amp;&amp;</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">r</span> <span class="o">&lt;=</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 当前区间完全包含在查询区间内
</span></span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">sum</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">l</span> <span class="o">+</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">r</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">l</span> <span class="o">&lt;=</span> <span class="n">mid</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 查询区间和左子树有交集
</span></span></span><span class="line"><span class="cl">        <span class="n">sum</span> <span class="o">+=</span> <span class="n">query</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">index</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">r</span> <span class="o">&gt;</span> <span class="n">mid</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 查询区间和右子树有交集
</span></span></span><span class="line"><span class="cl">        <span class="n">sum</span> <span class="o">+=</span> <span class="n">query</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">index</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">sum</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1">// 单点修改
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">update</span><span class="p">(</span><span class="kt">int</span> <span class="n">pos</span><span class="p">,</span> <span class="kt">int</span> <span class="n">val</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">l</span> <span class="o">==</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">r</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 叶子节点
</span></span></span><span class="line"><span class="cl">        <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">sum</span> <span class="o">=</span> <span class="n">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">l</span> <span class="o">+</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">r</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">pos</span> <span class="o">&lt;=</span> <span class="n">mid</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 修改的位置在左子树
</span></span></span><span class="line"><span class="cl">        <span class="n">update</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">index</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// 修改的位置在右子树
</span></span></span><span class="line"><span class="cl">        <span class="n">update</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">index</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">tree</span><span class="p">[</span><span class="n">index</span><span class="p">].</span><span class="n">sum</span> <span class="o">=</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">2</span><span class="p">].</span><span class="n">sum</span> <span class="o">+</span> <span class="n">tree</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">].</span><span class="n">sum</span><span class="p">;</span> <span class="c1">// 更新区间和
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">nums</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">};</span> <span class="c1">// 原始数组
</span></span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="c1">// 数组长度
</span></span></span><span class="line"><span class="cl">    <span class="n">tree</span><span class="p">.</span><span class="n">resize</span><span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="mi">4</span><span class="p">);</span> <span class="c1">// 线段树的大小为 4n
</span></span></span><span class="line"><span class="cl">    <span class="n">build</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nums</span><span class="p">);</span> <span class="c1">// 构建线段树
</span></span></span><span class="line"><span class="cl">    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">query</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">// 查询区间 [0, 4] 的和
</span></span></span><span class="line"><span class="cl">    <span class="n">update</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// 将第 2 个元素修改为 10
</span></span></span><span class="line"><span class="cl">    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">query</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">// 查询区间 [0, 4] 的和
</span></span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="构建解释">构建解释：</h4>
<p>递归地将数组分为左右两个子数组，直到子数组长度为 1，此时该子数组的区间和就是该子数组的元素值。</p>
<h4 id="查询解释">查询解释：</h4>
<p>如果当前区间完全包含在查询区间内，则直接返回该区间的区间和。</p>
<p>如果当前区间和查询区间有交集，则递归地查询左子树和右子树，然后将它们的区间和相加。</p>
<h4 id="修改解释">修改解释：</h4>
<p>如果当前区间的左右端点都等于修改的位置，则直接将该区间的区间和修改为新的值。</p>
<p>如果当前区间和修改的位置有交集，则递归地修改左子树和右子树，然后更新当前区间的区间和。</p>
<h4 id="线段树的时间复杂度">线段树的时间复杂度：</h4>
<p>线段树的时间复杂度主要取决于查询和修改操作的次数。</p>
<p>查询操作的时间复杂度为 $O(\log n)$，因为每次查询都可以将查询区间缩小一半。</p>
<p>修改操作的时间复杂度为 $O(\log n)$，因为每次修改都可以将修改的位置缩小一半。</p>
<p>因此，线段树的时间复杂度为 $O(\log n)$。</p>
<h4 id="线段树的空间复杂度">线段树的空间复杂度：</h4>
<p>线段树的空间复杂度主要取决于数组的大小。</p>
<p>如果数组的大小为 $n$，则线段树的空间复杂度为 $O(4n)$。</p>
<p>因此，线段树的空间复杂度为 $O(n)$。</p>
<h4 id="线段树的优点">线段树的优点：</h4>
<ul>
<li>
<p>可以在 $O(\log n)$ 的时间复杂度内实现单点修改、区间修改、区间查询等操作。</p>
</li>
<li>
<p>可以支持动态修改，即可以在修改数组的同时，在线地查询修改后的数组。</p>
</li>
<li>
<p>可以支持区间合并，即可以将多个区间的信息合并成一个区间的信息。</p>
</li>
<li>
<p>可以支持区间分裂，即可以将一个区间分裂成多个区间。</p>
</li>
</ul>
<h4 id="线段树的缺点">线段树的缺点：</h4>
<ul>
<li>
<p>线段树的空间复杂度较高，需要 $O(4n)$ 的空间。</p>
</li>
<li>
<p>线段树的实现较为复杂，需要递归地构建线段树和查询线段树。</p>
</li>
<li>
<p>线段树的查询和修改操作的时间复杂度较高，需要 $O(\log n)$ 的时间。</p>
</li>
<li>
<p>线段树的查询和修改操作的实现较为复杂，需要递归地查询和修改线段树。</p>
</li>
</ul>
<hr>
<p><strong>参考</strong></p>
<ul>
<li><a href="https://oi-wiki.org/ds/seg/#%E7%BA%BF%E6%AE%B5%E6%A0%91%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84%E4%B8%8E%E5%BB%BA%E6%A0%91">oi-wiki</a></li>
</ul>
]]></content:encoded></item><item><title>什么是无线网卡</title><link>https://farmer3-c.github.io/posts/post-2025-10-16/</link><pubDate>Thu, 16 Oct 2025 15:05:25 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-10-16/</guid><description>&lt;h2 id="什么是无线网卡"&gt;什么是无线网卡？&lt;/h2&gt;
&lt;p&gt;无线网卡，又称无线网络卡或 Wi-Fi 卡，是一种硬件组件，它使计算机或智能手机等设备能够连接到无线网络。它允许设备通过无线电频率信号与其他设备或接入点进行通信和数据交换，无需物理电缆。&lt;/p&gt;
&lt;h2 id="无线网卡的优点是什么"&gt;无线网卡的优点是什么？&lt;/h2&gt;
&lt;p&gt;无线网卡最显著的优势在于其自由移动性。用户无需通过线缆被限制在特定位置，即可连接网络和访问互联网。&lt;/p&gt;
&lt;p&gt;无线网络可以同时容纳多台设备，因此具有高度的可扩展性。这在许多设备需要连接到同一网络的环境中尤为重要，例如拥挤的公共场所或企业环境。&lt;/p&gt;
&lt;p&gt;无线网卡在连接和实现物联网设备之间的通信方面起着关键作用。它们促进传感器、设备和中央服务器之间的数据交换，推动物联网生态系统的增长&lt;/p&gt;
&lt;h2 id="无线网卡是如何工作的"&gt;无线网卡是如何工作的？&lt;/h2&gt;
&lt;p&gt;无线网卡通过使用射频信号来传输和接收数据。它们连接到网络的接入点，为数据流创建一条虚拟路径。这些网卡采用先进的加密技术来确保数据安全，使无线通信既高效又安全。&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://premioinc.com/blogs/blog/what-is-a-wireless-card-and-how-does-it-work"&gt;What is a Wireless Card? And How Does it Work?
&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.techtarget.com/searchnetworking/feature/Wireless-encryption-basics-Understanding-WEP-WPA-and-WPA2"&gt;Wireless security&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><content:encoded><![CDATA[<h2 id="什么是无线网卡">什么是无线网卡？</h2>
<p>无线网卡，又称无线网络卡或 Wi-Fi 卡，是一种硬件组件，它使计算机或智能手机等设备能够连接到无线网络。它允许设备通过无线电频率信号与其他设备或接入点进行通信和数据交换，无需物理电缆。</p>
<h2 id="无线网卡的优点是什么">无线网卡的优点是什么？</h2>
<p>无线网卡最显著的优势在于其自由移动性。用户无需通过线缆被限制在特定位置，即可连接网络和访问互联网。</p>
<p>无线网络可以同时容纳多台设备，因此具有高度的可扩展性。这在许多设备需要连接到同一网络的环境中尤为重要，例如拥挤的公共场所或企业环境。</p>
<p>无线网卡在连接和实现物联网设备之间的通信方面起着关键作用。它们促进传感器、设备和中央服务器之间的数据交换，推动物联网生态系统的增长</p>
<h2 id="无线网卡是如何工作的">无线网卡是如何工作的？</h2>
<p>无线网卡通过使用射频信号来传输和接收数据。它们连接到网络的接入点，为数据流创建一条虚拟路径。这些网卡采用先进的加密技术来确保数据安全，使无线通信既高效又安全。</p>
<hr>
<ul>
<li>
<p><a href="https://premioinc.com/blogs/blog/what-is-a-wireless-card-and-how-does-it-work">What is a Wireless Card? And How Does it Work?
</a></p>
</li>
<li>
<p><a href="https://www.techtarget.com/searchnetworking/feature/Wireless-encryption-basics-Understanding-WEP-WPA-and-WPA2">Wireless security</a></p>
</li>
</ul>
]]></content:encoded></item><item><title>Introduction to Linear Programing</title><link>https://farmer3-c.github.io/posts/introduction-to-linear-programing/</link><pubDate>Sun, 14 Sep 2025 23:54:39 +0800</pubDate><guid>https://farmer3-c.github.io/posts/introduction-to-linear-programing/</guid><description>Convex Optimization</description><content:encoded><![CDATA[<h2 id="what-is-linear-programming">What is Linear Programming?</h2>
<p><strong>Linear programming</strong> (LP), also known as linear optimization, is a powerful mathematical method used to find the best possible outcome in a given situation. It&rsquo;s used to achieve results like maximum profit or minimum cost, where the objective and the constraints are expressed as linear relationships. In essence, LP provides a systematic way to solve optimization problems.</p>
<hr>
<h3 id="standard-form">Standard Form</h3>
<p>To solve a linear programming problem, we first need to express it in <strong>standard form</strong>. This is the most common and intuitive way to structure an LP problem and consists of three key components:</p>
<ol>
<li>
<p><strong>A linear objective function to be maximized.</strong> This is the quantity you want to optimize. For example:
$f(x_{1}, x_{2}) = c_{1}x_{1} + c_{2}x_{2}$</p>
</li>
<li>
<p><strong>A set of linear inequality constraints.</strong> These are the rules or limitations of the problem.</p>
<p>$a_{11}x_{1} + a_{12}x_{2} \leq b_{1} $</p>
<p>$a_{21}x_{1} + a_{22}x_{2} \leq b_{2} $</p>
<p>$ a_{31}x_{1} + a_{32}x_{2} \leq b_{3}$</p>
</li>
<li>
<p><strong>Non-negative variables.</strong> The decision variables must be greater than or equal to zero.</p>
<p>$x_{1} \geq 0 $</p>
<p>$x_{2} \geq 0$</p>
</li>
</ol>
<p>In a more compact matrix notation, the problem can be expressed as:</p>
<p>$\textbf{maximize } \\\{ \mathbf{c^{T}x} \mid \mathbf{x} \in \mathbb{R}^{n} \land \mathbf{Ax} \leq \mathbf{b} \land \mathbf{x} \geq \mathbf{0} \\\}$</p>
<hr>
<h3 id="a-practical-example-the-oil-refinery-problem">A Practical Example: The Oil Refinery Problem</h3>
<p>Let&rsquo;s apply these concepts to a real-world scenario. An oil refinery produces two products: <strong>jet fuel</strong> and <strong>gasoline</strong>.</p>
<ul>
<li>The profit is <strong>$0.10 per barrel** for jet fuel and **$0.20 per barrel</strong> for gasoline.</li>
<li>The refinery has <strong>10,000 barrels</strong> of crude oil available.</li>
<li>A government contract requires at least <strong>1,000 barrels</strong> of jet fuel.</li>
<li>A private contract requires at least <strong>2,000 barrels</strong> of gasoline.</li>
<li>The truck fleet&rsquo;s delivery capacity is <strong>180,000 barrel-miles</strong>.</li>
<li>Jet fuel is delivered <strong>10 miles</strong> away, and gasoline is transported <strong>30 miles</strong> away.</li>
</ul>
<p>The question is: <strong>How can the refinery maximize its profit?</strong></p>
<h3 id="step-1-formulating-the-lp-model">Step 1: Formulating the LP Model</h3>
<p>First, let&rsquo;s define our variables. Let $x_1$ be the number of barrels of jet fuel and $x_2$ be the number of barrels of gasoline.</p>
<p>Our objective is to maximize profit, so the <strong>objective function</strong> is:</p>
<p>$\textbf{Maximize: } P = 0.10x_{1} + 0.20x_{2}$</p>
<p>Next, we establish the <strong>constraints</strong> based on the problem&rsquo;s conditions:</p>
<p>$
\begin{aligned}
x_{1} + x_{2} &\leq 10000 && \text{(Crude oil availability)} \newline
x_{1} &\geq 1000 && \text{(Jet fuel contract)} \newline
x_{2} &\geq 2000 && \text{(Gasoline contract)} \newline
10x_{1} + 30x_{2} &\leq 180000 && \text{(Delivery capacity)}
\end{aligned}
$</p>
<p>The plot below shows the <strong>feasible region</strong>—the area where all constraints are satisfied. The optimal solution will lie at one of the vertices of this region.</p>
<p><img alt="A graph showing the feasible region for a linear programming problem" loading="lazy" src="/img/in-post/Linear_Programming_Feasible_Region.svg.png"></p>
<hr>
<h3 id="step-2-converting-to-standard-form">Step 2: Converting to Standard Form</h3>
<p>The Simplex Method, a common algorithm for solving LP problems, requires a specific format.</p>
<p>First, let&rsquo;s handle the minimum production requirements. We can introduce new variables, $s_1 = x_1 - 1000$ and $s_2 = x_2 - 2000$, which represent the surplus production above the minimums. This ensures our new variables are non-negative ($s_1, s_2 \geq 0$).</p>
<p>Substituting these into our model gives a new objective function:</p>
<p>$\textbf{Maximize: } P = 0.1(s_1 + 1000) + 0.2(s_2 + 2000) = 0.1s_1 + 0.2s_2 + 500$</p>
<p>And updated constraints:</p>
<p>$
\begin{aligned}
(s_1 + 1000) + (s_2 + 2000) &\leq 10000 \implies s_1 + s_2 \leq 7000 \newline
10(s_1 + 1000) + 30(s_2 + 2000) &\leq 180000 \implies 10s_1 + 30s_2 \leq 110000 \newline
s_1, s_2 &\geq 0
\end{aligned}
$</p>
<p>Next, we convert the inequalities into equalities by introducing <strong>slack variables</strong> ($k_1, k_2$). These variables represent unused resources.</p>
<p>$
\begin{aligned}
s_1 + s_2 + k_1 &= 7000 \newline
10s_1 + 30s_2 + k_2 &= 110000
\end{aligned}
$</p>
<p>Our objective function can be rewritten as $Z - 0.1s_1 - 0.2s_2 = 500$.</p>
<hr>
<h3 id="step-3-solving-with-the-simplex-method">Step 3: Solving with the Simplex Method</h3>
<p>Now we can construct the initial <strong>simplex tableau</strong>, which is a matrix representation of our system.</p>
<p><strong>Initial Tableau</strong></p>
<table>
	<thead>
			<tr>
					<th style="text-align: center">$s_1$</th>
					<th style="text-align: center">$s_2$</th>
					<th style="text-align: center">$k_1$</th>
					<th style="text-align: center">$k_2$</th>
					<th style="text-align: center">$Z$</th>
					<th style="text-align: center">C</th>
					<th style="text-align: center">Basic Var.</th>
					<th style="text-align: center">Ratio</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: center">1</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">7000</td>
					<td style="text-align: center">$k_1$</td>
					<td style="text-align: center">7000/1 = 7000</td>
			</tr>
			<tr>
					<td style="text-align: center">10</td>
					<td style="text-align: center"><strong>30</strong></td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">110000</td>
					<td style="text-align: center">$k_2$</td>
					<td style="text-align: center">110000/30 ≈ 3667 ←</td>
			</tr>
			<tr>
					<td style="text-align: center">-0.1</td>
					<td style="text-align: center">-0.2 ↑</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">500</td>
					<td style="text-align: center">$Z$</td>
					<td style="text-align: center"></td>
			</tr>
	</tbody>
</table>
<p><strong>Iteration 1</strong></p>
<ol>
<li><strong>Identify Pivot Column:</strong> Find the most negative entry in the bottom (objective) row. This is <strong>-0.2</strong>, so the $s_2$ column is our pivot column.</li>
<li><strong>Identify Pivot Row:</strong> Calculate the ratio of the constant (C) to the entry in the pivot column for each constraint row. The smallest non-negative ratio determines the pivot row. Here, $110000 / 30 \approx 3667$ is the smallest, making the second row our pivot row.</li>
<li><strong>Pivot:</strong> The element at the intersection, <strong>30</strong>, is the pivot. We use row operations to make the pivot 1 and all other entries in its column 0.</li>
</ol>
<p>After performing the row operations, we get the next tableau.</p>
<p><strong>Tableau 2</strong></p>
<table>
	<thead>
			<tr>
					<th style="text-align: center">$s_1$</th>
					<th style="text-align: center">$s_2$</th>
					<th style="text-align: center">$k_1$</th>
					<th style="text-align: center">$k_2$</th>
					<th style="text-align: center">$Z$</th>
					<th style="text-align: center">C</th>
					<th style="text-align: center">Basic Var.</th>
					<th style="text-align: center">Ratio</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: center"><strong>2/3</strong></td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">-1/30</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">10000/3</td>
					<td style="text-align: center">$k_1$</td>
					<td style="text-align: center">(10000/3) / (2/3) = 5000 ←</td>
			</tr>
			<tr>
					<td style="text-align: center">1/3</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1/30</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">11000/3</td>
					<td style="text-align: center">$s_2$</td>
					<td style="text-align: center">(11000/3) / (1/3) = 11000</td>
			</tr>
			<tr>
					<td style="text-align: center">-1/30 ↑</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1/150</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">1233.33</td>
					<td style="text-align: center">$Z$</td>
					<td style="text-align: center"></td>
			</tr>
	</tbody>
</table>
<p><strong>Iteration 2</strong>
The bottom row still has a negative entry (<strong>-1/30</strong>), so we repeat the process. The $s_1$ column is the new pivot column. The ratio test identifies the first row as the pivot row.</p>
<p>After pivoting on the <strong>2/3</strong> element, we arrive at the final tableau.</p>
<p><strong>Final Tableau</strong></p>
<table>
	<thead>
			<tr>
					<th style="text-align: center">$s_1$</th>
					<th style="text-align: center">$s_2$</th>
					<th style="text-align: center">$k_1$</th>
					<th style="text-align: center">$k_2$</th>
					<th style="text-align: center">$Z$</th>
					<th style="text-align: center">C</th>
					<th style="text-align: center">Basic Var.</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: center">1</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1.5</td>
					<td style="text-align: center">-0.05</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">5000</td>
					<td style="text-align: center">$s_1$</td>
			</tr>
			<tr>
					<td style="text-align: center">0</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">-0.5</td>
					<td style="text-align: center">0.05</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">2000</td>
					<td style="text-align: center">$s_2$</td>
			</tr>
			<tr>
					<td style="text-align: center">0</td>
					<td style="text-align: center">0</td>
					<td style="text-align: center">0.05</td>
					<td style="text-align: center">0.0033</td>
					<td style="text-align: center">1</td>
					<td style="text-align: center">1400</td>
					<td style="text-align: center">$Z$</td>
			</tr>
	</tbody>
</table>
<p>Since there are no more negative entries in the bottom row, we have reached the optimal solution.</p>
<hr>
<h3 id="step-4-interpreting-the-final-result">Step 4: Interpreting the Final Result</h3>
<p>From the final tableau, we can read the solution:</p>
<ul>
<li>$s_1 = 5000$</li>
<li>$s_2 = 2000$</li>
<li>$Z = 1400$</li>
</ul>
<p>Now, we convert back to our original variables, $x_1$ and $x_2$:</p>
<ul>
<li>$x_1 = s_1 + 1000 = 5000 + 1000 = 6000$</li>
<li>$x_2 = s_2 + 2000 = 2000 + 2000 = 4000$</li>
</ul>
<p>The maximum profit is <strong>$1400</strong>. This is achieved by producing <strong>6,000 barrels of jet fuel</strong> and <strong>4,000 barrels of gasoline</strong>.</p>
<hr>
<p><em>This example is adapted from content available on <a href="https://math.libretexts.org/Bookshelves/Applied_Mathematics/Applied_Finite_Mathematics_(Sekhon_and_Bloom)/04:_Linear_Programming_The_Simplex_Method/4.02:_Maximization_By_The_Simplex_Method/4.2.01:_Maximization_By_The_Simplex_Method_(Exercises)">math.libretexts.org</a>.</em></p>
]]></content:encoded></item><item><title>machine learning</title><link>https://farmer3-c.github.io/posts/machine-learning/</link><pubDate>Sun, 14 Sep 2025 15:39:21 +0800</pubDate><guid>https://farmer3-c.github.io/posts/machine-learning/</guid><description>AI</description><content:encoded><![CDATA[<h1 id="机器学习">机器学习</h1>
<p><img alt="ai" loading="lazy" src="/img/in-post/AI_hierarchy.png"></p>
<h2 id="definition">definition</h2>
<p>机器学习（ML）是人工智能的一个研究领域，关注于开发和研究能够从已有数据中学习并推广到未见数据，从而无需明确指令就能执行任务的统计算法。在机器学习的一个子学科中，深度学习领域的进展使得神经网络——一种统计算法——在性能上超越了许多之前的机器学习方法。</p>
<p>统计学和数学优化（数学规划）方法是机器学习的基础。数据挖掘是一个相关的研究领域，专注于通过<strong>无监督学习</strong>进行<strong>探索性数据分析</strong>（<strong>EDA</strong>）。</p>
<p>从理论角度来看，大概近似正确学习为描述机器学习提供了一个框架。</p>
<h2 id="history">history</h2>
<p>机器学习一词由 IBM 员工、计算机游戏和人工智能领域的先驱<strong>亚瑟·塞缪尔</strong>于 1959 年提出。在这个时期，也使用了同义词“自教学计算机”。</p>
<p>最早的机器学习程序出现在 20 世纪 50 年代，当时亚瑟·萨缪尔发明了一个计算机程序，用于计算跳棋双方获胜的概率，但机器学习的历史可以追溯到人类数十年来研究认知过程的愿望和努力。1949 年，加拿大心理学家唐纳德·赫布出版了《行为的组织》一书，书中介绍了一种由神经细胞之间特定相互作用形成的理论神经结构。赫布的神经元相互作用模型为人工智能和机器学习算法在节点（计算机用于通信的人工神经元）下如何工作奠定了基础。其他研究人类认知系统的研究者也促进了现代机器学习技术的发展，包括逻辑学家沃尔特·皮茨和沃伦·麦克洛克，他们提出了早期的神经网络数学模型，以形成模拟人类思维过程的算法。</p>
<p>Modern day Machine Learning algorithms are broken into 3 algorithms types: Supervised Learning Algorithms, Unsupervised Learning Algorithms, and Reinforcement Learning Algorithms.</p>
<ul>
<li>Current Supervised Learning Algorithms have objectives of classification and regression.</li>
<li>Current Unsupervised Learning Algorithms have objectives of clustering, dimensionality reduction, and association rule.</li>
<li>Current Reinforcement Learning Algorithms focus on decisions that must be made with respect to some previous, unkown time and are broken down to either be studies of model based methods, and model free methods.</li>
</ul>
<h2 id="theory">theory</h2>
<p>学习者的一个核心目标是泛化其经验。在此文中，泛化是指学习机器在经历学习数据集后，能够对新未见过的示例/任务进行准确执行的能力。训练示例来自某个通常未知的概率分布（被认为是发生空间的代表），而学习者必须构建一个关于这个空间的通用模型，使其能够在新情况下产生足够准确的预测。</p>
<p>机器学习算法及其性能的计算分析是理论计算机科学的一个分支，通过概率近似正确学习模型（probably approximately correct learning model）属于计算学习理论（computational learning theory）。由于训练集是有限的且未来是不确定的，学习理论通常不会提供算法性能的保证。相反，性能的概率界限相当常见。偏差-方差分解（bias–variance decomposition）是量化泛化误差（generalisation error）的一种方法。</p>
<p>在泛化性能方面，假设的复杂度应与数据底层函数的复杂度相匹配。如果假设的复杂度低于函数，则模型对数据欠拟合。如果相应增加模型的复杂度，则训练误差会下降。但如果假设过于复杂，模型容易过拟合，泛化能力会变差。</p>
<h2 id="applications">applications</h2>
<p>There are many applications for machine learning, including:</p>
<ul>
<li>Agriculture</li>
<li>Anatomy</li>
<li>Adaptive website</li>
<li>Affective computing</li>
<li>Astronomy</li>
<li>Automated decision-making</li>
<li>Banking</li>
<li>Behaviorism</li>
<li>Bioinformatics</li>
<li>Brain–machine interfaces</li>
<li>Cheminformatics</li>
<li>Citizen Science</li>
<li>Climate Science</li>
<li>Computer networks</li>
<li>Computer vision</li>
<li>Credit-card fraud detection</li>
<li>Data quality</li>
<li>DNA sequence classification</li>
<li>Economics</li>
<li>Financial data analysis</li>
<li>General game playing</li>
<li>Handwriting recognition</li>
<li>Healthcare</li>
<li>Information retrieval</li>
<li>Insurance</li>
<li>Internet fraud detection</li>
<li>Investment management</li>
<li>Knowledge graph embedding</li>
<li>Linguistics</li>
<li>Machine learning control</li>
<li>Machine perception</li>
<li>Machine translation</li>
<li>Material Engineering</li>
<li>Marketing</li>
<li>Medical diagnosis</li>
<li>Natural language processing</li>
<li>Natural language understanding</li>
<li>Online advertising</li>
<li>Optimisation</li>
<li>Recommender systems</li>
<li>Robot locomotion</li>
<li>Search engines</li>
<li>Sentiment analysis</li>
<li>Sequence mining</li>
<li>Software engineering</li>
<li>Speech recognition</li>
<li>Structural health monitoring</li>
<li>Syntactic pattern recognition</li>
<li>Telecommunications</li>
<li>Theorem proving</li>
<li>Time-series forecasting</li>
<li>Tomographic reconstruction</li>
<li>User behaviour analytics</li>
</ul>
]]></content:encoded></item><item><title>datalab</title><link>https://farmer3-c.github.io/posts/datalab/</link><pubDate>Fri, 12 Sep 2025 14:25:50 +0800</pubDate><guid>https://farmer3-c.github.io/posts/datalab/</guid><description>csapp</description><content:encoded><![CDATA[<h1 id="csapp-data-lab">CS:APP Data Lab</h1>
<blockquote>
<p>The purpose of this lab is to become more familiar with bit-level representations of integers andfloating point numbers. You&rsquo;ll do this by solving a series of programming “puzzles.” Many of these puzzles are quite artificial, but you&rsquo;ll find yourself thinking much more about bits in working your way through them.<span style="float: right;">————  Harry Bovik</span></p>
</blockquote>
<h4 id="bitxor">bitXor</h4>
<ul>
<li>bitXor - x^y using only ~ and &amp;</li>
<li>Example: bitXor(4, 5) = 1</li>
<li>Legal ops: ~ &amp;</li>
<li>Max ops: 14</li>
<li>Rating: 1</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">bitXor</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// x^y=(x&amp;~y)|(~x&amp;y)=~(~x&amp;~y)&amp;~(x&amp;y)
</span></span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="o">~</span><span class="p">(</span><span class="o">~</span><span class="p">(</span><span class="n">x</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">y</span><span class="p">)</span> <span class="o">&amp;</span> <span class="o">~</span><span class="p">(</span><span class="o">~</span><span class="n">x</span> <span class="o">&amp;</span> <span class="n">y</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="tmin">tmin</h4>
<ul>
<li>tmin - return minimum two&rsquo;s complement integer</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 4</li>
<li>Rating: 1</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">tmin</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="istmax">isTmax</h4>
<ul>
<li>isTmax - returns 1 if x is the maximum, two&rsquo;s complement number, and 0 otherwise</li>
<li>Legal ops: ! ~ &amp; ^ | +</li>
<li>Max ops: 10</li>
<li>Rating: 1</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">isTmax</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="o">!</span><span class="p">(</span><span class="o">~</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="n">x</span><span class="p">)</span> <span class="o">&amp;</span> <span class="o">!!</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="alloddbits">allOddBits</h4>
<ul>
<li>allOddBits - return 1 if all odd-numbered bits in word set to 1</li>
<li>where bits are numbered from 0 (least significant) to 31 (most significant)</li>
<li>Examples: allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 12</li>
<li>Rating: 2</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">allOddBits</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">m</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0xAA</span> <span class="o">&lt;&lt;</span> <span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="mh">0xAA</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">m</span> <span class="o">=</span> <span class="p">(</span><span class="n">m</span> <span class="o">&lt;&lt;</span> <span class="mi">16</span><span class="p">)</span> <span class="o">|</span> <span class="n">m</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="o">!</span><span class="p">((</span><span class="n">x</span> <span class="o">&amp;</span> <span class="n">m</span><span class="p">)</span> <span class="o">^</span> <span class="n">m</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="negate">negate</h4>
<ul>
<li>negate - return -x</li>
<li>Example: negate(1) = -1.</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 5</li>
<li>Rating: 2</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">negate</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="o">~</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="isasciidigit">isAsciiDigit</h4>
<ul>
<li>isAsciiDigit - return 1 if 0x30 &lt;= x &lt;= 0x39 (ASCII codes for characters &lsquo;0&rsquo; to &lsquo;9&rsquo;)</li>
<li>
<pre><code>Example: isAsciiDigit(0x35) = 1.
</code></pre>
</li>
<li>
<pre><code>         isAsciiDigit(0x3a) = 0.
</code></pre>
</li>
<li>
<pre><code>         isAsciiDigit(0x05) = 0.
</code></pre>
</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 15</li>
<li>Rating: 3</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">isAsciiDigit</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="p">(</span><span class="o">~</span><span class="mh">0x30</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mh">0x39</span> <span class="o">+</span> <span class="p">(</span><span class="o">~</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="o">!</span><span class="p">((</span><span class="n">a</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">b</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="conditional">conditional</h4>
<ul>
<li>conditional - same as x ? y : z</li>
<li>Example: conditional(2,4,5) = 4</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 16</li>
<li>Rating: 3</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">conditional</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">,</span> <span class="kt">int</span> <span class="n">z</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">((</span><span class="o">~</span><span class="p">(</span><span class="o">!!</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&amp;</span> <span class="n">y</span><span class="p">)</span> <span class="o">|</span> <span class="p">((</span><span class="o">~</span><span class="p">(</span><span class="o">~</span><span class="p">(</span><span class="o">!!</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">&amp;</span> <span class="n">z</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="islessorequal">isLessOrEqual</h4>
<ul>
<li>isLessOrEqual - if x &lt;= y then return 1, else return 0</li>
<li>Example: isLessOrEqual(4,5) = 1.</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 24</li>
<li>Rating: 3</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">isLessOrEqual</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">y</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">f</span> <span class="o">=</span> <span class="n">a</span> <span class="o">^</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">d</span> <span class="o">=</span> <span class="n">y</span> <span class="o">+</span> <span class="o">~</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">ds</span> <span class="o">=</span> <span class="p">(</span><span class="n">d</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span><span class="n">f</span> <span class="o">&amp;</span> <span class="n">a</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">!</span><span class="n">f</span> <span class="o">&amp;</span> <span class="o">!</span><span class="n">ds</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="logicalneg">logicalNeg</h4>
<ul>
<li>logicalNeg - implement the ! operator, using all of the legal operators except !</li>
<li>Examples: logicalNeg(3) = 0, logicalNeg(0) = 1, logicalNeg(-5) = 0</li>
<li>Legal ops: ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 12</li>
<li>Rating: 4</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">logicalNeg</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(((</span><span class="o">~</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">|</span> <span class="n">x</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="howmanybits">howManyBits</h4>
<ul>
<li>howManyBits - return the minimum number of bits required to represent x in two&rsquo;s complement</li>
<li>Examples: howManyBits(12) = 5</li>
<li>
<pre><code>       howManyBits(298) = 10
</code></pre>
</li>
<li>
<pre><code>       howManyBits(-5) = 4
</code></pre>
</li>
<li>
<pre><code>       howManyBits(0)  = 1
</code></pre>
</li>
<li>
<pre><code>       howManyBits(-1) = 1
</code></pre>
</li>
<li>
<pre><code>       howManyBits(0x80000000) = 32
</code></pre>
</li>
<li>Legal ops: ! ~ &amp; ^ | + &laquo; &raquo;</li>
<li>Max ops: 90</li>
<li>Rating: 4</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">howManyBits</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">sign</span> <span class="o">=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">,</span> <span class="n">bit16</span><span class="p">,</span> <span class="n">bit8</span><span class="p">,</span> <span class="n">bit4</span><span class="p">,</span> <span class="n">bit2</span><span class="p">,</span> <span class="n">bit1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">sign</span> <span class="o">&amp;</span> <span class="o">~</span><span class="n">x</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="o">~</span><span class="n">sign</span> <span class="o">&amp;</span> <span class="n">x</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="n">bit16</span> <span class="o">=</span> <span class="p">(</span><span class="o">!!</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">x</span> <span class="o">&gt;&gt;=</span> <span class="n">bit16</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">bit8</span> <span class="o">=</span> <span class="p">(</span><span class="o">!!</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">8</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">x</span> <span class="o">&gt;&gt;=</span> <span class="n">bit8</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">bit4</span> <span class="o">=</span> <span class="p">(</span><span class="o">!!</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">4</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">x</span> <span class="o">&gt;&gt;=</span> <span class="n">bit4</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">bit2</span> <span class="o">=</span> <span class="p">(</span><span class="o">!!</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">))</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">x</span> <span class="o">&gt;&gt;=</span> <span class="n">bit2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="n">bit1</span> <span class="o">=</span> <span class="p">(</span><span class="o">!!</span><span class="p">(</span><span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="n">x</span> <span class="o">&gt;&gt;=</span> <span class="n">bit1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="n">bit16</span> <span class="o">+</span> <span class="n">bit2</span> <span class="o">+</span> <span class="n">bit4</span> <span class="o">+</span> <span class="n">bit8</span> <span class="o">+</span> <span class="n">bit1</span> <span class="o">+</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="floatscale2">floatScale2</h4>
<ul>
<li>floatScale2 - Return bit-level equivalent of expression 2*f for floating point argument f.</li>
<li>Both the argument and result are passed as unsigned int&rsquo;s, but they are to be interpreted as the bit-level representation of single-precision floating point values.</li>
<li>When argument is NaN, return argument</li>
<li>Legal ops: Any integer/unsigned operations incl. ||, &amp;&amp;. also if, while</li>
<li>Max ops: 30</li>
<li>Rating: 4</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">unsigned</span> <span class="nf">floatScale2</span><span class="p">(</span><span class="kt">unsigned</span> <span class="n">uf</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">unsigned</span> <span class="n">sign</span> <span class="o">=</span> <span class="p">(</span><span class="n">uf</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">,</span> <span class="n">exp</span> <span class="o">=</span> <span class="p">(</span><span class="n">uf</span> <span class="o">&gt;&gt;</span> <span class="mi">23</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">,</span> <span class="n">frac</span> <span class="o">=</span> <span class="n">uf</span> <span class="o">&amp;</span> <span class="mh">0x7fffff</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">==</span> <span class="mh">0xff</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">uf</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">frac</span> <span class="o">&amp;</span> <span class="mh">0x800000</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">exp</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">frac</span> <span class="o">&lt;&lt;=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">exp</span> <span class="o">&lt;&lt;</span> <span class="mi">23</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">sign</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">|</span> <span class="n">frac</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="n">exp</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">==</span> <span class="mh">0xff</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">sign</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="mh">0xff</span> <span class="o">&lt;&lt;</span> <span class="mi">23</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(</span><span class="n">sign</span> <span class="o">&lt;&lt;</span> <span class="mi">31</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">exp</span> <span class="o">&lt;&lt;</span> <span class="mi">23</span><span class="p">)</span> <span class="o">|</span> <span class="n">frac</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="floatfloat2int">floatFloat2Int</h4>
<ul>
<li>floatFloat2Int - Return bit-level equivalent of expression (int) f for floating point argument f.</li>
<li>Argument is passed as unsigned int, but it is to be interpreted as the bit-level representation of a single-precision floating point value.</li>
<li>Anything out of range (including NaN and infinity) should return 0x80000000u.</li>
<li>Legal ops: Any integer/unsigned operations incl. ||, &amp;&amp;. also if, while</li>
<li>Max ops: 30</li>
<li>Rating: 4</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">floatFloat2Int</span><span class="p">(</span><span class="kt">unsigned</span> <span class="n">uf</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kt">int</span> <span class="n">sign</span> <span class="o">=</span> <span class="n">uf</span> <span class="o">&gt;&gt;</span> <span class="mi">31</span><span class="p">,</span> <span class="n">exp</span> <span class="o">=</span> <span class="p">((</span><span class="n">uf</span> <span class="o">&gt;&gt;</span> <span class="mi">23</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0xff</span><span class="p">)</span> <span class="o">-</span> <span class="mi">127</span><span class="p">,</span> <span class="n">frac</span> <span class="o">=</span> <span class="p">(</span><span class="n">uf</span> <span class="o">&amp;</span> <span class="mh">0x7fffff</span><span class="p">)</span> <span class="o">|</span> <span class="mh">0x800000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">&gt;=</span> <span class="mi">31</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mh">0x80000000u</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">&lt;</span> <span class="mi">23</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">frac</span> <span class="o">&gt;&gt;=</span> <span class="p">(</span><span class="mi">23</span> <span class="o">-</span> <span class="n">exp</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">else</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">frac</span> <span class="o">&lt;&lt;=</span> <span class="p">(</span><span class="n">exp</span> <span class="o">-</span> <span class="mi">23</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">sign</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">frac</span> <span class="o">=</span> <span class="o">-</span><span class="n">frac</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="n">frac</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="floatpower2">floatPower2</h4>
<ul>
<li>floatPower2 - Return bit-level equivalent of the expression 2.0^x (2.0 raised to the power x) for any 32-bit integer x.</li>
<li>The unsigned value that is returned should have the identical bit representation as the single-precision floating-point number 2.0^x.</li>
<li>If the result is too small to be represented as a denorm, return 0. If too large, return +INF.</li>
<li>Legal ops: Any integer/unsigned operations incl. ||, &amp;&amp;. Also if, while</li>
<li>Max ops: 30</li>
<li>Rating: 4</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="kt">unsigned</span> <span class="nf">floatPower2</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">x</span> <span class="o">&lt;</span> <span class="o">-</span><span class="mi">148</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">x</span> <span class="o">&lt;</span> <span class="o">-</span><span class="mi">126</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">unsigned</span> <span class="n">f</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">148</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">unsigned</span> <span class="n">fra</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">f</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">fra</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="n">x</span> <span class="o">&lt;=</span> <span class="mi">127</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">127</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">k</span> <span class="o">&lt;&lt;</span> <span class="mi">23</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="mh">0x7f800000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded></item><item><title>Optimization for Unconstrained Differentiable Functions</title><link>https://farmer3-c.github.io/posts/optimization-for-unconstrained-differentiable-functions/</link><pubDate>Wed, 03 Sep 2025 23:32:42 +0800</pubDate><guid>https://farmer3-c.github.io/posts/optimization-for-unconstrained-differentiable-functions/</guid><description>Convex Optimization Theory and Method</description><content:encoded><![CDATA[<h3 id="optimization-for-unconstrained-differentiable-functions">Optimization for Unconstrained Differentiable Functions</h3>
<h4 id="11-mathematical-optimization">1.1 Mathematical optimization</h4>
<p>$\frac{x ^2}{a^2} + \frac{y ^2}{b^2} = 1$
$\textit{f}_0 =4|x||y|$</p>
<p>A <em>mathematical optimization problem</em>, or <em>just optimization problem</em>, has the form <em>maximize</em> $\textit{f}_0 $</p>
<p><img alt="elliptical" loading="lazy" src="/img/in-post/ell.png"></p>
<p>use x to represent $\textit{f}_0 $</p>
<p>$\textit{f}_0 =4xb\sqrt{1-\frac{x^2}{a^2}}   $</p>
<p>$x>0$</p>
<p>we need to make $\textit{f'}_0 =4b \left( \sqrt{1 - \frac{x^2}{a^2}} - \frac{x^2}{a^2 \sqrt{1 - \frac{x^2}{a^2}}} \right)=0$</p>
<p>$ x=\frac{\sqrt2a}{2}$</p>
<p>find out the max of $\textit{f}_0$  is $2ab$</p>
<h4 id="12-gradient-descent">1.2 Gradient descent</h4>
<p>Let&rsquo;s try to find the minimum value of<br>
$\textit{f}(x,y) = x^3-y^3+3x^2-3y^2-9x$</p>
<p>begin point:
$\textit{x}_0=3,\textit{y}_0=3$</p>
<h6 id="1gradient-descent">1.Gradient Descent</h6>
<p>First,calculate the gradient,
$\nabla \textit{f}_{(x,y)}=(\frac{\partial f}{\partial x },\frac{\partial f}{\partial y }) $<br>
$\frac{\partial f}{\partial x }=3x^2+6x-9$</p>
<p>$\frac{\partial f}{\partial y }=-3y^2-6y$</p>
<p>Second,select a suitable learning rate ,
we try to set $\alpha =0.01$,which can be changed if not suitable.</p>
<p>Iterative updates:<br>
$x_{n+1}=x_{n}-\alpha \frac{\partial f}{\partial x }$</p>
<p>$y_{n+1}=y_{n}-\alpha \frac{\partial f}{\partial y }$</p>
<p>Ending up finding the minimum value $f_{(1,-2)}=-9$</p>
<h6 id="2hessian-matrix-and-extreme-value-discrimination-method">2.Hessian Matrix and Extreme Value Discrimination Method</h6>
<p>$f_{(x,y)}$  is at the critical point $(a,b) \iff \frac{\partial f}{\partial x }=0,\frac{\partial f}{\partial y }=0$
Hessian matrix is</p>
<p>$
H=\begin{vmatrix}
\frac{\partial^2 f}{\partial x^2} & \frac{\partial f^2}{\partial x \partial y}  \newline
\frac{\partial f^2}{\partial x \partial y} & \frac{\partial^2 f}{\partial x^2} 
\end{vmatrix}
$</p>
<p>If the second-order partial derivatives are continuous,$\frac{\partial f^2}{\partial x \partial y}=\frac{\partial f^2}{\partial y \partial x}$
Discriminant: $D=\frac{\partial^2 f}{\partial x^2}\frac{\partial^2 f}{\partial y^2}-(\frac{\partial f^2}{\partial x \partial y})^2$</p>
<ul>
<li>$D>0,\frac{\partial^2 f}{\partial x^2}>0 \to $ mininmum  value point</li>
<li>$D>0,\frac{\partial^2 f}{\partial x^2}<0 \to $ maxinmum  value point</li>
<li>$D<0 \to $ saddle point (non-extremum)</li>
<li>$D=0 \to$ cannot determine (requires further analysis)</li>
</ul>
<blockquote>
<p>To sum,gradient descent normally use  $x_{n+1}=x_{n}-\alpha Grad(\textit f_{(x)})$</p>
</blockquote>
<h4 id="13-newton-method">1.3 Newton method</h4>
<h6 id="i">I  $ x_{n+1}=x_{n}- \frac {\textit f(x_{n})}{\textit f'(x_{n})} $</h6>
<p>Geometric intuitive derivation:</p>
<p>At point $x_{n}$,draw the tangent line of the function $y=f(x)$,the intersection point of this tangent line with the x-axis is used as the next estimate.</p>
<p>$y -f(x_{n})=f'(x_{n})(x-x_{n})$,</p>
<p>$0 -f(x_{n})=f'(x_{n})(x-x_{n})$,</p>
<p>$\to x_{n+1}=x_{n}- \frac {\textit f(x_{n})}{\textit f'(x_{n})}$</p>
<h6 id="ii">II  $ x_{n+1}=x_{n}- \frac {\textit f'(x_{n})}{\textit f''(x_{n})} $</h6>
<p>Taylor expansion:<br>
$f(x_{k}+t) \approx f(x_{k})+f'(x_{k})+ \frac {1}{2}f''(x_{k})t^2$,</p>
<p>$\frac {\partial f(x_{k}+t)}{\partial t} \approx f'(x_{k})+f''(x_{k})t=0 \to t=- \frac {\textit f'(x_{n})}{\textit f''(x_{n})}$,</p>
<p>$x_{n+1}=x_{n}- \frac {\textit f'(x_{n})}{\textit f''(x_{n})} $</p>
]]></content:encoded></item><item><title>总线系统</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/bus/</link><pubDate>Wed, 03 Sep 2025 18:17:48 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/bus/</guid><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;总线的概念和结构形态&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;总线的基本概念&lt;/a&gt;&lt;br&gt;
总线是一组公共的传输线，用于连接计算机的各个部件（CPU、内存、I/O设备），实现信息共享和交换。总线由数据总线（传输数据）、地址总线（传输地址）和控制总线（传输控制信号）三部分组成。总线按时序可分为同步总线（有时钟信号）和异步总线（握手信号）。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;总线的连接方式&lt;/a&gt;&lt;br&gt;
常见连接方式：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;单总线结构&lt;/strong&gt;：所有部件都连接到同一总线，简单但可能成为瓶颈（如早期IBM PC）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;双总线结构&lt;/strong&gt;：CPU与主存之间有一条高速内存总线，其他设备通过I/O总线与CPU通信（如南北桥架构）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多总线结构&lt;/strong&gt;：现代计算机使用多层次总线（如PCIe、DMI、QPI等）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;总线的内部结构&lt;/a&gt;&lt;br&gt;
总线内部包括：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;数据线&lt;/strong&gt;：宽度决定一次传输的位数（如32位、64位）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;地址线&lt;/strong&gt;：宽度决定可寻址空间。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;控制线&lt;/strong&gt;：包括读写信号、中断请求、总线请求/允许、时钟等。
此外还有电源线和地线。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;总线结构实例&lt;/a&gt;&lt;br&gt;
经典PC总线结构：CPU通过前端总线（FSB）连接北桥（内存控制器、AGP/PCIe），北桥连接南桥（PCI、ISA、USB、IDE等）。现代CPU集成内存控制器和PCIe控制器，芯片组简化为单芯片（PCH）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;总线接口&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;信息传送方式&lt;/a&gt;&lt;br&gt;
信息传送方式包括：并行（多位同时传输）和串行（逐位传输）。串行总线（如USB、PCIe）使用差分信号，距离长、速率高、引脚少。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;总线接口的基本概念&lt;/a&gt;&lt;br&gt;
总线接口（或称适配器、控制器）是连接设备与总线的逻辑电路。它负责数据缓冲、协议转换、电平转换、中断处理等。接口必须满足总线规定的电气和时序规范。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;总线仲裁&lt;/a&gt;&lt;br&gt;
当多个设备请求使用总线时，仲裁器决定哪个设备获得总线控制权。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;集中式仲裁&lt;/a&gt;&lt;br&gt;
一个中央总线仲裁器（常位于CPU或北桥）负责判决。常见方式：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;链式查询&lt;/strong&gt;：通过一条总线请求线，优先级由物理位置决定（离仲裁器越近优先级越高）。简单但速度慢，且优先级固定。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计数器定时查询&lt;/strong&gt;：仲裁器发计数值，设备匹配地址则获得总线。优先级可改变。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;独立请求方式&lt;/strong&gt;：每个设备有独立的请求线和允许线，仲裁器并行处理。速度快，但连线多（如PCI）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;分布式仲裁&lt;/a&gt;&lt;br&gt;
没有中央仲裁器，每个设备都有仲裁逻辑，通过共享的仲裁总线竞争。例如，SCSI总线使用分布式仲裁。优点是无单点故障。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;总线的定时和数据传送模式&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;总线的定时&lt;/a&gt;&lt;br&gt;
定时决定什么时候发送地址和数据：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;同步定时&lt;/strong&gt;：使用统一时钟，所有操作在时钟边沿发生。简单但所有设备需以相同频率工作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异步定时&lt;/strong&gt;：基于握手信号（请求、应答）。允许不同速度的设备共存，但控制稍复杂。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;总线数据传送模式&lt;/a&gt;&lt;br&gt;
常见传送模式：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;读/写周期&lt;/strong&gt;：主设备发送地址和控制信号，从设备返回数据或接收数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;突发传送&lt;/strong&gt;：一次地址后连续传送多个数据（如SDRAM突发模式），提高吞吐量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;块传送&lt;/strong&gt;：类似于突发。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分裂传送&lt;/strong&gt;：主设备请求后释放总线，从设备准备好后再重新申请，提高了总线利用率。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;PCI总线和PCIe总线&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;多总线结构&lt;/a&gt;&lt;br&gt;
PCI（外设组件互连）是一种并行总线，工作频率33/66MHz，32/64位宽度，带宽最高约533MB/s。PCIe（PCI Express）是高速串行总线，采用点对点连接和交换结构，替代了PCI和AGP。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;PCI总线信号&lt;/a&gt;&lt;br&gt;
PCI总线信号包括：地址/数据复用线（AD[31:0]）、控制信号（FRAME#, IRDY#, TRDY#）、仲裁信号（REQ#, GNT#）、错误报告（PERR#, SERR#）、中断信号等。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;PCI总线周期类型&lt;/a&gt;&lt;br&gt;
总线周期包括：配置周期（读写配置空间）、I/O周期、内存周期、特殊周期等。配置周期用于系统初始化时枚举设备。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;PCI总线周期操作&lt;/a&gt;&lt;br&gt;
一次PCI传输包含地址阶段（FRAME#有效，AD线上放地址）和数据阶段（IRDY#和TRDY#握手续传数据）。突发传输时地址只发一次，后续数据连续传送。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;PCI总线仲裁&lt;/a&gt;&lt;br&gt;
PCI总线使用集中式仲裁，每个主设备有独立的REQ#和GNT#线，仲裁器位于北桥或南桥。仲裁算法可以是轮询、优先级等。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;PCIe总线&lt;/a&gt;&lt;br&gt;
PCIe（PCI Express）采用高速串行差分信号（LANE），每个LANE发送速率从2.5GT/s（Gen1）到32GT/s（Gen5）及以上。支持x1、x2、x4、x8、x16、x32链路宽度。采用点对点交换结构，每个设备独享带宽。事务层使用数据包（TLP，事务层包）传递请求和完成。支持热插拔、电源管理、虚拟化等先进特性。PCIe已成为现代计算机的主流扩展总线，用于显卡、SSD、网卡等。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><content:encoded><![CDATA[<ul>
<li>
<p><a href="">总线的概念和结构形态</a></p>
<ul>
<li><a href="">总线的基本概念</a><br>
总线是一组公共的传输线，用于连接计算机的各个部件（CPU、内存、I/O设备），实现信息共享和交换。总线由数据总线（传输数据）、地址总线（传输地址）和控制总线（传输控制信号）三部分组成。总线按时序可分为同步总线（有时钟信号）和异步总线（握手信号）。</li>
<li><a href="">总线的连接方式</a><br>
常见连接方式：
<ul>
<li><strong>单总线结构</strong>：所有部件都连接到同一总线，简单但可能成为瓶颈（如早期IBM PC）。</li>
<li><strong>双总线结构</strong>：CPU与主存之间有一条高速内存总线，其他设备通过I/O总线与CPU通信（如南北桥架构）。</li>
<li><strong>多总线结构</strong>：现代计算机使用多层次总线（如PCIe、DMI、QPI等）。</li>
</ul>
</li>
<li><a href="">总线的内部结构</a><br>
总线内部包括：
<ul>
<li><strong>数据线</strong>：宽度决定一次传输的位数（如32位、64位）。</li>
<li><strong>地址线</strong>：宽度决定可寻址空间。</li>
<li><strong>控制线</strong>：包括读写信号、中断请求、总线请求/允许、时钟等。
此外还有电源线和地线。</li>
</ul>
</li>
<li><a href="">总线结构实例</a><br>
经典PC总线结构：CPU通过前端总线（FSB）连接北桥（内存控制器、AGP/PCIe），北桥连接南桥（PCI、ISA、USB、IDE等）。现代CPU集成内存控制器和PCIe控制器，芯片组简化为单芯片（PCH）。</li>
</ul>
</li>
<li>
<p><a href="">总线接口</a></p>
<ul>
<li><a href="">信息传送方式</a><br>
信息传送方式包括：并行（多位同时传输）和串行（逐位传输）。串行总线（如USB、PCIe）使用差分信号，距离长、速率高、引脚少。</li>
<li><a href="">总线接口的基本概念</a><br>
总线接口（或称适配器、控制器）是连接设备与总线的逻辑电路。它负责数据缓冲、协议转换、电平转换、中断处理等。接口必须满足总线规定的电气和时序规范。</li>
</ul>
</li>
<li>
<p><a href="">总线仲裁</a><br>
当多个设备请求使用总线时，仲裁器决定哪个设备获得总线控制权。</p>
<ul>
<li><a href="">集中式仲裁</a><br>
一个中央总线仲裁器（常位于CPU或北桥）负责判决。常见方式：
<ul>
<li><strong>链式查询</strong>：通过一条总线请求线，优先级由物理位置决定（离仲裁器越近优先级越高）。简单但速度慢，且优先级固定。</li>
<li><strong>计数器定时查询</strong>：仲裁器发计数值，设备匹配地址则获得总线。优先级可改变。</li>
<li><strong>独立请求方式</strong>：每个设备有独立的请求线和允许线，仲裁器并行处理。速度快，但连线多（如PCI）。</li>
</ul>
</li>
<li><a href="">分布式仲裁</a><br>
没有中央仲裁器，每个设备都有仲裁逻辑，通过共享的仲裁总线竞争。例如，SCSI总线使用分布式仲裁。优点是无单点故障。</li>
</ul>
</li>
<li>
<p><a href="">总线的定时和数据传送模式</a></p>
<ul>
<li><a href="">总线的定时</a><br>
定时决定什么时候发送地址和数据：
<ul>
<li><strong>同步定时</strong>：使用统一时钟，所有操作在时钟边沿发生。简单但所有设备需以相同频率工作。</li>
<li><strong>异步定时</strong>：基于握手信号（请求、应答）。允许不同速度的设备共存，但控制稍复杂。</li>
</ul>
</li>
<li><a href="">总线数据传送模式</a><br>
常见传送模式：
<ul>
<li><strong>读/写周期</strong>：主设备发送地址和控制信号，从设备返回数据或接收数据。</li>
<li><strong>突发传送</strong>：一次地址后连续传送多个数据（如SDRAM突发模式），提高吞吐量。</li>
<li><strong>块传送</strong>：类似于突发。</li>
<li><strong>分裂传送</strong>：主设备请求后释放总线，从设备准备好后再重新申请，提高了总线利用率。</li>
</ul>
</li>
</ul>
</li>
<li>
<p><a href="">PCI总线和PCIe总线</a></p>
<ul>
<li><a href="">多总线结构</a><br>
PCI（外设组件互连）是一种并行总线，工作频率33/66MHz，32/64位宽度，带宽最高约533MB/s。PCIe（PCI Express）是高速串行总线，采用点对点连接和交换结构，替代了PCI和AGP。</li>
<li><a href="">PCI总线信号</a><br>
PCI总线信号包括：地址/数据复用线（AD[31:0]）、控制信号（FRAME#, IRDY#, TRDY#）、仲裁信号（REQ#, GNT#）、错误报告（PERR#, SERR#）、中断信号等。</li>
<li><a href="">PCI总线周期类型</a><br>
总线周期包括：配置周期（读写配置空间）、I/O周期、内存周期、特殊周期等。配置周期用于系统初始化时枚举设备。</li>
<li><a href="">PCI总线周期操作</a><br>
一次PCI传输包含地址阶段（FRAME#有效，AD线上放地址）和数据阶段（IRDY#和TRDY#握手续传数据）。突发传输时地址只发一次，后续数据连续传送。</li>
<li><a href="">PCI总线仲裁</a><br>
PCI总线使用集中式仲裁，每个主设备有独立的REQ#和GNT#线，仲裁器位于北桥或南桥。仲裁算法可以是轮询、优先级等。</li>
<li><a href="">PCIe总线</a><br>
PCIe（PCI Express）采用高速串行差分信号（LANE），每个LANE发送速率从2.5GT/s（Gen1）到32GT/s（Gen5）及以上。支持x1、x2、x4、x8、x16、x32链路宽度。采用点对点交换结构，每个设备独享带宽。事务层使用数据包（TLP，事务层包）传递请求和完成。支持热插拔、电源管理、虚拟化等先进特性。PCIe已成为现代计算机的主流扩展总线，用于显卡、SSD、网卡等。</li>
</ul>
</li>
</ul>
]]></content:encoded></item><item><title>中央处理器</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/cpu/</link><pubDate>Wed, 03 Sep 2025 18:17:38 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/cpu/</guid><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;CPU的功能和组成&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;CPU的功能&lt;/a&gt;&lt;br&gt;
CPU是计算机的核心部件，其基本功能包括：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;指令控制&lt;/strong&gt;：从存储器取出指令，译码并执行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作控制&lt;/strong&gt;：产生微操作信号，驱动各部件执行指令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时间控制&lt;/strong&gt;：为每条指令提供时序节拍。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据加工&lt;/strong&gt;：通过ALU对数据进行算术/逻辑运算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中断处理&lt;/strong&gt;：响应外部/内部中断，切换进程。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;CPU的基本组成&lt;/a&gt;&lt;br&gt;
CPU主要由运算器、控制器、寄存器组和内部总线组成。控制器包括程序计数器（PC）、指令寄存器（IR）、指令译码器、时序产生器和控制逻辑（微程序或硬布线）。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;CPU中的主要寄存器&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;程序计数器（PC）&lt;/strong&gt;：存放下一条指令的地址。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;指令寄存器（IR）&lt;/strong&gt;：存放当前正在执行的指令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;累加器（ACC）&lt;/strong&gt;：存放中间运算结果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态寄存器（PSW/Flag）&lt;/strong&gt;：存放条件标志（C、Z、N、V）和中断允许等状态。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通用寄存器（R0-Rn）&lt;/strong&gt;：存放操作数和地址。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;堆栈指针（SP）&lt;/strong&gt;：指向栈顶地址。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基址/变址寄存器&lt;/strong&gt;：支持多种寻址方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;操作控制器与时序产生器&lt;/a&gt;&lt;br&gt;
操作控制器产生微操作命令序列，分为微程序控制器（存储微指令）和硬布线控制器（组合逻辑）。时序产生器提供时钟信号和节拍信号，控制指令的执行步骤。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;指令周期&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;指令周期的基本概念&lt;/a&gt;&lt;br&gt;
指令周期是指CPU从取指令、译码到执行完一条指令所花的时间。一个指令周期通常包含取指周期（取指令）、间址周期（若需取操作数地址）、执行周期、中断周期（若响应中断）。每个周期又由若干时钟周期（T周期）组成。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;MOV指令的指令周期&lt;/a&gt;&lt;br&gt;
MOV指令（寄存器间或立即数传送）的指令周期：取指→译码→执行（传送数据）。执行周期只需一个时钟周期（寄存器间）。若MOV涉及内存，则需内存读/写周期。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;LAD指令的指令周期&lt;/a&gt;&lt;br&gt;
LAD（LOAD）从内存读数据到寄存器：取指→译码→计算地址→读内存→写寄存器。执行周期包括地址计算和内存访问，通常需多个时钟周期。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;ADD指令的指令周期&lt;/a&gt;&lt;br&gt;
ADD加法指令（寄存器-寄存器）：取指→译码→ALU计算→写回结果。执行周期为1个时钟周期。若为内存操作数，则需额外访存周期。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;STO指令的指令周期&lt;/a&gt;&lt;br&gt;
STO（STORE）将寄存器内容写回内存：取指→译码→计算地址→写内存。写内存通常需要1个周期（假设内存写操作）。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;JMP指令的指令周期&lt;/a&gt;&lt;br&gt;
JMP无条件跳转：取指→译码→计算目标地址→将目标地址写入PC。执行周期短。条件跳转还需根据标志位决定是否修改PC。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;用方框图语言表示指令周期&lt;/a&gt;&lt;br&gt;
方框图语言以矩形框表示操作（如“取指令”）、菱形框表示判断（如“是否需要间址”），描述指令周期流程。可以清晰展示微操作序列和时序关系。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;时序产生器和控制方式&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;时序信号的作用和体制&lt;/a&gt;&lt;br&gt;
时序信号为CPU各部件提供同步节拍。常见体制：单节拍（所有操作在一个时钟周期完成，限于低速）、多节拍（每条指令分多个时钟周期）、异步（无统一时钟，应答方式）。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;时序信号产生器&lt;/a&gt;&lt;br&gt;
时序产生器由晶体振荡器（产生主频时钟）、分频器、节拍发生器（环形计数器或分频逻辑）组成。产生时钟周期（T1, T2&amp;hellip;）、机器周期（M周期）、指令周期等信号。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;控制方式&lt;/a&gt;&lt;br&gt;
控制方式指CPU如何发出微操作命令：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;同步控制&lt;/strong&gt;：所有指令使用固定长度的时钟周期。简单但效率低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异步控制&lt;/strong&gt;：每条指令或微操作采用应答方式，速度较快但控制复杂。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;联合控制&lt;/strong&gt;：大部分指令同步，少数复杂指令异步扩展。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;微程序控制器&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;微程序控制原理&lt;/a&gt;&lt;br&gt;
微程序控制将机器指令（宏指令）解释为一串微指令序列。控制存储器（ROM或RAM）存放微程序。执行指令时，微地址生成器根据指令操作码产生微地址，逐条读取微指令，每个微指令产生一组微操作控制信号。微指令格式分为水平型（一个时钟周期执行多个微操作）和垂直型（类似于机器指令的微指令）。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;微程序设计技术&lt;/a&gt;&lt;br&gt;
微程序设计技术包括：微指令编码（直接编码、字段直接编码、字段间接编码）、微地址形成（增量、多路转移、下址字段）、微程序顺序控制、微程序设计语言等。现代CPU的微程序常采用加标签的控制存储和分支逻辑。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;硬布线控制器&lt;/a&gt;&lt;br&gt;
硬布线控制器由组合逻辑电路（门电路、触发器）构成，直接根据指令操作码、时序节拍和状态条件产生控制信号。速度比微程序控制器快，但指令集复杂时逻辑设计极为复杂，不易修改。RISC处理器多采用硬布线控制（也有少数RISC使用微程序）。CISC的早期如8086使用微程序，后来逐步混合。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;流水CPU&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;并行处理技术&lt;/a&gt;&lt;br&gt;
并行处理技术包括：指令流水线（时间并行）、多发射（超标量）、多核（空间并行）。流水线将指令执行分解为若干阶段（取指、译码、执行、访存、写回），多个指令重叠执行。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;流水CPU的结构&lt;/a&gt;&lt;br&gt;
经典五级流水线：IF（取指令）、ID（指令译码/读寄存器）、EX（执行/地址计算）、MEM（访存）、WB（写回）。流水线寄存器（IF/ID、ID/EX、EX/MEM、MEM/WB）用于传递数据和控制信号。流水线需要处理结构冒险、数据冒险和控制冒险。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;流水线中的主要问题&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构冒险&lt;/strong&gt;：资源冲突，如指令和数据共用同一存储器。解决：哈佛结构（指令/数据分离）、增加资源。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据冒险&lt;/strong&gt;：后一条指令依赖前一条指令的结果。解决：转发（旁路）、插入气泡（停顿）、编译优化。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;控制冒险&lt;/strong&gt;：分支指令改变PC，导致流水线冲刷。解决：分支预测（静态/动态）、延迟槽（早期RISC）。
现代流水线深度可达10-20级（如Intel Core）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;RISC CPU&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;RISC机器的特点&lt;/a&gt;&lt;br&gt;
前面已述。RISC通常采用流水线、单周期指令、LOAD/STORE结构、大量寄存器。典型RISC处理器有ARM、MIPS、RISC-V、PowerPC（早期）等。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;RISC CPU实例&lt;/a&gt;&lt;br&gt;
ARM Cortex-A系列：多级流水线（通常13级或更少），支持超标量、乱序执行。RISC-V是一个开源指令集，设计简洁，适合教育和嵌入式。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;动态流水线调度&lt;/a&gt;&lt;br&gt;
动态调度由硬件（如Tomasulo算法）在运行时重排指令顺序，减少数据冒险造成的停顿。需要保留站、重排序缓冲（ROB）和寄存器重命名技术。常见于高性能处理器（Intel Core、AMD Zen）。与之相对的是静态调度（编译器优化）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><content:encoded><![CDATA[<ul>
<li>
<p><a href="">CPU的功能和组成</a></p>
<ul>
<li><a href="">CPU的功能</a><br>
CPU是计算机的核心部件，其基本功能包括：
<ul>
<li><strong>指令控制</strong>：从存储器取出指令，译码并执行。</li>
<li><strong>操作控制</strong>：产生微操作信号，驱动各部件执行指令。</li>
<li><strong>时间控制</strong>：为每条指令提供时序节拍。</li>
<li><strong>数据加工</strong>：通过ALU对数据进行算术/逻辑运算。</li>
<li><strong>中断处理</strong>：响应外部/内部中断，切换进程。</li>
</ul>
</li>
<li><a href="">CPU的基本组成</a><br>
CPU主要由运算器、控制器、寄存器组和内部总线组成。控制器包括程序计数器（PC）、指令寄存器（IR）、指令译码器、时序产生器和控制逻辑（微程序或硬布线）。</li>
<li><a href="">CPU中的主要寄存器</a>
<ul>
<li><strong>程序计数器（PC）</strong>：存放下一条指令的地址。</li>
<li><strong>指令寄存器（IR）</strong>：存放当前正在执行的指令。</li>
<li><strong>累加器（ACC）</strong>：存放中间运算结果。</li>
<li><strong>状态寄存器（PSW/Flag）</strong>：存放条件标志（C、Z、N、V）和中断允许等状态。</li>
<li><strong>通用寄存器（R0-Rn）</strong>：存放操作数和地址。</li>
<li><strong>堆栈指针（SP）</strong>：指向栈顶地址。</li>
<li><strong>基址/变址寄存器</strong>：支持多种寻址方式。</li>
</ul>
</li>
<li><a href="">操作控制器与时序产生器</a><br>
操作控制器产生微操作命令序列，分为微程序控制器（存储微指令）和硬布线控制器（组合逻辑）。时序产生器提供时钟信号和节拍信号，控制指令的执行步骤。</li>
</ul>
</li>
<li>
<p><a href="">指令周期</a></p>
<ul>
<li><a href="">指令周期的基本概念</a><br>
指令周期是指CPU从取指令、译码到执行完一条指令所花的时间。一个指令周期通常包含取指周期（取指令）、间址周期（若需取操作数地址）、执行周期、中断周期（若响应中断）。每个周期又由若干时钟周期（T周期）组成。</li>
<li><a href="">MOV指令的指令周期</a><br>
MOV指令（寄存器间或立即数传送）的指令周期：取指→译码→执行（传送数据）。执行周期只需一个时钟周期（寄存器间）。若MOV涉及内存，则需内存读/写周期。</li>
<li><a href="">LAD指令的指令周期</a><br>
LAD（LOAD）从内存读数据到寄存器：取指→译码→计算地址→读内存→写寄存器。执行周期包括地址计算和内存访问，通常需多个时钟周期。</li>
<li><a href="">ADD指令的指令周期</a><br>
ADD加法指令（寄存器-寄存器）：取指→译码→ALU计算→写回结果。执行周期为1个时钟周期。若为内存操作数，则需额外访存周期。</li>
<li><a href="">STO指令的指令周期</a><br>
STO（STORE）将寄存器内容写回内存：取指→译码→计算地址→写内存。写内存通常需要1个周期（假设内存写操作）。</li>
<li><a href="">JMP指令的指令周期</a><br>
JMP无条件跳转：取指→译码→计算目标地址→将目标地址写入PC。执行周期短。条件跳转还需根据标志位决定是否修改PC。</li>
<li><a href="">用方框图语言表示指令周期</a><br>
方框图语言以矩形框表示操作（如“取指令”）、菱形框表示判断（如“是否需要间址”），描述指令周期流程。可以清晰展示微操作序列和时序关系。</li>
</ul>
</li>
<li>
<p><a href="">时序产生器和控制方式</a></p>
<ul>
<li><a href="">时序信号的作用和体制</a><br>
时序信号为CPU各部件提供同步节拍。常见体制：单节拍（所有操作在一个时钟周期完成，限于低速）、多节拍（每条指令分多个时钟周期）、异步（无统一时钟，应答方式）。</li>
<li><a href="">时序信号产生器</a><br>
时序产生器由晶体振荡器（产生主频时钟）、分频器、节拍发生器（环形计数器或分频逻辑）组成。产生时钟周期（T1, T2&hellip;）、机器周期（M周期）、指令周期等信号。</li>
<li><a href="">控制方式</a><br>
控制方式指CPU如何发出微操作命令：
<ul>
<li><strong>同步控制</strong>：所有指令使用固定长度的时钟周期。简单但效率低。</li>
<li><strong>异步控制</strong>：每条指令或微操作采用应答方式，速度较快但控制复杂。</li>
<li><strong>联合控制</strong>：大部分指令同步，少数复杂指令异步扩展。</li>
</ul>
</li>
</ul>
</li>
<li>
<p><a href="">微程序控制器</a></p>
<ul>
<li><a href="">微程序控制原理</a><br>
微程序控制将机器指令（宏指令）解释为一串微指令序列。控制存储器（ROM或RAM）存放微程序。执行指令时，微地址生成器根据指令操作码产生微地址，逐条读取微指令，每个微指令产生一组微操作控制信号。微指令格式分为水平型（一个时钟周期执行多个微操作）和垂直型（类似于机器指令的微指令）。</li>
<li><a href="">微程序设计技术</a><br>
微程序设计技术包括：微指令编码（直接编码、字段直接编码、字段间接编码）、微地址形成（增量、多路转移、下址字段）、微程序顺序控制、微程序设计语言等。现代CPU的微程序常采用加标签的控制存储和分支逻辑。</li>
</ul>
</li>
<li>
<p><a href="">硬布线控制器</a><br>
硬布线控制器由组合逻辑电路（门电路、触发器）构成，直接根据指令操作码、时序节拍和状态条件产生控制信号。速度比微程序控制器快，但指令集复杂时逻辑设计极为复杂，不易修改。RISC处理器多采用硬布线控制（也有少数RISC使用微程序）。CISC的早期如8086使用微程序，后来逐步混合。</p>
</li>
<li>
<p><a href="">流水CPU</a></p>
<ul>
<li><a href="">并行处理技术</a><br>
并行处理技术包括：指令流水线（时间并行）、多发射（超标量）、多核（空间并行）。流水线将指令执行分解为若干阶段（取指、译码、执行、访存、写回），多个指令重叠执行。</li>
<li><a href="">流水CPU的结构</a><br>
经典五级流水线：IF（取指令）、ID（指令译码/读寄存器）、EX（执行/地址计算）、MEM（访存）、WB（写回）。流水线寄存器（IF/ID、ID/EX、EX/MEM、MEM/WB）用于传递数据和控制信号。流水线需要处理结构冒险、数据冒险和控制冒险。</li>
<li><a href="">流水线中的主要问题</a>
<ul>
<li><strong>结构冒险</strong>：资源冲突，如指令和数据共用同一存储器。解决：哈佛结构（指令/数据分离）、增加资源。</li>
<li><strong>数据冒险</strong>：后一条指令依赖前一条指令的结果。解决：转发（旁路）、插入气泡（停顿）、编译优化。</li>
<li><strong>控制冒险</strong>：分支指令改变PC，导致流水线冲刷。解决：分支预测（静态/动态）、延迟槽（早期RISC）。
现代流水线深度可达10-20级（如Intel Core）。</li>
</ul>
</li>
</ul>
</li>
<li>
<p><a href="">RISC CPU</a></p>
<ul>
<li><a href="">RISC机器的特点</a><br>
前面已述。RISC通常采用流水线、单周期指令、LOAD/STORE结构、大量寄存器。典型RISC处理器有ARM、MIPS、RISC-V、PowerPC（早期）等。</li>
<li><a href="">RISC CPU实例</a><br>
ARM Cortex-A系列：多级流水线（通常13级或更少），支持超标量、乱序执行。RISC-V是一个开源指令集，设计简洁，适合教育和嵌入式。</li>
<li><a href="">动态流水线调度</a><br>
动态调度由硬件（如Tomasulo算法）在运行时重排指令顺序，减少数据冒险造成的停顿。需要保留站、重排序缓冲（ROB）和寄存器重命名技术。常见于高性能处理器（Intel Core、AMD Zen）。与之相对的是静态调度（编译器优化）。</li>
</ul>
</li>
</ul>
]]></content:encoded></item><item><title>指令系统</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/instruction-set/</link><pubDate>Wed, 03 Sep 2025 18:17:20 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/instruction-set/</guid><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;指令系统的发展与性能要求&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;指令系统的发展&lt;/a&gt;&lt;br&gt;
早期计算机指令非常简单（如单地址、零地址指令）。随着硬件发展和应用需求，指令系统从基本算术逻辑扩展至浮点运算、字符串处理、多媒体（SIMD指令）、加密等。出现了复杂指令集计算机（CISC）和精简指令集计算机（RISC）两种设计哲学。CISC（如x86）指令丰富，便于编程但实现复杂；RISC（如ARM、MIPS）指令精简、规整，易于流水线和高频实现。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;指令系统的性能要求&lt;/a&gt;&lt;br&gt;
指令系统应满足：完整性（覆盖所有必要操作）、规整性（指令格式简单，寻址方式一致）、高效性（常用指令执行快）、兼容性（软件向前兼容）、可扩展性（便于增加新指令）。此外，还需要支持高级语言、操作系统和并发编程。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;低级语言与硬件结构的关系&lt;/a&gt;&lt;br&gt;
机器语言（二进制）和汇编语言（助记符）直接对应机器指令，与硬件结构（寄存器、ALU、总线等）紧密相关。程序员通过低级语言可以直接控制硬件资源，但编程效率低。高级语言通过编译或解释转换为目标机器指令，抽象层次更高。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;指令格式&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;操作码&lt;/a&gt;&lt;br&gt;
操作码（Opcode）指定指令要执行的操作（如ADD、MOV）。操作码长度可以是定长（便于译码，如RISC通常32位固定长度）或变长（如x86，1-15字节，节省空间但译码复杂）。操作码设计常采用扩展操作码技术，通过预留码点扩展指令数量。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;地址码&lt;/a&gt;&lt;br&gt;
地址码字段指明操作数的来源和结果的去向。根据地址码数量，指令可分为三地址、二地址、一地址、零地址（如堆栈机）。例如：ADD R1, R2, R3 （R1←R2+R3）为三地址；ADD R1, R2 （R1←R1+R2）为二地址；ADD R1 （ACC←ACC+R1）为一地址。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;指令字长度&lt;/a&gt;&lt;br&gt;
指令字长度可以是定长（如ARM的32位）或变长（如x86的1-15字节）。定长指令便于取指和译码，适合流水线；变长指令代码密度高，节省内存。现代处理器常采用混合方式：主流RISC为定长32位，CISC使用变长，但在内部转换为类似RISC的微操作。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;指令助记符&lt;/a&gt;&lt;br&gt;
助记符（Mnemonic）是汇编语言中表示操作码的英文缩写，如ADD、SUB、MOV、JMP。便于记忆和编写。操作数通常使用寄存器符号（如EAX）或立即数、内存地址表达式。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;指令格式举例&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ARM 32位指令&lt;/strong&gt;：例如 &lt;code&gt;ADD r0, r1, r2&lt;/code&gt;（机器码：&lt;code&gt;E0810002&lt;/code&gt;，其中[31:28]条件码，[27:25]为00，[24:21]操作为0100，[20]为S位等）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;x86指令&lt;/strong&gt;：变长，例如 &lt;code&gt;89 C8&lt;/code&gt; 表示 &lt;code&gt;MOV eax, ecx&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;操作数类型&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;一般的数据类型&lt;/a&gt;&lt;br&gt;
常见操作数类型：整数（字节、半字、字、双字）、浮点数（单精度/双精度）、字符（ASCII/Unicode）、逻辑数（布尔值）、指针（地址）。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;Pentium数据类型&lt;/a&gt;&lt;br&gt;
英特尔x86支持：字节（8位）、字（16位）、双字（32位）、四字（64位）、双四字（128位，用于SSE）、10字节扩展浮点数（80位）。也支持BCD（二进制编码十进制）和打包的SIMD数据。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;Power PC数据类型&lt;/a&gt;&lt;br&gt;
PowerPC（RISC）支持：字节、半字（16位）、字（32位）、双字（64位）。浮点类型为单精度和双精度。支持对齐访问。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;指令和数据的寻址方式&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;指令的寻址方式&lt;/a&gt;&lt;br&gt;
指令的寻址即确定下一条指令的地址。顺序执行时，指令地址由程序计数器（PC）自动递增；跳转指令通过偏移量（相对寻址）或绝对地址改变PC值。&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;操作数基本寻址方式&lt;/a&gt;&lt;br&gt;
常见寻址方式：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;立即寻址&lt;/strong&gt;：操作数直接包含在指令中（如 &lt;code&gt;ADD R1, #5&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;寄存器寻址&lt;/strong&gt;：操作数存放在寄存器中（如 &lt;code&gt;ADD R1, R2&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;直接寻址&lt;/strong&gt;：指令给出内存地址（如 &lt;code&gt;ADD R1, [1000]&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;间接寻址&lt;/strong&gt;：指令给出存放地址的寄存器或内存单元（如 &lt;code&gt;ADD R1, [R2]&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;变址寻址&lt;/strong&gt;：基址寄存器+偏移量（如 &lt;code&gt;ADD R1, [R2 + 10]&lt;/code&gt;），适于数组访问。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;相对寻址&lt;/strong&gt;：PC+偏移量，用于转移指令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基址寻址&lt;/strong&gt;：基址寄存器+偏移量，常用于重定位。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;堆栈寻址&lt;/strong&gt;：隐含使用堆栈指针（SP）访问栈顶。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=""&gt;寻址方式举例&lt;/a&gt;&lt;br&gt;
以ARM为例：&lt;code&gt;LDR R1, [R2, #8]&lt;/code&gt;（变址）、&lt;code&gt;LDR R1, [R2, R3]&lt;/code&gt;（寄存器偏移）、&lt;code&gt;LDR R1, label&lt;/code&gt;（PC相对寻址）。x86的 &lt;code&gt;MOV eax, [ebx+ecx*4+8]&lt;/code&gt; 复杂变址。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;典型指令&lt;/a&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<ul>
<li>
<p><a href="">指令系统的发展与性能要求</a></p>
<ul>
<li><a href="">指令系统的发展</a><br>
早期计算机指令非常简单（如单地址、零地址指令）。随着硬件发展和应用需求，指令系统从基本算术逻辑扩展至浮点运算、字符串处理、多媒体（SIMD指令）、加密等。出现了复杂指令集计算机（CISC）和精简指令集计算机（RISC）两种设计哲学。CISC（如x86）指令丰富，便于编程但实现复杂；RISC（如ARM、MIPS）指令精简、规整，易于流水线和高频实现。</li>
<li><a href="">指令系统的性能要求</a><br>
指令系统应满足：完整性（覆盖所有必要操作）、规整性（指令格式简单，寻址方式一致）、高效性（常用指令执行快）、兼容性（软件向前兼容）、可扩展性（便于增加新指令）。此外，还需要支持高级语言、操作系统和并发编程。</li>
<li><a href="">低级语言与硬件结构的关系</a><br>
机器语言（二进制）和汇编语言（助记符）直接对应机器指令，与硬件结构（寄存器、ALU、总线等）紧密相关。程序员通过低级语言可以直接控制硬件资源，但编程效率低。高级语言通过编译或解释转换为目标机器指令，抽象层次更高。</li>
</ul>
</li>
<li>
<p><a href="">指令格式</a></p>
<ul>
<li><a href="">操作码</a><br>
操作码（Opcode）指定指令要执行的操作（如ADD、MOV）。操作码长度可以是定长（便于译码，如RISC通常32位固定长度）或变长（如x86，1-15字节，节省空间但译码复杂）。操作码设计常采用扩展操作码技术，通过预留码点扩展指令数量。</li>
<li><a href="">地址码</a><br>
地址码字段指明操作数的来源和结果的去向。根据地址码数量，指令可分为三地址、二地址、一地址、零地址（如堆栈机）。例如：ADD R1, R2, R3 （R1←R2+R3）为三地址；ADD R1, R2 （R1←R1+R2）为二地址；ADD R1 （ACC←ACC+R1）为一地址。</li>
<li><a href="">指令字长度</a><br>
指令字长度可以是定长（如ARM的32位）或变长（如x86的1-15字节）。定长指令便于取指和译码，适合流水线；变长指令代码密度高，节省内存。现代处理器常采用混合方式：主流RISC为定长32位，CISC使用变长，但在内部转换为类似RISC的微操作。</li>
<li><a href="">指令助记符</a><br>
助记符（Mnemonic）是汇编语言中表示操作码的英文缩写，如ADD、SUB、MOV、JMP。便于记忆和编写。操作数通常使用寄存器符号（如EAX）或立即数、内存地址表达式。</li>
<li><a href="">指令格式举例</a>
<ul>
<li><strong>ARM 32位指令</strong>：例如 <code>ADD r0, r1, r2</code>（机器码：<code>E0810002</code>，其中[31:28]条件码，[27:25]为00，[24:21]操作为0100，[20]为S位等）。</li>
<li><strong>x86指令</strong>：变长，例如 <code>89 C8</code> 表示 <code>MOV eax, ecx</code>。</li>
</ul>
</li>
</ul>
</li>
<li>
<p><a href="">操作数类型</a></p>
<ul>
<li><a href="">一般的数据类型</a><br>
常见操作数类型：整数（字节、半字、字、双字）、浮点数（单精度/双精度）、字符（ASCII/Unicode）、逻辑数（布尔值）、指针（地址）。</li>
<li><a href="">Pentium数据类型</a><br>
英特尔x86支持：字节（8位）、字（16位）、双字（32位）、四字（64位）、双四字（128位，用于SSE）、10字节扩展浮点数（80位）。也支持BCD（二进制编码十进制）和打包的SIMD数据。</li>
<li><a href="">Power PC数据类型</a><br>
PowerPC（RISC）支持：字节、半字（16位）、字（32位）、双字（64位）。浮点类型为单精度和双精度。支持对齐访问。</li>
</ul>
</li>
<li>
<p><a href="">指令和数据的寻址方式</a></p>
<ul>
<li><a href="">指令的寻址方式</a><br>
指令的寻址即确定下一条指令的地址。顺序执行时，指令地址由程序计数器（PC）自动递增；跳转指令通过偏移量（相对寻址）或绝对地址改变PC值。</li>
<li><a href="">操作数基本寻址方式</a><br>
常见寻址方式：
<ul>
<li><strong>立即寻址</strong>：操作数直接包含在指令中（如 <code>ADD R1, #5</code>）。</li>
<li><strong>寄存器寻址</strong>：操作数存放在寄存器中（如 <code>ADD R1, R2</code>）。</li>
<li><strong>直接寻址</strong>：指令给出内存地址（如 <code>ADD R1, [1000]</code>）。</li>
<li><strong>间接寻址</strong>：指令给出存放地址的寄存器或内存单元（如 <code>ADD R1, [R2]</code>）。</li>
<li><strong>变址寻址</strong>：基址寄存器+偏移量（如 <code>ADD R1, [R2 + 10]</code>），适于数组访问。</li>
<li><strong>相对寻址</strong>：PC+偏移量，用于转移指令。</li>
<li><strong>基址寻址</strong>：基址寄存器+偏移量，常用于重定位。</li>
<li><strong>堆栈寻址</strong>：隐含使用堆栈指针（SP）访问栈顶。</li>
</ul>
</li>
<li><a href="">寻址方式举例</a><br>
以ARM为例：<code>LDR R1, [R2, #8]</code>（变址）、<code>LDR R1, [R2, R3]</code>（寄存器偏移）、<code>LDR R1, label</code>（PC相对寻址）。x86的 <code>MOV eax, [ebx+ecx*4+8]</code> 复杂变址。</li>
</ul>
</li>
<li>
<p><a href="">典型指令</a></p>
<ul>
<li><a href="">指令的分类</a><br>
指令通常分为：
<ul>
<li><strong>数据传送指令</strong>（MOV，LOAD，STORE）</li>
<li><strong>算术运算指令</strong>（ADD，SUB，MUL，DIV）</li>
<li><strong>逻辑运算指令</strong>（AND，OR，XOR，NOT，移位）</li>
<li><strong>控制转移指令</strong>（JMP，BCC（条件分支），CALL，RET）</li>
<li><strong>输入输出指令</strong>（IN，OUT）</li>
<li><strong>系统控制指令</strong>（NOP，HLT，特权指令）</li>
<li><strong>浮点指令</strong>（FADD，FMUL等）</li>
<li><strong>SIMD指令</strong>（MMX，SSE，AVX，NEON）</li>
</ul>
</li>
<li><a href="">基本指令系统的操作</a><br>
基本指令包括：算术/逻辑、存储器读写、分支、子程序调用/返回、堆栈操作等。例如，一个简单RISC指令集通常包含20-40种指令。</li>
<li><a href="">RISC指令系统</a><br>
RISC（精简指令集计算机）的特点：
<ul>
<li>指令数量少，每条指令功能简单，执行时间固定（通常单周期）。</li>
<li>指令长度固定，格式规整。</li>
<li>只有LOAD/STORE指令访问内存，其他指令操作数均来自寄存器。</li>
<li>大量通用寄存器（32个或更多）。</li>
<li>硬件实现简单，利于流水线和超标量。
典型RISC：ARM、MIPS、RISC-V。</li>
</ul>
</li>
</ul>
</li>
<li>
<p><a href="">ARM汇编语言</a><br>
ARM汇编语言基于ARM指令集（32位/64位）。常见指令：<code>MOV</code>（传送）、<code>ADD</code>/<code>SUB</code>（加减）、<code>LDR</code>/<code>STR</code>（内存读写）、<code>B</code>/<code>BL</code>（分支/带返回分支）、<code>CMP</code>（比较）、条件执行（如<code>ADDEQ</code>）。寄存器：R0-R12通用，R13（SP），R14（LR），R15（PC）。示例程序：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-armasm" data-lang="armasm"><span class="line"><span class="cl">    AREA <span class="err">Example</span>, <span class="err">CODE</span>, <span class="err">READONLY</span>
</span></span><span class="line"><span class="cl">    ENTRY
</span></span><span class="line"><span class="cl">    MOV <span class="err">R0</span>, #<span class="mi">5</span>
</span></span><span class="line"><span class="cl">    MOV <span class="err">R1</span>, #<span class="mi">3</span>
</span></span><span class="line"><span class="cl">    ADD <span class="err">R2</span>, <span class="err">R0</span>, <span class="err">R1</span>   <span class="c1">; R2 = 8
</span></span></span><span class="line"><span class="cl">    END
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<hr>
<p><a href="/pdf/%E8%AE%A1%E7%BB%84%E7%AC%AC4%E7%AB%A0.pdf">4</a></p>
]]></content:encoded></item><item><title>存储系统</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/storage/</link><pubDate>Wed, 03 Sep 2025 18:17:02 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/storage/</guid><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;存储系统概述&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;存储系统的层次结构&lt;/a&gt;&lt;br&gt;
&lt;img alt="alt text" loading="lazy" src="https://farmer3-c.github.io/img/in-post/pocc1.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;为了解决存储容量、存取速度和价格之间的矛盾，计算机中通常采用多级存储器体系结构，即使用高速缓冲存储器、主存储器和外存储器。CPU能直接访问的存储器称为&lt;strong&gt;内存储器&lt;/strong&gt;，包括高速缓冲存储器和主存储器。CPU不能直接访问&lt;strong&gt;外存储器&lt;/strong&gt;，外存储器的信息必须调入内存储器才能被CPU处理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高速缓冲存储器－主存 层次：CPU的处理速度比主存的存取速度快。为弥补主存速度的不足，在主存和CPU之间增加一级&lt;strong&gt;高速缓冲存储器&lt;/strong&gt;(&lt;strong&gt;Cache&lt;/strong&gt;)。其特点是速度高而容量小。它所存放的是主存中部分内容的复制，是当前最有可能被CPU访问的信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;从整体看，Cache－主存层次的存取速度接近于Cache的速度，而容量接近于主存的容量。Cache存储器全部由硬件调度，对程序员是透明的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;从整体看，主存－辅存层次具有接近于主存的速度和接近于辅存的容量。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;存储器的分类&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;按存储介质分
• 半导体存储器：主要有MOS型存储器和双极型存储器两大类。
• 磁表面存储器：在金属或塑料基体上，涂覆一层磁性材料，用磁层存储信息，常见的有磁盘、磁带等。
• 光存储器：采用激光技术访问的存储器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按存取方式分
• 随机存储器：任何存储单元的内容都能被&lt;strong&gt;随机存取&lt;/strong&gt;，且存取时间和存储单元的物理位置无关。如半导体存储器。
• 顺序存储器：只能按某种&lt;strong&gt;顺序来存取&lt;/strong&gt;，存取时间和存储单元的物理位置有关。如磁带存储器。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;磁盘存储器既不像随机存储器那样能随机地访问任一个存储单元，也不像顺序存储器那样完全按顺序存取，而是介于两者之间。存取信息时，第一步指向整个存储器中的某个小区域（磁盘上的磁道）；第二步在小区域内顺序检索，直至找到目的地后再进行读/写操作。其存取时间和信息的物理位置有一定关系。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按存储器的读写功能分
• 只读存储器(ROM)：存储的内容固定不变，只能读出而不能写入。
• 随机读写存储器(RAM)：既能读出又能写入。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按信息的可保存性分&lt;br&gt;
• 易失性存储器：断电后信息即消失的存储器。
• 非易失性存储器：断电后仍能保存信息的存储器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按在计算机系统中的作用分&lt;br&gt;
• 根据存储器在计算机系统中所起的作用，可分为主存储器、辅助存储器、高速缓冲存储器、控制存储器（用于存放微程序，由ROM构成）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;存储器的编址和端模式&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;存储器的技术指标&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;存储容量：存储器所包含的存储单元的总数称为存储容量。存储容量用字数或字节数表示。一个字节定义为8个二进制位，一个字包括2个或4个字节。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存取时间：从启动一次存储器操作到完成该操作所经历的时间。例如：读出时间是指从CPU向主存发出有效地址和读命令开始，直到将被选单元的内容读出为止所用的时间；写入时间是指从CPU向主存发出有效地址和写命令开始，直到信息写入被选中单元为止所用的时间。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存取周期：连续两次访问存储器操作之间所需要的最短时间。一般情况下，存取周期大于存取时间。这是因为对于任何一种存储器，在读写操作之后，总要有一段恢复内部状态的复原时间。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存储器带宽：又称数据传输率，指单位时间内存储器可读写的数据量，用位/秒或字节/秒度量。由存取周期和字长决定。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可靠性：用平均无故障时间来衡量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;其它参数：功耗、价格等。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=""&gt;静态随机存取存储器&lt;/a&gt;&lt;br&gt;
目前广泛使用的半导体存储器是MOS型半导体存储器，可以分为静态MOS型存储器（Static RAM）和动态MOS型存储器（Dynamic RAM）&lt;/p&gt;
&lt;div align="center"&gt;
&lt;img src="https://farmer3-c.github.io/img/in-post/pocc2.png" alt="六管SRAM存储元的电路图"&gt;
&lt;br&gt;
&lt;em&gt;六管SRAM存储元的电路图&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;$T_3、T_4$相当于负载电阻，$T_1、T_2$构成双稳态触发器。若$T_1$截止，A为高电平，使$T_2$导通，B为低电平，而B的低电平又使$T_1$更加截止；反之，若B为高电平，则A为低电平。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;可见该电路有两个稳定状态，且A和B两点电位总是互反的。如果用A点高电平代表 “1”，A点低电平代表 “ 0”，该电路可存储一位二进制数。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;$T_5、T_6、T_7和T_8$为控制管。如果某存储元被选中，X、Y地址译码线均处于高电平，使$T_5～T_8$导通，输入输出电路I/O和$\overline{I/O}$分别与A点和B点相连，A点和B点的电平状态就能输出到I/O和$\overline{I/O}$上，完成&lt;strong&gt;读操作&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;写操作时，如果要写入“1”，在I/O线上输入高电位，在$\overline{I/O}$线上输入低电位，开启$T_5～T_8$四个MOS管把高、低电位分别加在A、B点，使$T_1$管截止，使$T_2$管导通，将“1”写入存储元。如果要写入“0”，在I/O线上输入低电位，在$\overline{I/O}$线上输入高电位，打开$T_5～T_8$，把低、高电位分别加在A、B点，使$T_1$管导通，$T_2$管截止，将“0” 写入存储元。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=""&gt;基本的静态存储元阵列&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="center"&gt;
&lt;img src="https://farmer3-c.github.io/img/in-post/pocc3.png" alt="图"&gt;
&lt;br&gt;
&lt;em&gt;本例&lt;/em&gt;
&lt;/div&gt;
&lt;p&gt;任何一个 SRAM，都有三组信号线与外部打交道：
①地址线，本例中有 6 条，即 $A_0、A_1、 A_2、 A_3、 A_4、 A_5$，它指定了存储器的容量是 $2^6$=64 个存储单元。
②数据线，本例中有4 条，即 $I/O_0、 I/O_1、 I/O_2 、 I/O_3$，说明存储器的字长是 4 位，因此存储位元的总数是 64×4=256。
③控制线， 本例中 $R/\overline{W}$ 控制线， 它指定了对存储器进行读( $R/\overline{W}$ 高电平)， 还是进行写( $R/\overline{W}$低电平)。注意，读写操作不会同时发生。&lt;/p&gt;</description><content:encoded><![CDATA[<ul>
<li>
<p><a href="">存储系统概述</a></p>
<ul>
<li>
<p><a href="">存储系统的层次结构</a><br>
<img alt="alt text" loading="lazy" src="/img/in-post/pocc1.png"></p>
<ul>
<li>
<p>为了解决存储容量、存取速度和价格之间的矛盾，计算机中通常采用多级存储器体系结构，即使用高速缓冲存储器、主存储器和外存储器。CPU能直接访问的存储器称为<strong>内存储器</strong>，包括高速缓冲存储器和主存储器。CPU不能直接访问<strong>外存储器</strong>，外存储器的信息必须调入内存储器才能被CPU处理。</p>
</li>
<li>
<p>高速缓冲存储器－主存 层次：CPU的处理速度比主存的存取速度快。为弥补主存速度的不足，在主存和CPU之间增加一级<strong>高速缓冲存储器</strong>(<strong>Cache</strong>)。其特点是速度高而容量小。它所存放的是主存中部分内容的复制，是当前最有可能被CPU访问的信息。</p>
</li>
<li>
<p>从整体看，Cache－主存层次的存取速度接近于Cache的速度，而容量接近于主存的容量。Cache存储器全部由硬件调度，对程序员是透明的。</p>
</li>
</ul>
<blockquote>
<p>从整体看，主存－辅存层次具有接近于主存的速度和接近于辅存的容量。</p>
</blockquote>
</li>
<li>
<p><a href="">存储器的分类</a></p>
<ul>
<li>
<p>按存储介质分
• 半导体存储器：主要有MOS型存储器和双极型存储器两大类。
• 磁表面存储器：在金属或塑料基体上，涂覆一层磁性材料，用磁层存储信息，常见的有磁盘、磁带等。
• 光存储器：采用激光技术访问的存储器。</p>
</li>
<li>
<p>按存取方式分
• 随机存储器：任何存储单元的内容都能被<strong>随机存取</strong>，且存取时间和存储单元的物理位置无关。如半导体存储器。
• 顺序存储器：只能按某种<strong>顺序来存取</strong>，存取时间和存储单元的物理位置有关。如磁带存储器。</p>
<blockquote>
<p>磁盘存储器既不像随机存储器那样能随机地访问任一个存储单元，也不像顺序存储器那样完全按顺序存取，而是介于两者之间。存取信息时，第一步指向整个存储器中的某个小区域（磁盘上的磁道）；第二步在小区域内顺序检索，直至找到目的地后再进行读/写操作。其存取时间和信息的物理位置有一定关系。</p>
</blockquote>
</li>
<li>
<p>按存储器的读写功能分
• 只读存储器(ROM)：存储的内容固定不变，只能读出而不能写入。
• 随机读写存储器(RAM)：既能读出又能写入。</p>
</li>
<li>
<p>按信息的可保存性分<br>
• 易失性存储器：断电后信息即消失的存储器。
• 非易失性存储器：断电后仍能保存信息的存储器。</p>
</li>
<li>
<p>按在计算机系统中的作用分<br>
• 根据存储器在计算机系统中所起的作用，可分为主存储器、辅助存储器、高速缓冲存储器、控制存储器（用于存放微程序，由ROM构成）。</p>
</li>
</ul>
</li>
<li>
<p><a href="">存储器的编址和端模式</a></p>
</li>
<li>
<p><a href="">存储器的技术指标</a></p>
<ul>
<li>
<p>存储容量：存储器所包含的存储单元的总数称为存储容量。存储容量用字数或字节数表示。一个字节定义为8个二进制位，一个字包括2个或4个字节。</p>
</li>
<li>
<p>存取时间：从启动一次存储器操作到完成该操作所经历的时间。例如：读出时间是指从CPU向主存发出有效地址和读命令开始，直到将被选单元的内容读出为止所用的时间；写入时间是指从CPU向主存发出有效地址和写命令开始，直到信息写入被选中单元为止所用的时间。</p>
</li>
<li>
<p>存取周期：连续两次访问存储器操作之间所需要的最短时间。一般情况下，存取周期大于存取时间。这是因为对于任何一种存储器，在读写操作之后，总要有一段恢复内部状态的复原时间。</p>
</li>
<li>
<p>存储器带宽：又称数据传输率，指单位时间内存储器可读写的数据量，用位/秒或字节/秒度量。由存取周期和字长决定。</p>
</li>
<li>
<p>可靠性：用平均无故障时间来衡量。</p>
</li>
<li>
<p>其它参数：功耗、价格等。</p>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p><a href="">静态随机存取存储器</a><br>
目前广泛使用的半导体存储器是MOS型半导体存储器，可以分为静态MOS型存储器（Static RAM）和动态MOS型存储器（Dynamic RAM）</p>
  <div align="center">
  <img src="/img/in-post/pocc2.png" alt="六管SRAM存储元的电路图">
  <br>
  <em>六管SRAM存储元的电路图</em>
  </div>
<p>$T_3、T_4$相当于负载电阻，$T_1、T_2$构成双稳态触发器。若$T_1$截止，A为高电平，使$T_2$导通，B为低电平，而B的低电平又使$T_1$更加截止；反之，若B为高电平，则A为低电平。</p>
<blockquote>
<p>可见该电路有两个稳定状态，且A和B两点电位总是互反的。如果用A点高电平代表 “1”，A点低电平代表 “ 0”，该电路可存储一位二进制数。</p>
</blockquote>
<p>$T_5、T_6、T_7和T_8$为控制管。如果某存储元被选中，X、Y地址译码线均处于高电平，使$T_5～T_8$导通，输入输出电路I/O和$\overline{I/O}$分别与A点和B点相连，A点和B点的电平状态就能输出到I/O和$\overline{I/O}$上，完成<strong>读操作</strong>。</p>
<p>写操作时，如果要写入“1”，在I/O线上输入高电位，在$\overline{I/O}$线上输入低电位，开启$T_5～T_8$四个MOS管把高、低电位分别加在A、B点，使$T_1$管截止，使$T_2$管导通，将“1”写入存储元。如果要写入“0”，在I/O线上输入低电位，在$\overline{I/O}$线上输入高电位，打开$T_5～T_8$，把低、高电位分别加在A、B点，使$T_1$管导通，$T_2$管截止，将“0” 写入存储元。</p>
<ul>
<li><a href="">基本的静态存储元阵列</a></li>
</ul>
  <div align="center">
  <img src="/img/in-post/pocc3.png" alt="图">
  <br>
  <em>本例</em>
  </div>
<p>任何一个 SRAM，都有三组信号线与外部打交道：
①地址线，本例中有 6 条，即 $A_0、A_1、 A_2、 A_3、 A_4、 A_5$，它指定了存储器的容量是 $2^6$=64 个存储单元。
②数据线，本例中有4 条，即 $I/O_0、 I/O_1、 I/O_2 、 I/O_3$，说明存储器的字长是 4 位，因此存储位元的总数是 64×4=256。
③控制线， 本例中 $R/\overline{W}$ 控制线， 它指定了对存储器进行读( $R/\overline{W}$ 高电平)， 还是进行写( $R/\overline{W}$低电平)。注意，读写操作不会同时发生。</p>
<ul>
<li>
<p><a href="">基本的SRAM逻辑结构</a></p>
<p>SRAM存储器由存储体、地址译码电路、读写电路和控制电路组成。
* 存储体： 存储体是存储单元的集合。
* 地址译码器：CPU要选择某一存储单元，就在地址总线上输出该单元的地址信号给地址译码器，译码器把二进制代码表示的地址转换成电平信号，选中要访问的存储单元。
* 片选与读写控制电路：读写控制线用来控制芯片是进行读操作还是写操作；片选线用来决定该芯片是否被选中。</p>
</li>
<li>
<p><a href="">SRAM读/写时序</a></p>
</li>
<li>
<p><a href="">存储器容量的扩充</a></p>
</li>
<li>
<p><a href="">存储器与CPU的连接</a></p>
  <div align="center">
  <img src="/img/in-post/pocc4.png" alt="图">
  <br>
  </div>
<p>存储容量: 半导体存储芯片所能存储的二进制信息位数(单位bit)</p>
<p>可寻址最大范围: $2^k  n$ (单位bit，1Byte=8bit)</p>
<p>RAM芯片通过地址线、数据线和控制线与外部连接。存储器同CPU的连接就是要完成地址线、数据线和控制线的连接。地址线是单向输入的，数据线是双向的，既可输入也可输出。单个芯片的存储容量往往不能满足要求，需要进行扩展。扩展的方法有：<strong>位扩展法、字扩展法、字位同时扩展法</strong>。</p>
</li>
</ul>
</li>
<li>
<p><a href="">动态随机存取存储器</a></p>
<ul>
<li><a href="">DRAM存储元的工作原理</a></li>
<li><a href="">DRAM芯片的逻辑结构</a></li>
<li><a href="">DRAM读/写时序</a></li>
<li><a href="">DRAM的刷新操作</a></li>
<li><a href="">突发传输模式</a></li>
<li><a href="">同步DRAM(SDRAM)</a></li>
<li><a href="">双倍数据率SDRAM(DDR SDRAM)</a></li>
<li><a href="">DRAM读/写校验</a></li>
<li><a href="">CDRAM</a></li>
</ul>
</li>
<li>
<p><a href="">只读存储器</a></p>
<ul>
<li><a href="">只读存储器概述</a></li>
<li><a href="">NOR闪存</a></li>
</ul>
</li>
<li>
<p><a href="">并行存储器</a></p>
<ul>
<li><a href="">双端口存储器</a></li>
<li><a href="">多模块交叉存储器</a></li>
</ul>
</li>
<li>
<p><a href="">cache存储器</a></p>
<ul>
<li><a href="">cache基本原理</a></li>
<li><a href="">主存与cache的地址映射</a></li>
<li><a href="">cache的替换策略</a></li>
<li><a href="">cache的写操作策略</a></li>
<li><a href="">Pentium 4的cache组织</a></li>
<li><a href="">使用多级cache减少缺失损失</a></li>
</ul>
</li>
<li>
<p><a href="">虚拟存储器</a></p>
<ul>
<li><a href="">虚拟存储器的基本概念</a></li>
<li><a href="">页式虚拟存储器</a></li>
<li><a href="">段式虚拟存储器和段页式虚拟存储器</a></li>
<li><a href="">虚存的替换算法</a></li>
<li><a href="">存储管理部件</a></li>
</ul>
</li>
<li>
<p><a href="">奔腾系列机的虚存组织</a></p>
<ul>
<li><a href="">存储器模型</a></li>
<li><a href="">虚地址模式</a></li>
<li><a href="">分页模式下的地址转换</a></li>
</ul>
</li>
</ul>
<hr>
<p><a href="/pdf/%E8%AE%A1%E7%BB%84%E7%AC%AC3%E7%AB%A0-1.pdf">计组第3章-1</a><br>
<a href="/pdf/%E8%AE%A1%E7%BB%84%E7%AC%AC3%E7%AB%A0-2.pdf">计组第3章-2</a><br>
<a href="/pdf/%E8%AE%A1%E7%BB%84%E7%AC%AC3%E7%AB%A0-3.pdf">计组第3章-3</a></p>
]]></content:encoded></item><item><title>运算方法和运算器</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/arithmetic/</link><pubDate>Wed, 03 Sep 2025 18:16:43 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/arithmetic/</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E6%95%B0%E6%8D%AE%E4%B8%8E%E6%96%87%E5%AD%97%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95"&gt;数据与文字的表示方法&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"&gt;数据格式&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%95%B0%E7%9A%84%E6%9C%BA%E5%99%A8%E7%A0%81%E8%A1%A8%E7%A4%BA"&gt;数的机器码表示&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%AD%97%E7%AC%A6%E4%B8%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95"&gt;字符与字符串的表示方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%B1%89%E5%AD%97%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95"&gt;汉字的表示方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%A0%A1%E9%AA%8C%E7%A0%81"&gt;校验码&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%AE%9A%E7%82%B9%E5%8A%A0%E6%B3%95%E5%87%8F%E6%B3%95%E8%BF%90%E7%AE%97"&gt;定点加法、减法运算&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E8%A1%A5%E7%A0%81%E5%8A%A0%E6%B3%95"&gt;补码加法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%A1%A5%E7%A0%81%E5%87%8F%E6%B3%95"&gt;补码减法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%BA%A2%E5%87%BA%E6%A6%82%E5%BF%B5%E4%B8%8E%E6%A3%80%E6%B5%8B%E6%96%B9%E6%B3%95"&gt;溢出概念与检测方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%9F%BA%E6%9C%AC%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%8A%A0%E6%B3%95%E5%87%8F%E6%B3%95%E5%99%A8"&gt;基本的二进制加法/减法器&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%AE%9A%E7%82%B9%E9%99%A4%E6%B3%95%E8%BF%90%E7%AE%97"&gt;定点除法运算&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E5%8E%9F%E7%A0%81%E9%99%A4%E6%B3%95%E7%AE%97%E6%B3%95%E5%8E%9F%E7%90%86"&gt;原码除法算法原理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%B9%B6%E8%A1%8C%E9%99%A4%E6%B3%95%E5%99%A8"&gt;并行除法器&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%AE%9A%E7%82%B9%E8%BF%90%E7%AE%97%E5%99%A8%E7%9A%84%E7%BB%84%E6%88%90"&gt;定点运算器的组成&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97"&gt;逻辑运算&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%A4%9A%E5%8A%9F%E8%83%BD%E7%AE%97%E6%9C%AF%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E5%8D%95%E5%85%83"&gt;多功能算术/逻辑运算单元&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%86%85%E9%83%A8%E6%80%BB%E7%BA%BF"&gt;内部总线&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%AE%9A%E7%82%B9%E8%BF%90%E7%AE%97%E5%99%A8%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84"&gt;定点运算器的基本结构&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E6%96%B9%E6%B3%95%E5%92%8C%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E5%99%A8"&gt;浮点运算方法和浮点运算器&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E6%B5%AE%E7%82%B9%E5%8A%A0%E6%B3%95%E5%87%8F%E6%B3%95%E8%BF%90%E7%AE%97"&gt;浮点加法、减法运算&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%B5%AE%E7%82%B9%E4%B9%98%E6%B3%95%E9%99%A4%E6%B3%95%E8%BF%90%E7%AE%97"&gt;浮点乘法、除法运算&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E6%B5%81%E6%B0%B4%E7%BA%BF"&gt;浮点运算流水线&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="数据与文字的表示方法"&gt;数据与文字的表示方法&lt;/h2&gt;
&lt;h4 id="数据格式"&gt;数据格式&lt;/h4&gt;
&lt;p&gt;计算机中的数据分为数值数据和非数值数据（字符、汉字、图像、声音等）。数值数据在计算机内部采用二进制编码表示，根据小数点位置是否固定，分为定点表示法和浮点表示法。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定点表示法&lt;/strong&gt;：小数点位置固定不变，分为定点整数（纯整数）和定点小数（纯小数）。定点数通常用补码或原码表示。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;浮点表示法&lt;/strong&gt;：形如 N = M × R^E，其中M为尾数（定点小数），E为阶码（整数），R为基数（通常为2）。IEEE 754标准定义了单精度（32位）、双精度（64位）等浮点数格式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="数的机器码表示"&gt;数的机器码表示&lt;/h4&gt;
&lt;p&gt;计算机中为了简化运算电路，通常使用以下机器码表示有符号数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;原码&lt;/strong&gt;：符号位（0正1负）加绝对值。简单但不便于加减运算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反码&lt;/strong&gt;：正数同原码，负数符号位不变，其余位取反。主要用于中间计算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;补码&lt;/strong&gt;：正数同原码，负数反码加1。补码可将减法转化为加法，是现代计算机最常用的有符号整数编码。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;移码&lt;/strong&gt;：在补码基础上加上偏置常数（通常2^(n-1)），用于浮点数的阶码表示。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="字符与字符串的表示方法"&gt;字符与字符串的表示方法&lt;/h4&gt;
&lt;p&gt;字符编码采用标准编码方案，如ASCII（美国信息交换标准代码）使用7位或8位二进制表示128个基本字符（英文大小写字母、数字、标点符号、控制字符）。扩展ASCII（ISO-8859）支持西欧语言。Unicode（如UTF-8、UTF-16）统一表示全世界所有字符，支持多语言混排。字符串在内存中通常以连续字节存储，以空字符（&amp;rsquo;\0&amp;rsquo;）或长度字段作为结束标志。&lt;/p&gt;
&lt;h4 id="汉字的表示方法"&gt;汉字的表示方法&lt;/h4&gt;
&lt;p&gt;汉字编码分为输入码（拼音、五笔等）、机内码（存储编码，如GB2312、GB18030、BIG5、Unicode中的汉字区）、字形码（点阵或矢量字体）。国家标准GB2312包含6763个常用汉字，GB18030兼容GB2312并扩展至7万余汉字。在Unicode中，汉字位于CJK统一表意文字区（U+4E00至U+9FFF）。&lt;/p&gt;
&lt;h4 id="校验码"&gt;校验码&lt;/h4&gt;
&lt;p&gt;校验码用于检测数据在传输或存储过程中的错误。常见类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;奇偶校验码&lt;/strong&gt;：增加一位奇偶位，使整个码字中1的个数为奇数（奇校验）或偶数（偶校验）。只能检测奇数个错误，不能纠错。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;海明校验码&lt;/strong&gt;：通过在数据位之间插入多个校验位，能够检测并纠正一位错误（或者检测两位错）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环冗余校验（CRC）&lt;/strong&gt;：将数据视为多项式，除以生成多项式得到余数作为校验码。CRC能检测突发错误，广泛用于网络通信和存储设备。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="定点加法减法运算"&gt;定点加法、减法运算&lt;/h2&gt;
&lt;h4 id="补码加法"&gt;补码加法&lt;/h4&gt;
&lt;p&gt;补码加法的公式：[X+Y]补 = [X]补 + [Y]补 (mod 2^n)。即直接将两个数的补码相加，若最高位产生进位则丢弃该进位（模2^n运算）。正负数均可直接相加，无需特殊处理。例如：X=5(0101)，Y=-3(1101)，和=2(0010)。&lt;/p&gt;
&lt;h4 id="补码减法"&gt;补码减法&lt;/h4&gt;
&lt;p&gt;补码减法转化为加法：[X-Y]补 = [X]补 + [-Y]补。其中[-Y]补可通过将[Y]补连同符号位一起取反后加1得到。例如：X=5(0101)，Y=3(0011)，则[-Y]补=1101，相加得0010（即2）。&lt;/p&gt;
&lt;h4 id="溢出概念与检测方法"&gt;溢出概念与检测方法&lt;/h4&gt;
&lt;p&gt;当运算结果超出机器数表示范围时发生溢出。对于补码加减法，溢出检测方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;双符号位法（变形补码）&lt;/strong&gt;：用两个符号位，如00为正，01为上溢，10为下溢，11为负。结果的两个符号位不同则表示溢出。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单符号位法&lt;/strong&gt;：比较操作数的符号和结果的符号。若两个正数相加得负数，或两个负数相加得正数，则溢出。进位检测法：最高有效位的进位与符号位的进位不同时溢出。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="基本的二进制加法减法器"&gt;基本的二进制加法/减法器&lt;/h4&gt;
&lt;p&gt;一位全加器（FA）是实现加法/减法的基础。它有三个输入：A、B、低位进位Cin；两个输出：和S、进位Cout。逻辑表达式：S = A ⊕ B ⊕ Cin；Cout = AB + (A⊕B)Cin。多个全加器串联构成行波进位加法器（RCA）。减法可通过将减数取反（按位取反后加1，即使用异或门控制）并设置初始进位为1来实现。为提高速度，可采用超前进位加法器（CLA）并行计算进位。&lt;/p&gt;</description><content:encoded><![CDATA[<ul>
<li><a href="#%E6%95%B0%E6%8D%AE%E4%B8%8E%E6%96%87%E5%AD%97%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95">数据与文字的表示方法</a>
<ul>
<li><a href="#%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F">数据格式</a></li>
<li><a href="#%E6%95%B0%E7%9A%84%E6%9C%BA%E5%99%A8%E7%A0%81%E8%A1%A8%E7%A4%BA">数的机器码表示</a></li>
<li><a href="#%E5%AD%97%E7%AC%A6%E4%B8%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95">字符与字符串的表示方法</a></li>
<li><a href="#%E6%B1%89%E5%AD%97%E7%9A%84%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95">汉字的表示方法</a></li>
<li><a href="#%E6%A0%A1%E9%AA%8C%E7%A0%81">校验码</a></li>
</ul>
</li>
<li><a href="#%E5%AE%9A%E7%82%B9%E5%8A%A0%E6%B3%95%E5%87%8F%E6%B3%95%E8%BF%90%E7%AE%97">定点加法、减法运算</a>
<ul>
<li><a href="#%E8%A1%A5%E7%A0%81%E5%8A%A0%E6%B3%95">补码加法</a></li>
<li><a href="#%E8%A1%A5%E7%A0%81%E5%87%8F%E6%B3%95">补码减法</a></li>
<li><a href="#%E6%BA%A2%E5%87%BA%E6%A6%82%E5%BF%B5%E4%B8%8E%E6%A3%80%E6%B5%8B%E6%96%B9%E6%B3%95">溢出概念与检测方法</a></li>
<li><a href="#%E5%9F%BA%E6%9C%AC%E7%9A%84%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%8A%A0%E6%B3%95%E5%87%8F%E6%B3%95%E5%99%A8">基本的二进制加法/减法器</a></li>
</ul>
</li>
<li><a href="#%E5%AE%9A%E7%82%B9%E9%99%A4%E6%B3%95%E8%BF%90%E7%AE%97">定点除法运算</a>
<ul>
<li><a href="#%E5%8E%9F%E7%A0%81%E9%99%A4%E6%B3%95%E7%AE%97%E6%B3%95%E5%8E%9F%E7%90%86">原码除法算法原理</a></li>
<li><a href="#%E5%B9%B6%E8%A1%8C%E9%99%A4%E6%B3%95%E5%99%A8">并行除法器</a></li>
</ul>
</li>
<li><a href="#%E5%AE%9A%E7%82%B9%E8%BF%90%E7%AE%97%E5%99%A8%E7%9A%84%E7%BB%84%E6%88%90">定点运算器的组成</a>
<ul>
<li><a href="#%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97">逻辑运算</a></li>
<li><a href="#%E5%A4%9A%E5%8A%9F%E8%83%BD%E7%AE%97%E6%9C%AF%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E5%8D%95%E5%85%83">多功能算术/逻辑运算单元</a></li>
<li><a href="#%E5%86%85%E9%83%A8%E6%80%BB%E7%BA%BF">内部总线</a></li>
<li><a href="#%E5%AE%9A%E7%82%B9%E8%BF%90%E7%AE%97%E5%99%A8%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84">定点运算器的基本结构</a></li>
</ul>
</li>
<li><a href="#%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E6%96%B9%E6%B3%95%E5%92%8C%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E5%99%A8">浮点运算方法和浮点运算器</a>
<ul>
<li><a href="#%E6%B5%AE%E7%82%B9%E5%8A%A0%E6%B3%95%E5%87%8F%E6%B3%95%E8%BF%90%E7%AE%97">浮点加法、减法运算</a></li>
<li><a href="#%E6%B5%AE%E7%82%B9%E4%B9%98%E6%B3%95%E9%99%A4%E6%B3%95%E8%BF%90%E7%AE%97">浮点乘法、除法运算</a></li>
<li><a href="#%E6%B5%AE%E7%82%B9%E8%BF%90%E7%AE%97%E6%B5%81%E6%B0%B4%E7%BA%BF">浮点运算流水线</a></li>
</ul>
</li>
</ul>
<h2 id="数据与文字的表示方法">数据与文字的表示方法</h2>
<h4 id="数据格式">数据格式</h4>
<p>计算机中的数据分为数值数据和非数值数据（字符、汉字、图像、声音等）。数值数据在计算机内部采用二进制编码表示，根据小数点位置是否固定，分为定点表示法和浮点表示法。</p>
<ul>
<li><strong>定点表示法</strong>：小数点位置固定不变，分为定点整数（纯整数）和定点小数（纯小数）。定点数通常用补码或原码表示。</li>
<li><strong>浮点表示法</strong>：形如 N = M × R^E，其中M为尾数（定点小数），E为阶码（整数），R为基数（通常为2）。IEEE 754标准定义了单精度（32位）、双精度（64位）等浮点数格式。</li>
</ul>
<h4 id="数的机器码表示">数的机器码表示</h4>
<p>计算机中为了简化运算电路，通常使用以下机器码表示有符号数：</p>
<ul>
<li><strong>原码</strong>：符号位（0正1负）加绝对值。简单但不便于加减运算。</li>
<li><strong>反码</strong>：正数同原码，负数符号位不变，其余位取反。主要用于中间计算。</li>
<li><strong>补码</strong>：正数同原码，负数反码加1。补码可将减法转化为加法，是现代计算机最常用的有符号整数编码。</li>
<li><strong>移码</strong>：在补码基础上加上偏置常数（通常2^(n-1)），用于浮点数的阶码表示。</li>
</ul>
<h4 id="字符与字符串的表示方法">字符与字符串的表示方法</h4>
<p>字符编码采用标准编码方案，如ASCII（美国信息交换标准代码）使用7位或8位二进制表示128个基本字符（英文大小写字母、数字、标点符号、控制字符）。扩展ASCII（ISO-8859）支持西欧语言。Unicode（如UTF-8、UTF-16）统一表示全世界所有字符，支持多语言混排。字符串在内存中通常以连续字节存储，以空字符（&rsquo;\0&rsquo;）或长度字段作为结束标志。</p>
<h4 id="汉字的表示方法">汉字的表示方法</h4>
<p>汉字编码分为输入码（拼音、五笔等）、机内码（存储编码，如GB2312、GB18030、BIG5、Unicode中的汉字区）、字形码（点阵或矢量字体）。国家标准GB2312包含6763个常用汉字，GB18030兼容GB2312并扩展至7万余汉字。在Unicode中，汉字位于CJK统一表意文字区（U+4E00至U+9FFF）。</p>
<h4 id="校验码">校验码</h4>
<p>校验码用于检测数据在传输或存储过程中的错误。常见类型：</p>
<ul>
<li><strong>奇偶校验码</strong>：增加一位奇偶位，使整个码字中1的个数为奇数（奇校验）或偶数（偶校验）。只能检测奇数个错误，不能纠错。</li>
<li><strong>海明校验码</strong>：通过在数据位之间插入多个校验位，能够检测并纠正一位错误（或者检测两位错）。</li>
<li><strong>循环冗余校验（CRC）</strong>：将数据视为多项式，除以生成多项式得到余数作为校验码。CRC能检测突发错误，广泛用于网络通信和存储设备。</li>
</ul>
<h2 id="定点加法减法运算">定点加法、减法运算</h2>
<h4 id="补码加法">补码加法</h4>
<p>补码加法的公式：[X+Y]补 = [X]补 + [Y]补 (mod 2^n)。即直接将两个数的补码相加，若最高位产生进位则丢弃该进位（模2^n运算）。正负数均可直接相加，无需特殊处理。例如：X=5(0101)，Y=-3(1101)，和=2(0010)。</p>
<h4 id="补码减法">补码减法</h4>
<p>补码减法转化为加法：[X-Y]补 = [X]补 + [-Y]补。其中[-Y]补可通过将[Y]补连同符号位一起取反后加1得到。例如：X=5(0101)，Y=3(0011)，则[-Y]补=1101，相加得0010（即2）。</p>
<h4 id="溢出概念与检测方法">溢出概念与检测方法</h4>
<p>当运算结果超出机器数表示范围时发生溢出。对于补码加减法，溢出检测方法：</p>
<ul>
<li><strong>双符号位法（变形补码）</strong>：用两个符号位，如00为正，01为上溢，10为下溢，11为负。结果的两个符号位不同则表示溢出。</li>
<li><strong>单符号位法</strong>：比较操作数的符号和结果的符号。若两个正数相加得负数，或两个负数相加得正数，则溢出。进位检测法：最高有效位的进位与符号位的进位不同时溢出。</li>
</ul>
<h4 id="基本的二进制加法减法器">基本的二进制加法/减法器</h4>
<p>一位全加器（FA）是实现加法/减法的基础。它有三个输入：A、B、低位进位Cin；两个输出：和S、进位Cout。逻辑表达式：S = A ⊕ B ⊕ Cin；Cout = AB + (A⊕B)Cin。多个全加器串联构成行波进位加法器（RCA）。减法可通过将减数取反（按位取反后加1，即使用异或门控制）并设置初始进位为1来实现。为提高速度，可采用超前进位加法器（CLA）并行计算进位。</p>
<h2 id="定点除法运算">定点除法运算</h2>
<h4 id="原码除法算法原理">原码除法算法原理</h4>
<p>原码除法：商符由被除数和除数的符号位异或得到；数值部分为绝对值相除。常见算法：</p>
<ul>
<li><strong>恢复余数法</strong>：每次用余数减除数，若结果为负则恢复余数并商0，左移再试；若为正则商1，左移继续。速度较慢。</li>
<li><strong>不恢复余数法（加减交替法）</strong>：根据余数符号决定下一步是加除数还是减除数，无需恢复，减少操作次数。计算机中常用此方法实现定点除法。</li>
</ul>
<h4 id="并行除法器">并行除法器</h4>
<p>为提高除法速度，可采用并行除法器，如基于数组结构或加法器网络的除法器。基本原理是类似于手工除法的逐次比较，但通过硬件并行加速。现代CPU中的除法器通常采用SRT算法（通过冗余位估计商数字），可以在每步产生多位商，并利用进位保留加法器（CSA）提高速度。</p>
<h2 id="定点运算器的组成">定点运算器的组成</h2>
<h4 id="逻辑运算">逻辑运算</h4>
<p>除了算术运算，运算器还需支持逻辑运算：与（AND）、或（OR）、非（NOT）、异或（XOR）、移位（算术左移/右移、逻辑左移/右移、循环移位）。逻辑运算按位进行，无进位/借位。移位操作常用于乘除法的快速实现和位处理。</p>
<h4 id="多功能算术逻辑运算单元">多功能算术/逻辑运算单元</h4>
<p>ALU（算术逻辑单元）是一个组合逻辑电路，能够根据控制信号选择执行多种运算（加、减、与、或、异或、移位等）。典型的ALU使用一个操作码（如4位）来选择运算类型。现代ALU还包含状态寄存器（标志位：Z（零）、C（进位）、V（溢出）、N（负））。例如，74181芯片是一个4位ALU，可执行16种算术和逻辑运算。</p>
<h4 id="内部总线">内部总线</h4>
<p>运算器内部使用总线连接ALU、寄存器组（累加器、通用寄存器、暂存器等）和内部数据通路。总线分为单总线、双总线、三总线结构：</p>
<ul>
<li><strong>单总线</strong>：所有操作数通过一条总线传输，结构简单但速度慢（需要分时传送两个操作数）。</li>
<li><strong>双总线</strong>：两个操作数可同时通过两条总线送入ALU，速度较快。</li>
<li><strong>三总线</strong>：两个操作数总线和一个结果总线，可并行输入输出，性能最高。</li>
</ul>
<h4 id="定点运算器的基本结构">定点运算器的基本结构</h4>
<p>定点运算器通常包括：</p>
<ul>
<li><strong>ALU</strong>：核心运算部件。</li>
<li><strong>通用寄存器组（Register File）</strong>：存放操作数和中间结果。</li>
<li><strong>状态寄存器（PSW/Flags）</strong>：存放ALU运算产生的状态标志。</li>
<li><strong>数据总线接口</strong>：与数据总线相连。</li>
<li><strong>控制逻辑</strong>：接收控制信号，协调数据通路。</li>
</ul>
<p>运算器可采用流水线结构进一步提高吞吐率。</p>
<h2 id="浮点运算方法和浮点运算器">浮点运算方法和浮点运算器</h2>
<h4 id="浮点加法减法运算">浮点加法、减法运算</h4>
<p>浮点加减法运算分为以下步骤：</p>
<ol>
<li><strong>对阶</strong>：使两数阶码相等。小阶向大阶看齐，尾数右移相应位数（右移时保留保护位和舍入位）。</li>
<li><strong>尾数加减</strong>：将对阶后的尾数按定点小数加减法运算。</li>
<li><strong>规格化</strong>：若结果尾数不符合规格化形式（如绝对值≥1或&lt;0.5），则进行左规（尾数左移，阶码减1）或右规（尾数右移，阶码加1）。</li>
<li><strong>舍入</strong>：采用就近舍入、朝0舍入等模式，处理右移时移出的位。</li>
<li><strong>溢出判断</strong>：阶码上溢或下溢时产生异常（如无穷大、非规格化数）。</li>
</ol>
<h4 id="浮点乘法除法运算">浮点乘法、除法运算</h4>
<ul>
<li><strong>浮点乘法</strong>：乘积的阶码 = 两数阶码相加（减去偏置常数），尾数相乘（定点乘法）。然后规格化、舍入、判溢出。</li>
<li><strong>浮点除法</strong>：商的阶码 = 被除数阶码 - 除数阶码（加上偏置常数），尾数相除。同样需要规格化等步骤。</li>
</ul>
<h4 id="浮点运算流水线">浮点运算流水线</h4>
<p>为了提高浮点运算吞吐率，现代处理器采用流水线浮点单元（FPU）。浮点流水线通常分为若干级：指令译码、操作数读取、执行（对阶、加减、规格化等流水多级）、写回结果。例如，Intel的FPU可同时处理多条浮点指令。流水线中存在资源冲突和写后读等冒险，需通过转发、停顿等机制解决。</p>
]]></content:encoded></item><item><title>计组概论</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/intro/</link><pubDate>Wed, 03 Sep 2025 18:16:17 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/intro/</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E5%88%86%E7%B1%BB"&gt;计算机的分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E5%8F%91%E5%B1%95%E7%AE%80%E5%8F%B2"&gt;计算机的发展简史&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E4%BA%94%E4%BB%A3%E5%8F%98%E5%8C%96"&gt;计算机的五代变化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%8D%8A%E5%AF%BC%E4%BD%93%E5%AD%98%E5%82%A8%E5%99%A8%E7%9A%84%E5%8F%91%E5%B1%95"&gt;半导体存储器的发展&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%BE%AE%E5%A4%84%E7%90%86%E5%99%A8%E7%9A%84%E5%8F%91%E5%B1%95"&gt;微处理器的发展&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87"&gt;计算机的性能指标&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E7%A1%AC%E4%BB%B6"&gt;计算机的硬件&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E7%A1%AC%E4%BB%B6%E7%BB%84%E6%88%90%E8%A6%81%E7%B4%A0"&gt;硬件组成要素&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%BF%90%E7%AE%97%E5%99%A8"&gt;运算器&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E5%AD%98%E5%82%A8%E5%99%A8"&gt;存储器&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E6%8E%A7%E5%88%B6%E5%99%A8"&gt;控制器&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E9%80%82%E9%85%8D%E5%99%A8%E4%B8%8E%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA%E8%AE%BE%E5%A4%87"&gt;适配器与输入/输出设备&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E8%BD%AF%E4%BB%B6"&gt;计算机的软件&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E8%BD%AF%E4%BB%B6%E7%9A%84%E7%BB%84%E6%88%90%E4%B8%8E%E5%88%86%E7%B1%BB"&gt;软件的组成与分类&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%BD%AF%E4%BB%B6%E7%9A%84%E5%8F%91%E5%B1%95%E6%BC%94%E5%8F%98"&gt;软件的发展演变&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84"&gt;计算机系统的层次结构&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#%E5%A4%9A%E7%BA%A7%E7%BB%84%E6%88%90%E7%9A%84%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F"&gt;多级组成的计算机系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#%E8%BD%AF%E4%BB%B6%E4%B8%8E%E7%A1%AC%E4%BB%B6%E7%9A%84%E9%80%BB%E8%BE%91%E7%AD%89%E4%BB%B7%E6%80%A7"&gt;软件与硬件的逻辑等价性&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="计算机的分类"&gt;计算机的分类&lt;/h2&gt;
&lt;p&gt;电子计算机从总体上来说分为两大类。一类是&lt;strong&gt;电子模拟计算机&lt;/strong&gt;，模拟计算机的特点是数值由连续量来表示，运算过程也是连续的。另一类是&lt;strong&gt;电子数字计算机&lt;/strong&gt;，数字计算机的主要特点是按位运算，并且不连续地跳动计算。&lt;/p&gt;
&lt;p&gt;此外，数字计算机还可根据规模和用途分为巨型机、大型机、小型机、微型机、工作站、嵌入式计算机等类别。巨型机用于科学计算和国家战略任务；微型机（个人计算机）普及最广；嵌入式系统则应用于智能设备、汽车电子等领域。&lt;/p&gt;
&lt;h2 id="计算机的发展简史"&gt;计算机的发展简史&lt;/h2&gt;
&lt;h4 id="计算机的五代变化"&gt;计算机的五代变化&lt;/h4&gt;
&lt;p&gt;世界上第一台电子数字计算机是1946年在美国宾夕法尼亚大学制成的ENIAC。这台机器用了18000多个电子管，占地170m²，重量达30吨，而运算速度只有5000次/秒。&lt;/p&gt;
&lt;p&gt;自从这台计算机问世70多年来，从使用器件的角度来说，计算机的发展大致经历了五代的变化。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一代为1946～1957年，电子管计算机。采用电子管作为逻辑元件，磁鼓或磁芯作为存储器，体积庞大、功耗高、可靠性低。主要用于科学计算。&lt;/li&gt;
&lt;li&gt;第二代为1958～1964年，晶体管计算机。晶体管代替电子管，体积缩小，功耗降低，速度提高。出现了高级编程语言（如FORTRAN、COBOL），开始应用于商业领域。&lt;/li&gt;
&lt;li&gt;第三代为1965～1971年，中小规模集成电路计算机。将多个晶体管集成在一块硅片上，使计算机进一步小型化，运算速度达到每秒数百万次。操作系统和分时系统开始普及。&lt;/li&gt;
&lt;li&gt;第四代为1972～1990年，大规模和超大规模集成电路计算机。一片芯片可集成数千至上万个元件。个人计算机（PC）诞生并迅速发展。1971年Intel 4004微处理器标志着微计算机时代的开始。&lt;/li&gt;
&lt;li&gt;第五代为1991年开始的巨大规模集成电路计算机。运算速度提高到每秒10亿次以上。由一片巨大规模集成电路实现的单片计算机（系统级芯片，SoC）开始出现。并行处理、多核技术、量子计算等新技术不断涌现。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;计算机从第三代起，与集成电路技术的发展密切相关。LSI（大规模集成电路）的采用，一块集成电路芯片上可以放置1000个元件，VLSI（超大规模集成电路）达到每个芯片1万个元件，现在的ULSI（甚大规模集成电路）芯片超过了100万个元件。1965年摩尔观察到芯片上的晶体管数量每年翻一番，1970年这种态势减慢成每18个月翻一番，这就是人们所称的&lt;strong&gt;摩尔定律&lt;/strong&gt;。该定律揭示了集成电路工艺的持续进步，但也面临物理极限的挑战。&lt;/p&gt;
&lt;h4 id="半导体存储器的发展"&gt;半导体存储器的发展&lt;/h4&gt;
&lt;p&gt;半导体存储器的发展经历了从磁芯存储器到半导体RAM和ROM的转变。20世纪60年代末，半导体存储器开始取代磁芯存储器，成为计算机的主要存储部件。随着集成电路技术的进步，存储容量不断增大，成本不断降低，速度也大幅提升。如今，DRAM（动态随机存取存储器）和SRAM（静态随机存取存储器）广泛应用于主存和高速缓存，闪存（Flash）则成为移动设备和固态硬盘的重要存储介质。近年来，3D NAND、MRAM、ReRAM等新型存储器不断涌现，进一步拓展了存储技术的边界。&lt;/p&gt;
&lt;h4 id="微处理器的发展"&gt;微处理器的发展&lt;/h4&gt;
&lt;p&gt;微处理器是将中央处理器的主要功能集成到一块芯片上的器件。1971年，英特尔公司推出了世界上第一块微处理器4004，4位字长，主频108kHz，开启了微处理器时代。随后，8位微处理器（Intel 8080、Zilog Z80）、16位（Intel 8086/8088、Motorola 68000）、32位（Intel 80386、ARM）、64位微处理器相继问世，性能不断提升，集成度从数千晶体管发展到数百亿晶体管。微处理器的出现极大地推动了个人计算机和嵌入式系统的发展。当前主流微处理器包括Intel Core系列、AMD Ryzen系列、ARM Cortex系列等，广泛应用于从智能手机到超级计算机的各类设备。&lt;/p&gt;
&lt;h4 id="计算机的性能指标"&gt;计算机的性能指标&lt;/h4&gt;
&lt;p&gt;衡量计算机性能的主要指标包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;主频（时钟频率）&lt;/strong&gt;：CPU的核心时钟速率，单位Hz。主频越高，单位时间内能完成的操作越多，但不同架构的CPU不能单纯比较主频。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;字长&lt;/strong&gt;：CPU一次能并行处理的二进制位数，通常为8、16、32、64位。字长影响数据精度和寻址范围。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运算速度&lt;/strong&gt;：通常用每秒百万条指令（MIPS）或每秒浮点运算次数（FLOPS）表示。现代计算机常用SPEC等基准测试程序综合评估。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存储容量&lt;/strong&gt;：主存（RAM）容量和辅存（硬盘/SSD）容量。容量越大，可运行的程序和数据越多。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输入输出速度&lt;/strong&gt;：I/O带宽和响应时间，影响系统的整体运行效率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;其他指标&lt;/strong&gt;：功耗、可靠性（MTBF）、可用性、可扩展性等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="计算机的硬件"&gt;计算机的硬件&lt;/h2&gt;
&lt;h4 id="硬件组成要素"&gt;硬件组成要素&lt;/h4&gt;
&lt;p&gt;计算机硬件主要包括运算器、存储器、控制器、输入设备和输出设备五大部分。它们共同协作，实现数据的输入、存储、运算、控制和输出功能。这些部件通过总线（数据总线、地址总线、控制总线）相互连接，组成完整的硬件系统。&lt;/p&gt;
&lt;h4 id="运算器"&gt;运算器&lt;/h4&gt;
&lt;p&gt;运算器负责对数据进行算术和逻辑运算，是计算机的“计算核心”。它通常包括算术逻辑单元（ALU）、累加器（ACC）、暂存器、状态寄存器（标志寄存器）等部件。ALU执行加、减、乘、除等算术运算和与、或、非、异或等逻辑运算。运算器的设计对计算机的性能至关重要。&lt;/p&gt;
&lt;h4 id="存储器"&gt;存储器&lt;/h4&gt;
&lt;p&gt;存储器用于存放程序和数据，分为主存（内存）和辅存（外存）。主存速度快但容量有限，通常由DRAM构成，直接与CPU交换信息；辅存容量大但速度较慢，如硬盘、固态硬盘、光盘等，用于长期保存信息。存储器系统采用层次结构（Cache-主存-辅存）来兼顾速度、容量和成本。&lt;/p&gt;
&lt;h4 id="控制器"&gt;控制器&lt;/h4&gt;
&lt;p&gt;控制器负责协调和控制计算机各部件的工作，保证程序的正确执行。它通过时序信号和控制信号实现对各部件的管理。控制器从存储器中逐条取出指令，分析指令（译码），然后发出相应的微操作命令序列，驱动运算器、存储器、I/O设备执行指令规定的操作。控制器分为微程序控制器和硬布线控制器两种主要类型。&lt;/p&gt;
&lt;h4 id="适配器与输入输出设备"&gt;适配器与输入输出设备&lt;/h4&gt;
&lt;p&gt;适配器（也称接口或控制器）用于连接主机与各种输入输出设备，如键盘、鼠标、显示器、打印机、磁盘驱动器等，实现数据的输入和输出。适配器负责信号转换、数据缓冲、协议转换和错误处理。常见的I/O接口标准有USB、HDMI、SATA、PCIe等。输入设备将外部信息转换为计算机可识别的电信号；输出设备则将计算机的处理结果转换为人们可感知的形式（如显示、打印、声音）。&lt;/p&gt;
&lt;h2 id="计算机的软件"&gt;计算机的软件&lt;/h2&gt;
&lt;h4 id="软件的组成与分类"&gt;软件的组成与分类&lt;/h4&gt;
&lt;p&gt;计算机软件分为系统软件和应用软件。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;系统软件&lt;/strong&gt;：包括操作系统（Windows、Linux、macOS等）、编译程序（GCC、LLVM等）、解释程序、数据库管理系统（MySQL、Oracle等）、汇编程序、链接程序等，负责管理硬件资源和为应用软件提供运行环境。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;应用软件&lt;/strong&gt;：用于完成特定的用户任务，如文字处理（Word）、图像编辑（Photoshop）、科学计算（MATLAB）、网页浏览（Chrome）、游戏、财务软件等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="软件的发展演变"&gt;软件的发展演变&lt;/h4&gt;
&lt;p&gt;软件从最初的机器语言（二进制代码）、汇编语言（符号化机器指令）发展到高级语言（FORTRAN、C、Java、Python等）和面向对象编程，极大地提高了开发效率和程序的可维护性。随着互联网和人工智能的发展，软件的功能和复杂性也在不断提升。软件开发方法也从结构化方法发展到面向对象、组件化、服务化、敏捷开发、DevOps等模式。开源软件的兴起深刻改变了软件产业格局。&lt;/p&gt;</description><content:encoded><![CDATA[<ul>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E5%88%86%E7%B1%BB">计算机的分类</a></li>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E5%8F%91%E5%B1%95%E7%AE%80%E5%8F%B2">计算机的发展简史</a>
<ul>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E4%BA%94%E4%BB%A3%E5%8F%98%E5%8C%96">计算机的五代变化</a></li>
<li><a href="#%E5%8D%8A%E5%AF%BC%E4%BD%93%E5%AD%98%E5%82%A8%E5%99%A8%E7%9A%84%E5%8F%91%E5%B1%95">半导体存储器的发展</a></li>
<li><a href="#%E5%BE%AE%E5%A4%84%E7%90%86%E5%99%A8%E7%9A%84%E5%8F%91%E5%B1%95">微处理器的发展</a></li>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E6%80%A7%E8%83%BD%E6%8C%87%E6%A0%87">计算机的性能指标</a></li>
</ul>
</li>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E7%A1%AC%E4%BB%B6">计算机的硬件</a>
<ul>
<li><a href="#%E7%A1%AC%E4%BB%B6%E7%BB%84%E6%88%90%E8%A6%81%E7%B4%A0">硬件组成要素</a></li>
<li><a href="#%E8%BF%90%E7%AE%97%E5%99%A8">运算器</a></li>
<li><a href="#%E5%AD%98%E5%82%A8%E5%99%A8">存储器</a></li>
<li><a href="#%E6%8E%A7%E5%88%B6%E5%99%A8">控制器</a></li>
<li><a href="#%E9%80%82%E9%85%8D%E5%99%A8%E4%B8%8E%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA%E8%AE%BE%E5%A4%87">适配器与输入/输出设备</a></li>
</ul>
</li>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%9A%84%E8%BD%AF%E4%BB%B6">计算机的软件</a>
<ul>
<li><a href="#%E8%BD%AF%E4%BB%B6%E7%9A%84%E7%BB%84%E6%88%90%E4%B8%8E%E5%88%86%E7%B1%BB">软件的组成与分类</a></li>
<li><a href="#%E8%BD%AF%E4%BB%B6%E7%9A%84%E5%8F%91%E5%B1%95%E6%BC%94%E5%8F%98">软件的发展演变</a></li>
</ul>
</li>
<li><a href="#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84">计算机系统的层次结构</a>
<ul>
<li><a href="#%E5%A4%9A%E7%BA%A7%E7%BB%84%E6%88%90%E7%9A%84%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F">多级组成的计算机系统</a></li>
<li><a href="#%E8%BD%AF%E4%BB%B6%E4%B8%8E%E7%A1%AC%E4%BB%B6%E7%9A%84%E9%80%BB%E8%BE%91%E7%AD%89%E4%BB%B7%E6%80%A7">软件与硬件的逻辑等价性</a></li>
</ul>
</li>
</ul>
<h2 id="计算机的分类">计算机的分类</h2>
<p>电子计算机从总体上来说分为两大类。一类是<strong>电子模拟计算机</strong>，模拟计算机的特点是数值由连续量来表示，运算过程也是连续的。另一类是<strong>电子数字计算机</strong>，数字计算机的主要特点是按位运算，并且不连续地跳动计算。</p>
<p>此外，数字计算机还可根据规模和用途分为巨型机、大型机、小型机、微型机、工作站、嵌入式计算机等类别。巨型机用于科学计算和国家战略任务；微型机（个人计算机）普及最广；嵌入式系统则应用于智能设备、汽车电子等领域。</p>
<h2 id="计算机的发展简史">计算机的发展简史</h2>
<h4 id="计算机的五代变化">计算机的五代变化</h4>
<p>世界上第一台电子数字计算机是1946年在美国宾夕法尼亚大学制成的ENIAC。这台机器用了18000多个电子管，占地170m²，重量达30吨，而运算速度只有5000次/秒。</p>
<p>自从这台计算机问世70多年来，从使用器件的角度来说，计算机的发展大致经历了五代的变化。</p>
<ul>
<li>第一代为1946～1957年，电子管计算机。采用电子管作为逻辑元件，磁鼓或磁芯作为存储器，体积庞大、功耗高、可靠性低。主要用于科学计算。</li>
<li>第二代为1958～1964年，晶体管计算机。晶体管代替电子管，体积缩小，功耗降低，速度提高。出现了高级编程语言（如FORTRAN、COBOL），开始应用于商业领域。</li>
<li>第三代为1965～1971年，中小规模集成电路计算机。将多个晶体管集成在一块硅片上，使计算机进一步小型化，运算速度达到每秒数百万次。操作系统和分时系统开始普及。</li>
<li>第四代为1972～1990年，大规模和超大规模集成电路计算机。一片芯片可集成数千至上万个元件。个人计算机（PC）诞生并迅速发展。1971年Intel 4004微处理器标志着微计算机时代的开始。</li>
<li>第五代为1991年开始的巨大规模集成电路计算机。运算速度提高到每秒10亿次以上。由一片巨大规模集成电路实现的单片计算机（系统级芯片，SoC）开始出现。并行处理、多核技术、量子计算等新技术不断涌现。</li>
</ul>
<p>计算机从第三代起，与集成电路技术的发展密切相关。LSI（大规模集成电路）的采用，一块集成电路芯片上可以放置1000个元件，VLSI（超大规模集成电路）达到每个芯片1万个元件，现在的ULSI（甚大规模集成电路）芯片超过了100万个元件。1965年摩尔观察到芯片上的晶体管数量每年翻一番，1970年这种态势减慢成每18个月翻一番，这就是人们所称的<strong>摩尔定律</strong>。该定律揭示了集成电路工艺的持续进步，但也面临物理极限的挑战。</p>
<h4 id="半导体存储器的发展">半导体存储器的发展</h4>
<p>半导体存储器的发展经历了从磁芯存储器到半导体RAM和ROM的转变。20世纪60年代末，半导体存储器开始取代磁芯存储器，成为计算机的主要存储部件。随着集成电路技术的进步，存储容量不断增大，成本不断降低，速度也大幅提升。如今，DRAM（动态随机存取存储器）和SRAM（静态随机存取存储器）广泛应用于主存和高速缓存，闪存（Flash）则成为移动设备和固态硬盘的重要存储介质。近年来，3D NAND、MRAM、ReRAM等新型存储器不断涌现，进一步拓展了存储技术的边界。</p>
<h4 id="微处理器的发展">微处理器的发展</h4>
<p>微处理器是将中央处理器的主要功能集成到一块芯片上的器件。1971年，英特尔公司推出了世界上第一块微处理器4004，4位字长，主频108kHz，开启了微处理器时代。随后，8位微处理器（Intel 8080、Zilog Z80）、16位（Intel 8086/8088、Motorola 68000）、32位（Intel 80386、ARM）、64位微处理器相继问世，性能不断提升，集成度从数千晶体管发展到数百亿晶体管。微处理器的出现极大地推动了个人计算机和嵌入式系统的发展。当前主流微处理器包括Intel Core系列、AMD Ryzen系列、ARM Cortex系列等，广泛应用于从智能手机到超级计算机的各类设备。</p>
<h4 id="计算机的性能指标">计算机的性能指标</h4>
<p>衡量计算机性能的主要指标包括：</p>
<ul>
<li><strong>主频（时钟频率）</strong>：CPU的核心时钟速率，单位Hz。主频越高，单位时间内能完成的操作越多，但不同架构的CPU不能单纯比较主频。</li>
<li><strong>字长</strong>：CPU一次能并行处理的二进制位数，通常为8、16、32、64位。字长影响数据精度和寻址范围。</li>
<li><strong>运算速度</strong>：通常用每秒百万条指令（MIPS）或每秒浮点运算次数（FLOPS）表示。现代计算机常用SPEC等基准测试程序综合评估。</li>
<li><strong>存储容量</strong>：主存（RAM）容量和辅存（硬盘/SSD）容量。容量越大，可运行的程序和数据越多。</li>
<li><strong>输入输出速度</strong>：I/O带宽和响应时间，影响系统的整体运行效率。</li>
<li><strong>其他指标</strong>：功耗、可靠性（MTBF）、可用性、可扩展性等。</li>
</ul>
<h2 id="计算机的硬件">计算机的硬件</h2>
<h4 id="硬件组成要素">硬件组成要素</h4>
<p>计算机硬件主要包括运算器、存储器、控制器、输入设备和输出设备五大部分。它们共同协作，实现数据的输入、存储、运算、控制和输出功能。这些部件通过总线（数据总线、地址总线、控制总线）相互连接，组成完整的硬件系统。</p>
<h4 id="运算器">运算器</h4>
<p>运算器负责对数据进行算术和逻辑运算，是计算机的“计算核心”。它通常包括算术逻辑单元（ALU）、累加器（ACC）、暂存器、状态寄存器（标志寄存器）等部件。ALU执行加、减、乘、除等算术运算和与、或、非、异或等逻辑运算。运算器的设计对计算机的性能至关重要。</p>
<h4 id="存储器">存储器</h4>
<p>存储器用于存放程序和数据，分为主存（内存）和辅存（外存）。主存速度快但容量有限，通常由DRAM构成，直接与CPU交换信息；辅存容量大但速度较慢，如硬盘、固态硬盘、光盘等，用于长期保存信息。存储器系统采用层次结构（Cache-主存-辅存）来兼顾速度、容量和成本。</p>
<h4 id="控制器">控制器</h4>
<p>控制器负责协调和控制计算机各部件的工作，保证程序的正确执行。它通过时序信号和控制信号实现对各部件的管理。控制器从存储器中逐条取出指令，分析指令（译码），然后发出相应的微操作命令序列，驱动运算器、存储器、I/O设备执行指令规定的操作。控制器分为微程序控制器和硬布线控制器两种主要类型。</p>
<h4 id="适配器与输入输出设备">适配器与输入输出设备</h4>
<p>适配器（也称接口或控制器）用于连接主机与各种输入输出设备，如键盘、鼠标、显示器、打印机、磁盘驱动器等，实现数据的输入和输出。适配器负责信号转换、数据缓冲、协议转换和错误处理。常见的I/O接口标准有USB、HDMI、SATA、PCIe等。输入设备将外部信息转换为计算机可识别的电信号；输出设备则将计算机的处理结果转换为人们可感知的形式（如显示、打印、声音）。</p>
<h2 id="计算机的软件">计算机的软件</h2>
<h4 id="软件的组成与分类">软件的组成与分类</h4>
<p>计算机软件分为系统软件和应用软件。</p>
<ul>
<li><strong>系统软件</strong>：包括操作系统（Windows、Linux、macOS等）、编译程序（GCC、LLVM等）、解释程序、数据库管理系统（MySQL、Oracle等）、汇编程序、链接程序等，负责管理硬件资源和为应用软件提供运行环境。</li>
<li><strong>应用软件</strong>：用于完成特定的用户任务，如文字处理（Word）、图像编辑（Photoshop）、科学计算（MATLAB）、网页浏览（Chrome）、游戏、财务软件等。</li>
</ul>
<h4 id="软件的发展演变">软件的发展演变</h4>
<p>软件从最初的机器语言（二进制代码）、汇编语言（符号化机器指令）发展到高级语言（FORTRAN、C、Java、Python等）和面向对象编程，极大地提高了开发效率和程序的可维护性。随着互联网和人工智能的发展，软件的功能和复杂性也在不断提升。软件开发方法也从结构化方法发展到面向对象、组件化、服务化、敏捷开发、DevOps等模式。开源软件的兴起深刻改变了软件产业格局。</p>
<h2 id="计算机系统的层次结构">计算机系统的层次结构</h2>
<h4 id="多级组成的计算机系统">多级组成的计算机系统</h4>
<p>现代计算机系统采用多级层次结构，从上到下依次为：</p>
<ul>
<li><strong>应用层</strong>：运行各种应用程序，与用户直接交互。</li>
<li><strong>高级语言层</strong>：由编译程序将高级语言翻译为汇编或机器语言。</li>
<li><strong>汇编语言层</strong>：使用助记符表示机器指令，通过汇编程序转换为机器码。</li>
<li><strong>操作系统层</strong>：提供系统调用接口，管理硬件资源和进程调度。</li>
<li><strong>机器语言层（指令集架构层）</strong>：指令系统定义计算机的软硬件接口。</li>
<li><strong>微程序层/硬件逻辑层</strong>：由微程序或硬布线实现指令解释。</li>
</ul>
<p>每一层都为上一层提供服务和接口，实现复杂功能的分层管理。层次化设计降低了系统复杂度，便于软硬件的分工和独立演进。</p>
<h4 id="软件与硬件的逻辑等价性">软件与硬件的逻辑等价性</h4>
<p>通过软件和硬件的协同设计，许多硬件功能可以用软件实现，反之亦然。这种逻辑等价性为计算机系统的灵活性和可扩展性提供了保障。例如，浮点运算可以软件模拟（慢）或硬件实现（快）；指令集可以通过微程序（可重写）或硬布线（固定）实现。软件和硬件的权衡本质上是速度、成本、灵活性的权衡。现代计算机采用固件（如BIOS/UEFI）作为软硬件之间的中间层。</p>
<p><a href="/pdf/%E8%AE%A1%E7%BB%84%E7%AC%AC1%E7%AB%A0.pdf">1</a></p>
]]></content:encoded></item><item><title>计算机组成原理</title><link>https://farmer3-c.github.io/posts/principles-of-computer-composition/post-2025-09-03/</link><pubDate>Wed, 03 Sep 2025 18:12:14 +0800</pubDate><guid>https://farmer3-c.github.io/posts/principles-of-computer-composition/post-2025-09-03/</guid><description>Principles of computer composition</description><content:encoded><![CDATA[<h1 id="计算机组成原理">计算机组成原理</h1>
<ul>
<li>
<p><a href="/2025/09/03/1/">概论</a></p>
</li>
<li>
<p><a href="/2025/09/03/2/">运算方法和运算器</a></p>
</li>
<li>
<p><a href="/2025/09/03/3/">存储系统</a></p>
</li>
<li>
<p><a href="/2025/09/03/4/">指令系统</a></p>
</li>
<li>
<p><a href="/2025/09/03/5/">中央处理器</a></p>
</li>
<li>
<p><a href="/2025/09/03/6/">总线系统</a></p>
</li>
</ul>
<h1 id="参考">参考</h1>
<hr>
<ul>
<li>白中英，戴志涛.计算机组成原理 第6版</li>
</ul>
]]></content:encoded></item><item><title>应用层</title><link>https://farmer3-c.github.io/posts/computer-networks/application-layer/</link><pubDate>Wed, 27 Aug 2025 19:48:37 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/application-layer/</guid><description>&lt;p&gt;应用层是参考模型的最上层，也是距离用户最近的一层，为各式各样的应用定义了通信规则和协同方式，满足不同的应用需求。围绕这个主题，本章主要探讨了以下内容。&lt;/p&gt;
&lt;h3 id="1应用进程通信方式与套接字编程"&gt;（1）应用进程通信方式与套接字编程&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;客户/服务器模型（C/S）&lt;/strong&gt;：服务器长期运行，被动等待请求；客户主动发起请求，完成服务后断开。优点是集中管理，缺点是服务器可能成为瓶颈。现代 Web、FTP、电子邮件均采用此模型。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;套接字（Socket）&lt;/strong&gt;：应用层与传输层的编程接口。原语包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;socket()&lt;/code&gt;：创建套接字。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bind()&lt;/code&gt;：绑定本地地址和端口（服务器用）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;listen()&lt;/code&gt;（TCP）：进入被动监听状态。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;accept()&lt;/code&gt;（TCP）：接受连接请求。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect()&lt;/code&gt;（TCP）：主动连接服务器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;send()/recv()&lt;/code&gt; 或 &lt;code&gt;write()/read()&lt;/code&gt;：数据传输。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;close()&lt;/code&gt;：关闭连接。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;基于 TCP 的套接字流程：服务器创建→绑定→监听→接受；客户端创建→连接→通信；可靠有序字节流。
基于 UDP 的套接字流程：无需连接，直接使用 &lt;code&gt;sendto()&lt;/code&gt;/&lt;code&gt;recvfrom()&lt;/code&gt;，发送和接收数据报。&lt;/p&gt;
&lt;h3 id="2域名系统dns"&gt;（2）域名系统（DNS）&lt;/h3&gt;
&lt;p&gt;DNS 负责将主机名（如 &lt;a href="https://www.example.com"&gt;www.example.com&lt;/a&gt;）解析为 IP 地址。域名空间为层次树结构，根域为 &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;（点），顶层域（TLD）包括通用域（.com, .org）和国家域（.cn, .uk）等。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;域名服务器&lt;/strong&gt;按层次分工：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;根域名服务器&lt;/strong&gt;：全球 13 组（逻辑上），不直接解析，只指引到 TLD 服务器。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;顶级域名服务器&lt;/strong&gt;：负责特定 TLD 下的域名。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权威域名服务器&lt;/strong&gt;：负责特定域（如 example.com）的所有记录。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;本地域名服务器&lt;/strong&gt;：ISP 或企业网络提供，缓存解析结果，代表用户发起查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解析算法&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;递归查询&lt;/strong&gt;：本地域名服务器代为请求其他服务器，将最终结果返回用户。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;迭代查询&lt;/strong&gt;：本地域名服务器依次询问各服务器（根→TLD→权威），每个服务器返回下一级地址。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;DNS 缓存&lt;/strong&gt;：各层服务器缓存解析结果，降低延迟，但必须设置 TTL 以确保更新。&lt;/p&gt;
&lt;h3 id="3典型应用层协议"&gt;（3）典型应用层协议&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;文件传输（FTP）&lt;/strong&gt;：使用两个 TCP 连接：控制连接（端口 21，发送命令）和数据连接（端口 20，传输文件）。支持主动模式（服务器主动连接客户端）和被动模式（客户端连接服务器协商的端口）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;远程登录 TELNET/SSH&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TELNET&lt;/strong&gt;（端口 23）：明文传输，不安全。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SSH&lt;/strong&gt;（端口 22）：加密认证，支持远程 shell、文件传输（SFTP）、端口转发。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;电子邮件协议&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SMTP（简单邮件传输协议）&lt;/strong&gt;（端口 25）：用于邮件客户端到服务器、服务器到服务器之间的邮件发送。仅支持 ASCII 文本，使用 MIME 支持多媒体。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;POP3（邮局协议第3版）&lt;/strong&gt;（端口 110）：下载邮件到本地，通常删除服务器上的邮件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IMAP（互联网消息访问协议）&lt;/strong&gt;（端口 143）：邮件保留在服务器上，支持远程文件夹管理、部分下载。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;MIME（多用途互联网邮件扩展）&lt;/strong&gt;：在邮件中传输非 ASCII 内容（图片、音频、附件），通过定义新的内容类型（Content-Type）和编码方式（Base64、QP）。&lt;/p&gt;</description><content:encoded><![CDATA[<p>应用层是参考模型的最上层，也是距离用户最近的一层，为各式各样的应用定义了通信规则和协同方式，满足不同的应用需求。围绕这个主题，本章主要探讨了以下内容。</p>
<h3 id="1应用进程通信方式与套接字编程">（1）应用进程通信方式与套接字编程</h3>
<p><strong>客户/服务器模型（C/S）</strong>：服务器长期运行，被动等待请求；客户主动发起请求，完成服务后断开。优点是集中管理，缺点是服务器可能成为瓶颈。现代 Web、FTP、电子邮件均采用此模型。</p>
<p><strong>套接字（Socket）</strong>：应用层与传输层的编程接口。原语包括：</p>
<ul>
<li><code>socket()</code>：创建套接字。</li>
<li><code>bind()</code>：绑定本地地址和端口（服务器用）。</li>
<li><code>listen()</code>（TCP）：进入被动监听状态。</li>
<li><code>accept()</code>（TCP）：接受连接请求。</li>
<li><code>connect()</code>（TCP）：主动连接服务器。</li>
<li><code>send()/recv()</code> 或 <code>write()/read()</code>：数据传输。</li>
<li><code>close()</code>：关闭连接。</li>
</ul>
<p>基于 TCP 的套接字流程：服务器创建→绑定→监听→接受；客户端创建→连接→通信；可靠有序字节流。
基于 UDP 的套接字流程：无需连接，直接使用 <code>sendto()</code>/<code>recvfrom()</code>，发送和接收数据报。</p>
<h3 id="2域名系统dns">（2）域名系统（DNS）</h3>
<p>DNS 负责将主机名（如 <a href="https://www.example.com">www.example.com</a>）解析为 IP 地址。域名空间为层次树结构，根域为 <code>&quot;&quot;</code>（点），顶层域（TLD）包括通用域（.com, .org）和国家域（.cn, .uk）等。</p>
<p><strong>域名服务器</strong>按层次分工：</p>
<ul>
<li><strong>根域名服务器</strong>：全球 13 组（逻辑上），不直接解析，只指引到 TLD 服务器。</li>
<li><strong>顶级域名服务器</strong>：负责特定 TLD 下的域名。</li>
<li><strong>权威域名服务器</strong>：负责特定域（如 example.com）的所有记录。</li>
<li><strong>本地域名服务器</strong>：ISP 或企业网络提供，缓存解析结果，代表用户发起查询。</li>
</ul>
<p><strong>解析算法</strong>：</p>
<ul>
<li><strong>递归查询</strong>：本地域名服务器代为请求其他服务器，将最终结果返回用户。</li>
<li><strong>迭代查询</strong>：本地域名服务器依次询问各服务器（根→TLD→权威），每个服务器返回下一级地址。</li>
</ul>
<p><strong>DNS 缓存</strong>：各层服务器缓存解析结果，降低延迟，但必须设置 TTL 以确保更新。</p>
<h3 id="3典型应用层协议">（3）典型应用层协议</h3>
<p><strong>文件传输（FTP）</strong>：使用两个 TCP 连接：控制连接（端口 21，发送命令）和数据连接（端口 20，传输文件）。支持主动模式（服务器主动连接客户端）和被动模式（客户端连接服务器协商的端口）。</p>
<p><strong>远程登录 TELNET/SSH</strong>：</p>
<ul>
<li><strong>TELNET</strong>（端口 23）：明文传输，不安全。</li>
<li><strong>SSH</strong>（端口 22）：加密认证，支持远程 shell、文件传输（SFTP）、端口转发。</li>
</ul>
<p><strong>电子邮件协议</strong>：</p>
<ul>
<li><strong>SMTP（简单邮件传输协议）</strong>（端口 25）：用于邮件客户端到服务器、服务器到服务器之间的邮件发送。仅支持 ASCII 文本，使用 MIME 支持多媒体。</li>
<li><strong>POP3（邮局协议第3版）</strong>（端口 110）：下载邮件到本地，通常删除服务器上的邮件。</li>
<li><strong>IMAP（互联网消息访问协议）</strong>（端口 143）：邮件保留在服务器上，支持远程文件夹管理、部分下载。</li>
</ul>
<p><strong>MIME（多用途互联网邮件扩展）</strong>：在邮件中传输非 ASCII 内容（图片、音频、附件），通过定义新的内容类型（Content-Type）和编码方式（Base64、QP）。</p>
<h3 id="4万维网与-http">（4）万维网与 HTTP</h3>
<p>万维网（WWW）是基于客户/服务器的分布式信息系统，通过超链接关联资源（网页、图片、视频）。</p>
<p><strong>静态 Web vs 动态 Web</strong>：</p>
<ul>
<li><strong>静态页面</strong>：HTML 文件存储在服务器，内容固定，适用于信息展示。</li>
<li><strong>动态页面</strong>：服务器端脚本（PHP、ASP、Node.js）根据请求参数动态生成 HTML，或由客户端 JavaScript 操作 DOM 实现动态效果。</li>
</ul>
<p><strong>HTTP（超文本传输协议）</strong>：</p>
<ul>
<li>版本演变：HTTP/0.9（仅 GET）、HTTP/1.0（支持头部、状态码）、HTTP/1.1（持久连接、管道化）、HTTP/2（多路复用、服务器推送）、HTTP/3（基于 QUIC）。</li>
<li>方法：GET、POST、PUT、DELETE、HEAD、OPTIONS。</li>
<li>状态码：1xx（信息）、2xx（成功）、3xx（重定向）、4xx（客户端错误）、5xx（服务器错误）。</li>
</ul>
<p><strong>代理服务器与 Web 缓存</strong>：</p>
<ul>
<li><strong>代理服务器</strong>：位于客户端和服务器之间，可转发请求、过滤内容、缓存响应、匿名访问。</li>
<li><strong>Web 缓存</strong>：将最近访问的页面副本存储靠近用户的位置（浏览器缓存、ISP 缓存、反向代理），减少延迟和带宽消耗。缓存一致性通过 <code>Cache-Control</code> 和 <code>ETag</code> 控制。</li>
</ul>
<p><strong>Web 安全</strong>：</p>
<ul>
<li><strong>加密通信</strong>：HTTPS = HTTP + TLS（传输层安全），加密数据防止窃听。</li>
<li><strong>验证对方身份</strong>：服务器证书（X.509），由 CA（证书颁发机构）签名。</li>
<li><strong>数据完整性</strong>：TLS 的 MAC 保证数据在传输中未被篡改。</li>
</ul>
<h3 id="5多媒体应用与内容分发网络">（5）多媒体应用与内容分发网络</h3>
<p>因特网的三种音频/视频服务：</p>
<ul>
<li><strong>流式存储音频/视频</strong>：用户点播预先录制的文件（如 Netflix、YouTube）。支持暂停、快进。</li>
<li><strong>流式直播音频/视频</strong>：实时采集并广播（如直播、网络电台）。</li>
<li><strong>交互式音频/视频</strong>：实时双向通信（如 Zoom、Skype），对延迟敏感。</li>
</ul>
<p>发布海量音频/视频数据面临挑战：服务器带宽、延迟、跨运营商传输质量。<strong>内容分发网络（CDN）</strong> 解决此问题：在全球部署边缘节点，将内容缓存在靠近用户的位置。用户被 DNS 重定向到最近的 CDN 节点。CDN 降低了源服务器负载，提高了用户体验。</p>
<h3 id="6p2p-应用与分布式散列表">（6）P2P 应用与分布式散列表</h3>
<p><strong>P2P 体系结构</strong>：没有中心服务器，每个节点（对等方）既是客户端又是服务器（称为“对等方”）。通过直接交换共享文件、带宽、存储。</p>
<p><strong>工作原理</strong>：例如 BitTorrent，将文件分为很多小块（piece）。节点从 tracker 或 DHT 获取其他对等方地址，并行下载不同块，同时上传自己已拥有的块（“人人为我，我为人人”）。稀有优先、阻塞/乐观疏通等机制提高效率。</p>
<p><strong>分布式散列表（DHT）</strong>：实现键值对的分布式存储，每个对等方负责一小部分键空间。典型算法：Chord（环形结构）、Kademlia（基于异或距离）。DHT 为 P2P 系统（如 BT 的 DHT 网络、以太坊）提供高效的资源定位服务。</p>
]]></content:encoded></item><item><title>网络层</title><link>https://farmer3-c.github.io/posts/computer-networks/network-layer/</link><pubDate>Wed, 27 Aug 2025 19:48:28 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/network-layer/</guid><description>&lt;p&gt;网络层是两个核心层之一，其功能是将分组从源主机一路送到目的主机。本章围绕这个功能，探讨网络层的技术和协议。&lt;/p&gt;
&lt;h2 id="网络层服务模型"&gt;网络层服务模型&lt;/h2&gt;
&lt;p&gt;网络层首先探讨了源和目的之间的通信网络的分类和提供的服务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;数据报网络&lt;/strong&gt;：提供无连接的服务，每个分组（数据报）独立路由，使用 IP 协议。特点：不维护连接状态，分组可能乱序到达。优点：鲁棒性强，适合动态路由。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;虚电路网络&lt;/strong&gt;：提供面向连接的服务，通信前需建立虚电路（如 X.25、ATM、MPLS）。特点：所有分组沿相同路径按序到达，可以预留资源（QoS）。缺点：需要维护连接状态，容错性差（节点故障导致所有连接中断）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;网络层上的协议分为被路由协议（routed protocol）和路由选择协议（routing protocol）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;被路由协议&lt;/strong&gt;：为分组的路由提供所需要的信息，例如 IP 协议提供地址和分组格式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;路由选择协议&lt;/strong&gt;：用于填充路由表，如 RIP、OSPF、BGP。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ipv4-地址与子网划分"&gt;IPv4 地址与子网划分&lt;/h2&gt;
&lt;h3 id="ipv4-地址表示和分类"&gt;IPv4 地址表示和分类&lt;/h3&gt;
&lt;p&gt;IPv4 地址长度为 32 位，通常用点分十进制表示（如 192.0.2.1）。最初分为五类（A、B、C、D、E）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A 类&lt;/strong&gt;：首位 0，网络号 8 位，主机号 24 位（范围 0.0.0.0 – 127.255.255.255），但 0 和 127 保留，实际 1–126。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B 类&lt;/strong&gt;：首位 10，网络号 16 位，主机号 16 位（128.0.0.0 – 191.255.255.255）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C 类&lt;/strong&gt;：首位 110，网络号 24 位，主机号 8 位（192.0.0.0 – 223.255.255.255）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;D 类&lt;/strong&gt;（组播）：1110 开头，地址 224.0.0.0 – 239.255.255.255。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E 类&lt;/strong&gt;（保留）：240.0.0.0 – 255.255.255.255。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="子网划分与-cidr"&gt;子网划分与 CIDR&lt;/h3&gt;
&lt;p&gt;IPv4 地址资源按块分配给 ISP，个人用户从 ISP 获取 IP 地址。为了方便管理和节约 IP 地址，使用&lt;strong&gt;子网掩码&lt;/strong&gt;（如 255.255.255.0）将主机号再分为子网号和子网内主机号。**可变长子网掩码（VLSM）**允许不同子网使用不同掩码长度，尽量不浪费地址。&lt;/p&gt;</description><content:encoded><![CDATA[<p>网络层是两个核心层之一，其功能是将分组从源主机一路送到目的主机。本章围绕这个功能，探讨网络层的技术和协议。</p>
<h2 id="网络层服务模型">网络层服务模型</h2>
<p>网络层首先探讨了源和目的之间的通信网络的分类和提供的服务：</p>
<ul>
<li><strong>数据报网络</strong>：提供无连接的服务，每个分组（数据报）独立路由，使用 IP 协议。特点：不维护连接状态，分组可能乱序到达。优点：鲁棒性强，适合动态路由。</li>
<li><strong>虚电路网络</strong>：提供面向连接的服务，通信前需建立虚电路（如 X.25、ATM、MPLS）。特点：所有分组沿相同路径按序到达，可以预留资源（QoS）。缺点：需要维护连接状态，容错性差（节点故障导致所有连接中断）。</li>
</ul>
<p>网络层上的协议分为被路由协议（routed protocol）和路由选择协议（routing protocol）：</p>
<ul>
<li><strong>被路由协议</strong>：为分组的路由提供所需要的信息，例如 IP 协议提供地址和分组格式。</li>
<li><strong>路由选择协议</strong>：用于填充路由表，如 RIP、OSPF、BGP。</li>
</ul>
<h2 id="ipv4-地址与子网划分">IPv4 地址与子网划分</h2>
<h3 id="ipv4-地址表示和分类">IPv4 地址表示和分类</h3>
<p>IPv4 地址长度为 32 位，通常用点分十进制表示（如 192.0.2.1）。最初分为五类（A、B、C、D、E）：</p>
<ul>
<li><strong>A 类</strong>：首位 0，网络号 8 位，主机号 24 位（范围 0.0.0.0 – 127.255.255.255），但 0 和 127 保留，实际 1–126。</li>
<li><strong>B 类</strong>：首位 10，网络号 16 位，主机号 16 位（128.0.0.0 – 191.255.255.255）。</li>
<li><strong>C 类</strong>：首位 110，网络号 24 位，主机号 8 位（192.0.0.0 – 223.255.255.255）。</li>
<li><strong>D 类</strong>（组播）：1110 开头，地址 224.0.0.0 – 239.255.255.255。</li>
<li><strong>E 类</strong>（保留）：240.0.0.0 – 255.255.255.255。</li>
</ul>
<h3 id="子网划分与-cidr">子网划分与 CIDR</h3>
<p>IPv4 地址资源按块分配给 ISP，个人用户从 ISP 获取 IP 地址。为了方便管理和节约 IP 地址，使用<strong>子网掩码</strong>（如 255.255.255.0）将主机号再分为子网号和子网内主机号。**可变长子网掩码（VLSM）**允许不同子网使用不同掩码长度，尽量不浪费地址。</p>
<p><strong>CIDR（无类别域间路由）</strong>：舍弃固定类别，使用“前缀/长度”表示任意长度的网络前缀（例如 192.168.0.0/16）。CIDR 支持路由聚合（超网），大幅缩小路由表规模。</p>
<h3 id="ip-寻址与-mac-寻址的协作">IP 寻址与 MAC 寻址的协作</h3>
<p>IP 寻址用于跨网络通信（逻辑地址），而 MAC 寻址（物理地址）用于同一子网内的链路层传输。在数据传输过程中：</p>
<ul>
<li>源主机将 IP 分组封装成帧，目的 MAC 地址为下一跳路由器（或目的主机）的 MAC。</li>
<li>路由器转发时，IP 分组（源和目的 IP 不变）被重新封装，MAC 地址每跳都更新。</li>
</ul>
<h3 id="地址解析协议arp">地址解析协议（ARP）</h3>
<p>在知晓通信对方的 IPv4 地址，但却不知其 MAC 地址时，启用地址解析协议（ARP）。工作原理：</p>
<ol>
<li>发送方广播 ARP 请求（“谁拥有 IP X？请回复 MAC”）。</li>
<li>目标主机单播 ARP 应答（包含自己的 MAC）。</li>
<li>发送方将映射存入 ARP 缓存（通常 20 分钟有效期）。</li>
</ol>
<p>当目的主机位于远程网络中时，必须使用<strong>默认网关</strong>（路由器），此时 ARP 请求的目标 IP 是网关 IP，从而获得网关 MAC。</p>
<h3 id="icmp互联网控制消息协议">ICMP（互联网控制消息协议）</h3>
<p>IP 分组传输仅是尽力而为，会遭遇丢包、拥塞等异常。ICMP 提供差错报告和网络诊断。</p>
<ul>
<li><strong>差错报告</strong>：目的不可达（3）、超时（11，如 TTL 为 0）、参数问题等。</li>
<li><strong>网络诊断</strong>：回声请求/应答（Type 8/0）用于 ping；时间戳请求用于测量延迟。</li>
<li>著名的 <strong>traceroute</strong> 使用 TTL 逐跳递增和 ICMP 超时报文来探测路径。</li>
</ul>
<h2 id="nat网络地址转换">NAT（网络地址转换）</h2>
<p>IPv4 总地址池已于 2011 年枯竭，而网民人数还在逐年上升。NAT 是地址不够用的快速修补方案。</p>
<ul>
<li><strong>私有地址</strong>：三个保留地址块（10.0.0.0/8、172.16.0.0/12、192.168.0.0/16），仅限内部网络使用，不接入公网路由。</li>
<li><strong>NAT 工作原理</strong>：内部主机访问公网时，NAT 路由器将源 IP（私有）和端口号转换为公网 IP 和一个新端口，并维护映射表。返回数据时逆向转换。</li>
<li><strong>NAT 局限性</strong>：破坏端到端透明性，外部无法主动连接内部主机（需手动配置端口转发或 UPnP）。</li>
</ul>
<h2 id="ipv6">IPv6</h2>
<p>IPv6 是大势所趋，其地址长度为 128 位，采用冒分十六进制表示（如 2001:0db8:85a3::8a2e:0370:7334）。</p>
<h3 id="ipv6-地址分类">IPv6 地址分类</h3>
<ul>
<li><strong>单播</strong>：唯一标识一个接口，包括全球单播（可聚合全球）、链路本地（FE80::/10）、唯一本地（FC00::/7）等。</li>
<li><strong>多播</strong>（FF00::/8）：代替 IPv4 广播。</li>
<li><strong>任播</strong>：分配多个节点，数据发送到最近的一个（按路由距离）。</li>
</ul>
<h3 id="地址获取与-dad">地址获取与 DAD</h3>
<p>IPv6 地址可以通过两种方式获取：</p>
<ul>
<li><strong>无状态地址自动配置（SLAAC）</strong>：根据路由器通告的前缀 + 接口标识符（通常由 MAC 生成 EUI-64）自动生成地址。</li>
<li><strong>动态主机配置协议 v6（DHCPv6）</strong>：有状态配置，可下发 DNS 等信息。</li>
</ul>
<p>获得的 IPv6 地址需要通过<strong>重复地址检测（DAD）</strong> 之后才可使用：节点发送邻居请求（NS）询问该地址是否已被使用，若无响应则地址有效。</p>
<h3 id="邻居发现协议ndp">邻居发现协议（NDP）</h3>
<p>NDP 取代 IPv4 的 ARP，提供：</p>
<ul>
<li><strong>地址解析</strong>：使用邻居请求（NS）/邻居通告（NA）获取链路层地址。</li>
<li><strong>路由器发现</strong>：主机通过路由器通告（RA）获知前缀和默认网关。</li>
<li><strong>地址自动配置</strong>：结合 SLAAC。</li>
<li><strong>重定向</strong>：路由器通知主机更优的下一跳。</li>
</ul>
<h3 id="ipv4-向-ipv6-过渡技术">IPv4 向 IPv6 过渡技术</h3>
<p>三大类过渡技术：</p>
<ol>
<li><strong>双协议栈</strong>：节点同时运行 IPv4 和 IPv6，根据目的地址选择协议。</li>
<li><strong>隧道技术</strong>：将 IPv6 分组封装在 IPv4 分组中，穿越 IPv4 网络（如 6to4、Teredo）。</li>
<li><strong>NAT-PT / NAT64</strong>：在边界网关处进行 IPv6 与 IPv4 地址和协议的转换。</li>
</ol>
<h2 id="路由选择协议">路由选择协议</h2>
<p>按照运行的位置，路由选择协议分为：</p>
<ul>
<li><strong>IGP（内部网关协议）</strong>：在一个自治系统（AS）内部运行，如 RIP、OSPF。</li>
<li><strong>EGP（外部网关协议）</strong>：AS 之间运行，主要是 BGP。</li>
</ul>
<h3 id="距离矢量路由协议rip">距离矢量路由协议（RIP）</h3>
<p>基本原理：每个路由器周期性地向邻居通告其到所有目的网络的“距离”（跳数），并更新自己的路由表。</p>
<ul>
<li><strong>RIP（Routing Information Protocol）</strong>：使用跳数作为度量（最大 15，16 表示无穷大）。每 30 秒广播更新。存在<strong>计数到无穷</strong>问题：链路故障时，错误路由信息在网中传播，需通过水平分割、毒性逆转、最大跳数限制（15）等方法缓解。</li>
<li><strong>RIPv2</strong>：支持 CIDR、认证和多播。</li>
</ul>
<h3 id="链路状态路由协议ospf">链路状态路由协议（OSPF）</h3>
<p>链路状态（LS）路由协议的基本原理是：发现、设置、构造、分发和计算。每个路由器通过洪泛 LSA（链路状态通告）收集全网的拓扑信息，用 Dijkstra 算法计算最短路径。</p>
<p><strong>OSPF（开放最短路径优先）</strong>：</p>
<ul>
<li>五种报文：Hello（建立邻居）、数据库描述（DD，同步 LSA 摘要）、链路状态请求（LSR）、链路状态更新（LSU）、链路状态确认（LSAck）。</li>
<li><strong>DR/BDR 选举</strong>：在广播多路访问网络（如以太网）中，选举一个指定路由器（DR）和备份 BDR 来减少 LSA 洪泛。</li>
<li><strong>分区域运行</strong>：将大型 AS 分为多个区域（Area 0 为骨干区域），区域内部计算详细路由，区域间汇总路由。好处：缩小路由表、隔离故障、减少 LSA 洪泛。</li>
</ul>
<h2 id="qos服务质量">QoS（服务质量）</h2>
<p>网络从免费走向商用时，QoS 问题就不可回避了。本章探讨了三个 QoS 模型：</p>
<ol>
<li><strong>综合服务模型（IntServ）</strong>：为每个流（如视频会议）预留资源，使用 RSVP 信令。可提供严格 QoS，但扩展性差，不适合大规模网络。</li>
<li><strong>区分服务模型（DiffServ）</strong>：对流量分类标记（DS 字段），边界路由器标记流量类别，核心路由器按每跳行为（PHB）调度（如加速转发 EF、确保转发 AF）。可扩展性好，是目前主流的 QoS 方案。</li>
<li><strong>多协议标签交换（MPLS）</strong>：在网络边缘给分组打上固定长度的标签，核心路由器根据标签快速转发（不查 IP 头）。支持流量工程和虚拟专用网（VPN），位于层 2 和层 3 之间。</li>
</ol>
<hr>
<p><a href="/pdf/05-%E8%B7%AF%E7%94%B1%E9%80%89%E6%8B%A9%E5%92%8C%E7%BD%91%E7%BB%9C%E5%B1%82-0929.pdf">0929</a><br>
<a href="/pdf/05-%E8%B7%AF%E7%94%B1%E9%80%89%E6%8B%A9%E5%92%8C%E7%BD%91%E7%BB%9C%E5%B1%82-1014.pdf">1014</a></p>
]]></content:encoded></item><item><title>传输层</title><link>https://farmer3-c.github.io/posts/computer-networks/transport-layer/</link><pubDate>Wed, 27 Aug 2025 19:47:43 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/transport-layer/</guid><description>&lt;p&gt;传输层是承接应用层和网络层的关键一环，传输层基于网络层提供的服务将主机与主机之间的通信封装为端与端之间的通信，实现了两台主机进程之间的数据交付，并且为上层应用屏蔽了复杂的底层网络细节，建立了网络的抽象模型。围绕以上特性，本章探讨传输层使用的技术。&lt;/p&gt;
&lt;h3 id="1传输层多路复用分用功能与端到端传输"&gt;（1）传输层多路复用/分用功能与端到端传输&lt;/h3&gt;
&lt;p&gt;传输层通过 &lt;strong&gt;多路复用&lt;/strong&gt; 和 &lt;strong&gt;多路分用&lt;/strong&gt; 实现多个应用进程共享网络层服务。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多路复用&lt;/strong&gt;：发送方传输层将多个应用进程的数据（来自不同套接字）封装成数据段，然后传递给网络层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多路分用&lt;/strong&gt;：接收方传输层根据数据段中的端口号，将数据交付给正确的套接字（即相应进程）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;端口&lt;/strong&gt;：16 位整数（0–65535），用于标识主机上的特定进程。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;熟知端口&lt;/strong&gt;（0–1023）：分配给标准服务，如 HTTP(80)、HTTPS(443)、FTP(21)、SSH(22)、DNS(53)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;注册端口&lt;/strong&gt;（1024–49151）：用户应用程序使用，需要向 IANA 注册。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态/私有端口&lt;/strong&gt;（49152–65535）：客户端临时使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;套接字（Socket）&lt;/strong&gt;：IP 地址 + 端口号的组合，唯一标识网络中的一个端点。套接字是应用层与传输层之间的编程抽象。&lt;/p&gt;
&lt;p&gt;传输层提供两种核心服务模式：无连接的 UDP 和面向连接的 TCP。&lt;/p&gt;
&lt;h3 id="2udp用户数据报协议"&gt;（2）UDP（用户数据报协议）&lt;/h3&gt;
&lt;p&gt;UDP 提供无连接、不可靠的数据传输服务，不保证顺序，不进行重传。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;无连接：发送前无需建立连接，每个 UDP 数据段独立处理。&lt;/li&gt;
&lt;li&gt;轻量：头部开销小（仅 8 字节），无拥塞控制和流量控制。&lt;/li&gt;
&lt;li&gt;支持组播和广播。&lt;/li&gt;
&lt;li&gt;应用场景：对延迟敏感、容忍丢包、实时性要求高的场景（如 DNS 查询、VoIP、视频直播、在线游戏）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;UDP 数据段格式&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;源端口（2 字节）、目的端口（2 字节）、长度（2 字节，包括头部和数据）、校验和（2 字节，覆盖头部和数据及伪头部）。&lt;/li&gt;
&lt;li&gt;校验和计算：包含 UDP 伪头部（源 IP、目的 IP、协议号、UDP 长度），用于检测从网络层到传输层的差错。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;典型应用&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;远程过程调用（RPC）&lt;/strong&gt;：客户调用远程服务时，UDP 的低延迟适合请求-响应交互。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时传输协议（RTP）&lt;/strong&gt;：通常运行在 UDP 上，传输音视频媒体流，允许少量丢包。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3tcp传输控制协议"&gt;（3）TCP（传输控制协议）&lt;/h3&gt;
&lt;p&gt;TCP 提供面向连接、可靠、有序的字节流服务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;面向连接：数据传输前需经过三次握手建立连接。&lt;/li&gt;
&lt;li&gt;可靠传输：使用序号、确认、重传保证数据不丢失、不重复、按序到达。&lt;/li&gt;
&lt;li&gt;流量控制：基于滑动窗口机制，协调发送速率避免接收方缓存溢出。&lt;/li&gt;
&lt;li&gt;拥塞控制：动态调整发送速率，避免网络过载。&lt;/li&gt;
&lt;li&gt;全双工通信：支持双向同时传输数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;TCP 数据段格式&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;源端口、目的端口（各 2 字节）&lt;/li&gt;
&lt;li&gt;序号（4 字节，本段第一个字节的序号）&lt;/li&gt;
&lt;li&gt;确认号（4 字节，期望收到的下一个序号，表示之前的数据都已收到）&lt;/li&gt;
&lt;li&gt;数据偏移（4 位，头部长度）&lt;/li&gt;
&lt;li&gt;标志位：ACK（确认有效）、RST（复位）、SYN（同步序号）、FIN（终止连接）、URG（紧急指针有效）、PSH（立即推送）&lt;/li&gt;
&lt;li&gt;窗口大小（2 字节，接收方给出的剩余缓存空间）&lt;/li&gt;
&lt;li&gt;校验和（2 字节，覆盖头部、数据和伪头部）&lt;/li&gt;
&lt;li&gt;紧急指针（2 字节，与 URG 配合）&lt;/li&gt;
&lt;li&gt;选项（可变长，如最大段大小 MSS、时间戳、窗口缩放因子）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;可靠传输机制&lt;/strong&gt;：&lt;/p&gt;</description><content:encoded><![CDATA[<p>传输层是承接应用层和网络层的关键一环，传输层基于网络层提供的服务将主机与主机之间的通信封装为端与端之间的通信，实现了两台主机进程之间的数据交付，并且为上层应用屏蔽了复杂的底层网络细节，建立了网络的抽象模型。围绕以上特性，本章探讨传输层使用的技术。</p>
<h3 id="1传输层多路复用分用功能与端到端传输">（1）传输层多路复用/分用功能与端到端传输</h3>
<p>传输层通过 <strong>多路复用</strong> 和 <strong>多路分用</strong> 实现多个应用进程共享网络层服务。</p>
<ul>
<li><strong>多路复用</strong>：发送方传输层将多个应用进程的数据（来自不同套接字）封装成数据段，然后传递给网络层。</li>
<li><strong>多路分用</strong>：接收方传输层根据数据段中的端口号，将数据交付给正确的套接字（即相应进程）。</li>
</ul>
<p><strong>端口</strong>：16 位整数（0–65535），用于标识主机上的特定进程。</p>
<ul>
<li><strong>熟知端口</strong>（0–1023）：分配给标准服务，如 HTTP(80)、HTTPS(443)、FTP(21)、SSH(22)、DNS(53)。</li>
<li><strong>注册端口</strong>（1024–49151）：用户应用程序使用，需要向 IANA 注册。</li>
<li><strong>动态/私有端口</strong>（49152–65535）：客户端临时使用。</li>
</ul>
<p><strong>套接字（Socket）</strong>：IP 地址 + 端口号的组合，唯一标识网络中的一个端点。套接字是应用层与传输层之间的编程抽象。</p>
<p>传输层提供两种核心服务模式：无连接的 UDP 和面向连接的 TCP。</p>
<h3 id="2udp用户数据报协议">（2）UDP（用户数据报协议）</h3>
<p>UDP 提供无连接、不可靠的数据传输服务，不保证顺序，不进行重传。</p>
<p><strong>特点</strong>：</p>
<ul>
<li>无连接：发送前无需建立连接，每个 UDP 数据段独立处理。</li>
<li>轻量：头部开销小（仅 8 字节），无拥塞控制和流量控制。</li>
<li>支持组播和广播。</li>
<li>应用场景：对延迟敏感、容忍丢包、实时性要求高的场景（如 DNS 查询、VoIP、视频直播、在线游戏）。</li>
</ul>
<p><strong>UDP 数据段格式</strong>：</p>
<ul>
<li>源端口（2 字节）、目的端口（2 字节）、长度（2 字节，包括头部和数据）、校验和（2 字节，覆盖头部和数据及伪头部）。</li>
<li>校验和计算：包含 UDP 伪头部（源 IP、目的 IP、协议号、UDP 长度），用于检测从网络层到传输层的差错。</li>
</ul>
<p><strong>典型应用</strong>：</p>
<ul>
<li><strong>远程过程调用（RPC）</strong>：客户调用远程服务时，UDP 的低延迟适合请求-响应交互。</li>
<li><strong>实时传输协议（RTP）</strong>：通常运行在 UDP 上，传输音视频媒体流，允许少量丢包。</li>
</ul>
<h3 id="3tcp传输控制协议">（3）TCP（传输控制协议）</h3>
<p>TCP 提供面向连接、可靠、有序的字节流服务。</p>
<p><strong>特点</strong>：</p>
<ul>
<li>面向连接：数据传输前需经过三次握手建立连接。</li>
<li>可靠传输：使用序号、确认、重传保证数据不丢失、不重复、按序到达。</li>
<li>流量控制：基于滑动窗口机制，协调发送速率避免接收方缓存溢出。</li>
<li>拥塞控制：动态调整发送速率，避免网络过载。</li>
<li>全双工通信：支持双向同时传输数据。</li>
</ul>
<p><strong>TCP 数据段格式</strong>：</p>
<ul>
<li>源端口、目的端口（各 2 字节）</li>
<li>序号（4 字节，本段第一个字节的序号）</li>
<li>确认号（4 字节，期望收到的下一个序号，表示之前的数据都已收到）</li>
<li>数据偏移（4 位，头部长度）</li>
<li>标志位：ACK（确认有效）、RST（复位）、SYN（同步序号）、FIN（终止连接）、URG（紧急指针有效）、PSH（立即推送）</li>
<li>窗口大小（2 字节，接收方给出的剩余缓存空间）</li>
<li>校验和（2 字节，覆盖头部、数据和伪头部）</li>
<li>紧急指针（2 字节，与 URG 配合）</li>
<li>选项（可变长，如最大段大小 MSS、时间戳、窗口缩放因子）</li>
</ul>
<p><strong>可靠传输机制</strong>：</p>
<ul>
<li><strong>序号机制</strong>：每个字节都有序号，ACK 确认的是累积收到的最高序号的下一字节。</li>
<li><strong>确认机制</strong>：接收方发送 ACK，可延迟确认（通常 200ms）或捎带在数据中。</li>
<li><strong>重传机制</strong>：发送方维护重传计时器，超时未收到 ACK 则重传。超时时间 RTO 根据往返时间 RTT 动态计算（Jacobson 算法）。</li>
</ul>
<p><strong>流量控制</strong>：通过接收窗口（rwnd）实现。接收方在 ACK 中通告自己的可用缓存大小，发送方不能超过该窗口。</p>
<h3 id="4tcp-连接管理">（4）TCP 连接管理</h3>
<p><strong>三次握手建立连接</strong>：</p>
<ol>
<li>客户端发送 SYN 段（seq=x，SYN=1），进入 SYN_SENT。</li>
<li>服务器回复 SYN+ACK（seq=y，ACK=x+1，SYN=1），进入 SYN_RCVD。</li>
<li>客户端发送 ACK（ACK=y+1），进入 ESTABLISHED；服务器收到 ACK 后也进入 ESTABLISHED。</li>
</ol>
<p>必要性：防止旧的重复连接请求突然到达服务器而产生错误；双方协商初始序号。</p>
<p><strong>四次挥手释放连接</strong>：</p>
<ol>
<li>主动关闭方发送 FIN（seq=u），进入 FIN_WAIT_1。</li>
<li>被动关闭方回复 ACK（ACK=u+1），进入 CLOSE_WAIT；主动方进入 FIN_WAIT_2。</li>
<li>被动方发送 FIN（seq=v），进入 LAST_ACK。</li>
<li>主动方回复 ACK（ACK=v+1），进入 TIME_WAIT（等待 2MSL 后关闭），被动方关闭。</li>
</ol>
<p><strong>TCP 状态机</strong>：包括 LISTEN、SYN_SENT、SYN_RCVD、ESTABLISHED、FIN_WAIT_1/2、CLOSE_WAIT、TIME_WAIT、CLOSED 等状态。</p>
<h3 id="5tcp-计时器管理">（5）TCP 计时器管理</h3>
<p>四种常见计时器：</p>
<ul>
<li><strong>重传计时器</strong>：超时未收到 ACK 则重传，RTO 基于 RTT 估算（使用 Karn 算法处理重传歧义）。</li>
<li><strong>持续计时器</strong>：当接收窗口为 0 时启动，定期发送零窗口探测，防止窗口更新丢失导致的死锁。</li>
<li><strong>保活计时器</strong>：长时间空闲时发送探测段，用于检测连接是否存活（默认 2 小时）。</li>
<li><strong>时间等待计时器</strong>：TIME_WAIT 状态时长 2MSL（最长报文段寿命），确保最后一个 ACK 可重发并延迟释放端口。</li>
</ul>
<p><strong>RTT 估算</strong>：Jacobson 算法使用加权移动平均：<br>
<code>SRTT = α * SRTT + (1-α) * RTT_sample</code>（α 通常 0.875）<br>
<code>RTTVAR = β * RTTVAR + (1-β) * |SRTT - RTT_sample|</code><br>
<code>RTO = SRTT + 4 * RTTVAR</code><br>
Karn 算法指出：重传后的 RTT 样本不应参与计算，且采用指数退避。</p>
<h3 id="6tcp-拥塞控制">（6）TCP 拥塞控制</h3>
<p>拥塞控制的目标是避免网络过载，公平共享带宽。TCP 使用窗口机制：拥塞窗口（cwnd）与接收窗口（rwnd）的最小值为实际发送窗口。</p>
<p>四个阶段：</p>
<ol>
<li><strong>慢启动</strong>：cwnd 从 1 个 MSS 开始，每收到一个 ACK 增加 1 个 MSS（指数增长），直到达到慢启动阈值 ssthresh。</li>
<li><strong>拥塞避免</strong>：cwnd 每 RTT 增加 1 个 MSS（线性增长），直到出现丢包（超时或收到三个重复 ACK）。</li>
<li><strong>快速重传</strong>：发送方收到三个重复 ACK 后立即重传丢失段，无需等待超时。</li>
<li><strong>快速恢复</strong>（TCP Reno）：将 ssthresh 设为 cwnd/2，cwnd 设为 ssthresh + 3，然后进入拥塞避免。</li>
</ol>
<p><strong>AIMD（加性增乘性减）</strong>：拥塞避免阶段线性增加；丢包后将窗口减半（乘性减）。此算法保证了 TCP 流的公平性（多个流共享瓶颈链路时逐渐收敛到公平带宽分配）。</p>
<h3 id="7新一代传输协议-quic">（7）新一代传输协议 QUIC</h3>
<p>TCP 在移动网络、高延迟、多路复用下存在头部阻塞等问题。QUIC（Quick UDP Internet Connections）是基于 UDP 的新一代低时延传输协议。</p>
<p><strong>发展历程</strong>：由 Google 提出，现已成为 IETF 标准（RFC 9000），是 HTTP/3 的底层传输协议。</p>
<p><strong>优化思路</strong>：</p>
<ul>
<li><strong>多流复用</strong>：在一个连接内支持多个独立流，某个流丢包不影响其他流（解决 TCP 头部阻塞）。</li>
<li><strong>0-RTT 连接建立</strong>：结合加密握手，可在首个数据包中携带数据，减少延迟。</li>
<li><strong>连接迁移</strong>：使用连接 ID 而非 (IP, port) 标识连接，支持移动设备切换网络时连接不断。</li>
<li><strong>改进的拥塞控制</strong>：每个流独立拥塞控制，可插拔算法（如 BBR）。</li>
</ul>
<p><strong>数据段格式</strong>：长头部（版本协商）和短头部（常规传输），包含连接 ID、包号、帧类型等。</p>
<p><strong>连接管理</strong>：基于非对称加密的握手，结合 TLS 1.3，实现安全与连接建立并行。</p>
<p>QUIC 通过“流”这一概念，实现了更灵活的传输模型，特别适用于 Web 和实时应用。</p>
]]></content:encoded></item><item><title>链路层</title><link>https://farmer3-c.github.io/posts/computer-networks/data-link-layer/</link><pubDate>Wed, 27 Aug 2025 19:47:32 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/data-link-layer/</guid><description>&lt;h2 id="数据链路层的主要功能"&gt;数据链路层的主要功能&lt;/h2&gt;
&lt;p&gt;数据链路层位于物理层和网络层之间，其主要功能包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;成帧&lt;/strong&gt;：将网络层交付的比特流封装成独立的帧，添加帧头和帧尾，以便接收方能识别帧的边界。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;差错控制&lt;/strong&gt;：通过检错码或纠错码检测（或纠正）传输过程中产生的比特错误，并可配合重传机制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流量控制&lt;/strong&gt;：协调发送方和接收方的速率，防止接收方缓存溢出。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;介质访问控制（MAC）&lt;/strong&gt;：在广播型多路访问链路（如以太网、WiFi）上，决定哪个节点何时占用信道。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;链路管理&lt;/strong&gt;：建立、维护和释放数据链路层的连接（在面向连接的链路中）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可靠传输&lt;/strong&gt;：在不可靠的物理链路上，通过确认和重传机制实现数据的可靠交付。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本章对成帧的基本方法进行了详细的描述；针对错误的处理这一数据链路层的重要任务，介绍了检错和纠错的基本原理和典型的编码方法；详细介绍了奇偶检验、循环冗余校验、互联网校验等常用检错码，以及纠1位错的海明码、里所码、低密度奇偶检验等常用纠错码。&lt;/p&gt;
&lt;h3 id="成帧的基本方法"&gt;成帧的基本方法&lt;/h3&gt;
&lt;p&gt;成帧是指将原始比特流分割成若干独立的帧，以便接收方能准确提取每个帧的数据。常用方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;字节计数法&lt;/strong&gt;：帧头中使用一个字段表示帧的总长度（字节数）。接收方读取长度字段后，就知道从哪里结束。缺点：长度字段本身出错会导致帧同步丢失。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;字节填充的标志字节法&lt;/strong&gt;：使用特殊标志字节（如 FLAG=0x7E）表示帧的开始和结束。如果数据中出现了标志字节，则在其前面插入转义字节（如 ESC=0x7D）。接收方遇到转义字节则删除并还原数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;比特填充的标志比特法&lt;/strong&gt;（HDLC 常用）：使用标志位序列 01111110 作为帧边界。发送方在数据中连续出现 5 个 1 后自动插入一个 0；接收方连续收到 5 个 1 后，若下一比特为 0 则删除该 0，若为 1 且再下一比特为 0 则视为标志。该方法避免了修改数据内容长度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;物理层编码违例法&lt;/strong&gt;：利用物理层编码中的“非法”信号作为帧边界（例如曼彻斯特编码中不使用连续的相同电平）。仅适用于特定的物理层编码。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="检错与纠错基本原理"&gt;检错与纠错基本原理&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;检错码&lt;/strong&gt;：在数据后添加冗余位（校验位），使得接收方能根据校验位判断数据是否出错。常见检错码：奇偶校验、循环冗余校验（CRC）、校验和（Checksum）。检错码无法确定错误位置，只能判断“有/无错误”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;纠错码&lt;/strong&gt;：添加更多冗余位，使接收方能不仅检测错误，还能定位并纠正一定数量的错误比特。典型纠错码：海明码（纠1位错）、BCH码、里所（Reed-Solomon）码、低密度奇偶检验（LDPC）码。纠错码的编码效率（数据位/总位数）较低，适用于无法重传的场景（如深空通信、实时音频）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="常用检错码详解"&gt;常用检错码详解&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;奇偶校验&lt;/strong&gt;：在数据后面附加一个比特，使整个数据中 1 的个数为奇数（奇校验）或偶数（偶校验）。可以检测奇数个比特错误，但不能检测偶数个错误，且无法纠错。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;循环冗余校验（CRC）&lt;/strong&gt;：将数据视为多项式，用生成多项式相除，余数作为 CRC 码附加。接收方重新计算并比对余数。可以检测任意长度的大多数突发错误（取决于生成多项式），广泛用于以太网、WiFi、存储设备。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;互联网校验和（Internet Checksum）&lt;/strong&gt;：将数据按 16 位字分组，进行二进制反码求和，结果取反。简单高效，用于 IP、TCP、UDP 头部校验。错误检测能力弱于 CRC，但便于在软件中快速计算。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="常用纠错码简介"&gt;常用纠错码简介&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;海明码（Hamming Code）&lt;/strong&gt;：通过在数据位之间插入校验位，使得数据位与校验位形成多个奇偶校验组。能够纠正单比特错误，并能检测双比特错误（扩展海明码）。最小码距为 3（或 4）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;里所码（Reed-Solomon, RS）&lt;/strong&gt;：非二进制纠错码，以符号（如 8 位字节）为单位进行编码，非常擅长纠正突发错误。广泛用于光盘、QR 码、卫星通信、数字电视。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;低密度奇偶检验码（LDPC）&lt;/strong&gt;：使用稀疏校验矩阵，通过迭代置信传播译码，性能接近香农极限。用于 5G、WiFi 6（802.11ax）、10G 以太网等。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了实现数据链路层上的可靠传输，本章介绍了利用停-等协议实现流量控制，利用肯定确认与重传机制处理信道上出现差错的情况。此外，为了提高信道利用率，本章介绍了滑动窗口协议的基本思想，在此基础上详细说明了回退 n 帧协议和选择性重传协议的工作原理，并对两者的滑动窗口大小进行了分析。&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="数据链路层的主要功能">数据链路层的主要功能</h2>
<p>数据链路层位于物理层和网络层之间，其主要功能包括：</p>
<ul>
<li><strong>成帧</strong>：将网络层交付的比特流封装成独立的帧，添加帧头和帧尾，以便接收方能识别帧的边界。</li>
<li><strong>差错控制</strong>：通过检错码或纠错码检测（或纠正）传输过程中产生的比特错误，并可配合重传机制。</li>
<li><strong>流量控制</strong>：协调发送方和接收方的速率，防止接收方缓存溢出。</li>
<li><strong>介质访问控制（MAC）</strong>：在广播型多路访问链路（如以太网、WiFi）上，决定哪个节点何时占用信道。</li>
<li><strong>链路管理</strong>：建立、维护和释放数据链路层的连接（在面向连接的链路中）。</li>
<li><strong>可靠传输</strong>：在不可靠的物理链路上，通过确认和重传机制实现数据的可靠交付。</li>
</ul>
<p>本章对成帧的基本方法进行了详细的描述；针对错误的处理这一数据链路层的重要任务，介绍了检错和纠错的基本原理和典型的编码方法；详细介绍了奇偶检验、循环冗余校验、互联网校验等常用检错码，以及纠1位错的海明码、里所码、低密度奇偶检验等常用纠错码。</p>
<h3 id="成帧的基本方法">成帧的基本方法</h3>
<p>成帧是指将原始比特流分割成若干独立的帧，以便接收方能准确提取每个帧的数据。常用方法：</p>
<ul>
<li><strong>字节计数法</strong>：帧头中使用一个字段表示帧的总长度（字节数）。接收方读取长度字段后，就知道从哪里结束。缺点：长度字段本身出错会导致帧同步丢失。</li>
<li><strong>字节填充的标志字节法</strong>：使用特殊标志字节（如 FLAG=0x7E）表示帧的开始和结束。如果数据中出现了标志字节，则在其前面插入转义字节（如 ESC=0x7D）。接收方遇到转义字节则删除并还原数据。</li>
<li><strong>比特填充的标志比特法</strong>（HDLC 常用）：使用标志位序列 01111110 作为帧边界。发送方在数据中连续出现 5 个 1 后自动插入一个 0；接收方连续收到 5 个 1 后，若下一比特为 0 则删除该 0，若为 1 且再下一比特为 0 则视为标志。该方法避免了修改数据内容长度。</li>
<li><strong>物理层编码违例法</strong>：利用物理层编码中的“非法”信号作为帧边界（例如曼彻斯特编码中不使用连续的相同电平）。仅适用于特定的物理层编码。</li>
</ul>
<h3 id="检错与纠错基本原理">检错与纠错基本原理</h3>
<ul>
<li><strong>检错码</strong>：在数据后添加冗余位（校验位），使得接收方能根据校验位判断数据是否出错。常见检错码：奇偶校验、循环冗余校验（CRC）、校验和（Checksum）。检错码无法确定错误位置，只能判断“有/无错误”。</li>
<li><strong>纠错码</strong>：添加更多冗余位，使接收方能不仅检测错误，还能定位并纠正一定数量的错误比特。典型纠错码：海明码（纠1位错）、BCH码、里所（Reed-Solomon）码、低密度奇偶检验（LDPC）码。纠错码的编码效率（数据位/总位数）较低，适用于无法重传的场景（如深空通信、实时音频）。</li>
</ul>
<h3 id="常用检错码详解">常用检错码详解</h3>
<ul>
<li><strong>奇偶校验</strong>：在数据后面附加一个比特，使整个数据中 1 的个数为奇数（奇校验）或偶数（偶校验）。可以检测奇数个比特错误，但不能检测偶数个错误，且无法纠错。</li>
<li><strong>循环冗余校验（CRC）</strong>：将数据视为多项式，用生成多项式相除，余数作为 CRC 码附加。接收方重新计算并比对余数。可以检测任意长度的大多数突发错误（取决于生成多项式），广泛用于以太网、WiFi、存储设备。</li>
<li><strong>互联网校验和（Internet Checksum）</strong>：将数据按 16 位字分组，进行二进制反码求和，结果取反。简单高效，用于 IP、TCP、UDP 头部校验。错误检测能力弱于 CRC，但便于在软件中快速计算。</li>
</ul>
<h3 id="常用纠错码简介">常用纠错码简介</h3>
<ul>
<li><strong>海明码（Hamming Code）</strong>：通过在数据位之间插入校验位，使得数据位与校验位形成多个奇偶校验组。能够纠正单比特错误，并能检测双比特错误（扩展海明码）。最小码距为 3（或 4）。</li>
<li><strong>里所码（Reed-Solomon, RS）</strong>：非二进制纠错码，以符号（如 8 位字节）为单位进行编码，非常擅长纠正突发错误。广泛用于光盘、QR 码、卫星通信、数字电视。</li>
<li><strong>低密度奇偶检验码（LDPC）</strong>：使用稀疏校验矩阵，通过迭代置信传播译码，性能接近香农极限。用于 5G、WiFi 6（802.11ax）、10G 以太网等。</li>
</ul>
<p>为了实现数据链路层上的可靠传输，本章介绍了利用停-等协议实现流量控制，利用肯定确认与重传机制处理信道上出现差错的情况。此外，为了提高信道利用率，本章介绍了滑动窗口协议的基本思想，在此基础上详细说明了回退 n 帧协议和选择性重传协议的工作原理，并对两者的滑动窗口大小进行了分析。</p>
<h3 id="停-等协议stop-and-wait">停-等协议（Stop-and-Wait）</h3>
<p>发送方每发送一个帧，就必须等待接收方发回确认（ACK）后才能发送下一帧。若超过一定时间（重传计时器）未收到 ACK，则重传该帧。接收方发送 ACK 后可设置一个序号（0/1）来区分新旧帧。</p>
<ul>
<li><strong>优点</strong>：实现简单，需要的帧序号少（1 比特即可）。</li>
<li><strong>缺点</strong>：信道利用率低，尤其在长传播时延的链路（如卫星链路）中，发送方大部分时间在等待 ACK。</li>
</ul>
<h3 id="滑动窗口协议">滑动窗口协议</h3>
<p>为了提高信道利用率，允许发送方在未收到确认前连续发送多个帧。发送方维护一个发送窗口（可发送但未确认的帧序号范围），接收方维护一个接收窗口（允许接收的帧序号范围）。窗口大小 W 影响吞吐量和缓冲区需求。</p>
<ul>
<li><strong>回退 n 帧协议（Go-Back-N, GBN）</strong>：接收方只按序接收，若收到失序帧则丢弃，且不发送 ACK。发送方超时后从第一个丢失帧开始重传之后所有帧。<br>
<strong>窗口大小限制</strong>：发送窗口 ≤ 2^m - 1（m 为序号比特数），否则无法区分新旧帧。<br>
<strong>优缺点</strong>：接收方缓存要求低（只需 1 个位置），但重传效率低（一帧错误导致多帧重传）。</li>
<li><strong>选择性重传协议（Selective Repeat, SR）</strong>：接收方可以缓存所有正确接收但序号不连续的帧，并对每个正确帧单独发送 ACK。发送方仅重传超时的帧。<br>
<strong>窗口大小限制</strong>：发送窗口和接收窗口均 ≤ 2^(m-1)。<br>
<strong>优缺点</strong>：效率高（只重传错误帧），但需要接收方缓存失序帧，实现更复杂。</li>
</ul>
<p>本章选择 HDLC 协议、PPP 以及 PPPoE 作为数据链路层的协议实例，通过介绍这三个协议的工作机制，进一步帮助读者理解数据链路层协议在网络体系结构中起到的重要作用。</p>
<h3 id="协议实例解析">协议实例解析</h3>
<ul>
<li><strong>HDLC（High-Level Data Link Control）</strong>：面向比特的同步链路层协议，支持点对点和多点链路。使用比特填充（01111110 标志）实现透明传输。提供三种帧类型：信息帧（I）、监控帧（S，用于确认和拒绝）、无编号帧（U，用于链路建立/释放）。帧中包含 3 比特序号，支持滑动窗口。</li>
<li><strong>PPP（Point-to-Point Protocol）</strong>：面向字节的点对点链路协议，广泛用于拨号上网、PPPoE 等。使用字节填充的标志字节（0x7E）。支持多种网络层协议（如 IP、IPX）。封装时包含协议字段，提供 LCP（链路控制协议）建立/配置链路，以及 NCP（网络控制协议）配置网络层参数。</li>
<li><strong>PPPoE（PPP over Ethernet）</strong>：将 PPP 帧封装在以太网帧中，支持以太网上的点对点会话（如宽带拨号）。分为发现阶段（获取对端 MAC 地址和 Session ID）和会话阶段（传输 PPP 帧）。PPPoE 使得 ISP 可以在共享以太网上对每个用户进行身份认证和计费。</li>
</ul>
<h2 id="局域网与介质访问控制">局域网与介质访问控制</h2>
<p>本章从局域网的拓扑和传输数据方式开始，阐述了局域网中的广播信道和传输带来的问题，由此引出介质访问控制（MAC）子层。MAC 子层是数据链路层的主要部分，局域网主要覆盖了物理层和数据链路层两层的内容。</p>
<h3 id="广播信道与冲突问题">广播信道与冲突问题</h3>
<p>局域网通常采用多路访问广播信道（如总线型、星型），所有节点共享同一信道。当多个节点同时发送时，信号在信道上叠加（<strong>冲突</strong>），导致数据损坏。解决冲突的方法就是介质访问控制协议。</p>
<p>介质访问控制解决共享信道引发的争用问题，主要有随机访问协议、受控访问协议和有限竞争访问协议三种。</p>
<h3 id="随机访问协议">随机访问协议</h3>
<p>节点随机发送数据，发生冲突后采取相应恢复机制。</p>
<ul>
<li><strong>纯 ALOHA</strong>：有数据就发，冲突后等待随机时间重传。效率低（最大吞吐量仅 18.4%）。</li>
<li><strong>分槽 ALOHA</strong>：将时间划分为时间槽，节点只能在槽开始时刻发送。冲突概率减半，最大吞吐量提高到 36.8%。</li>
<li><strong>CSMA（载波侦听多路访问）</strong>：发送前先侦听信道（“先听后发”）。包括 1-坚持 CSMA（信道空闲立即发）、非坚持 CSMA（空闲则发，否则等待随机时间）和 p-坚持 CSMA（以概率 p 发送）。</li>
<li><strong>CSMA/CD（带冲突检测的 CSMA）</strong>：在 CSMA 基础上增加“边发边听”，一旦检测到冲突立即停止发送并发送阻塞信号，然后随机退避。用于经典以太网（半双工模式）。最小帧长需保证在发送完成前能检测到冲突（对于 10M 以太网，最小帧长 64 字节）。</li>
</ul>
<h3 id="受控访问协议">受控访问协议</h3>
<p>无冲突协议，节点通过某种机制轮流使用信道。</p>
<ul>
<li><strong>位图协议（预留协议）</strong>：每个竞争周期内，每个节点在自己的比特槽中宣布是否有数据要发，后续按位图顺序轮询发送。</li>
<li><strong>二进制倒计数协议</strong>：每个帧发送前，节点以二进制地址竞争信道，地址高的节点优先发送。</li>
<li><strong>令牌传递协议</strong>：一个特殊的令牌帧在网络中循环，只有持有令牌的节点才能发送数据。用于令牌环、FDDI。</li>
</ul>
<h3 id="有限竞争访问协议">有限竞争访问协议</h3>
<p>结合随机访问（轻载时低延迟）和受控访问（重载时高吞吐量）的优点，如自适应树搜索协议。</p>
<p>以太网是使用最广泛的局域网，本章介绍了经典以太网的物理拓扑和逻辑拓扑介质访问控制方法；经典以太网逐渐过渡到了交换式以太网，冲突域的缩小，提升了网络的性能。</p>
<h3 id="以太网帧格式">以太网帧格式</h3>
<p>以太网数据帧的格式是重要的内容，本章详细介绍了 DIX 以太网数据帧中各个字段的名称和含义，在此基础上介绍 IEEE 802.3 数据帧的不同之处，读者可对比学习。</p>
<ul>
<li>
<p><strong>DIX Ethernet II 帧</strong>（当前主流）：</p>
<ul>
<li>前导码（7 字节同步 + 1 字节 SFD）</li>
<li>目的 MAC 地址（6 字节）</li>
<li>源 MAC 地址（6 字节）</li>
<li>类型（2 字节，表示上层协议如 0x0800 为 IP）</li>
<li>数据（46–1500 字节）</li>
<li>帧校验序列（FCS，4 字节 CRC32）</li>
</ul>
</li>
<li>
<p><strong>IEEE 802.3 帧</strong>：用“长度”字段代替“类型”字段（2 字节），数据之后增加 LLC（逻辑链路控制）头部。由于实际使用中类型字段更灵活，802.3 帧逐渐被 DIX 替代。</p>
</li>
</ul>
<p>以太网从 10M 经典以太网开始，不断发展，传输速率从 10 Mb/s 到 100 Mb/s（快速以太网），再到 1000 Mb/s（吉比特以太网），后面还有万兆以太网、25 Gb/s、40 Gb/s、100 Gb/s、400 Gb/s，以太网也从局域网的范畴跨入了广域传输的范畴。</p>
<h3 id="交换式以太网与交换机工作原理">交换式以太网与交换机工作原理</h3>
<p>数据链路层（L2）交换原理可以用转发、丢弃（过滤）、泛洪和学习 4 个词概括，每个数据帧的到来，促使算法运行以决策执行哪个动作（三选一）：学习的全称是逆向地址学习，以建立、更新和维护 MAC 地址表（决策依据），学习每个数据帧，且终身学习。</p>
<ul>
<li><strong>转发</strong>：若目的 MAC 地址在 MAC 地址表中且端口不同于接收端口，将帧从该端口转发出去。</li>
<li><strong>丢弃（过滤）</strong>：若目的 MAC 地址对应的端口就是接收端口，则丢弃（不转发）。</li>
<li><strong>泛洪</strong>：若目的 MAC 地址是广播地址、多播地址或未知单播地址，则向除接收端口外的所有端口转发。</li>
<li><strong>学习</strong>：从帧的源 MAC 地址和接收端口学习，将映射写入或刷新 MAC 地址表（老化时间通常 300 秒）。</li>
</ul>
<p>执行链路层交换的设备主要是交换机，交换机转发数据帧有三种方式：</p>
<ul>
<li><strong>存储转发交换</strong>：完整接收整个帧并检查 FCS 无误后才转发。错误率低，但时延高（取决于帧长）。</li>
<li><strong>直通交换</strong>：只查看目的 MAC 地址（前 6 字节）即开始转发。时延最低，但可能转发错误帧或冲突碎片。</li>
<li><strong>无碎片交换</strong>：检查前 64 字节（通常错误帧小于 64 字节），无错则转发。出错率和时延介于前两者之间。</li>
</ul>
<h3 id="广播域与-vlan">广播域与 VLAN</h3>
<p>交换机连接起来的网络同在一个物理 LAN，即广播域。大的广播域带来网络性能的下降（广播风暴）和安全问题（任何节点可嗅探广播流量）。虚拟局域网（VLAN）等同于一个广播域，可以切分一个大的物理 LAN 为若干小的 VLAN。</p>
<ul>
<li><strong>VLAN 原理</strong>：通过交换机配置将端口分组，不同 VLAN 间的通信必须经过三层路由（通常使用路由器或三层交换机）。</li>
<li><strong>VLAN 标记</strong>：IEEE 802.1Q 标准在以太网帧中插入 4 字节 VLAN 标签（包含 12 位 VLAN ID），允许多个 VLAN 共享物理链路。</li>
<li><strong>优点</strong>：隔离广播域、增强安全性、简化网络管理、灵活控制访问策略。</li>
</ul>
<h3 id="生成树协议stp">生成树协议（STP）</h3>
<p>为了可靠传输数据帧，交换机之间往往采用多条物理连接，不可避免地形成物理环，从而引发重复帧、MAC 地址表不稳定、广播风暴等严重问题。生成树协议（STP）用于在冗余物理拓扑上产生无环的逻辑树，任意两点之间通达但不产生环。</p>
<ul>
<li><strong>工作原理</strong>：交换机交换 BPDU（桥协议数据单元），选举根桥（Root Bridge），每个非根桥选择到根桥的最短路径端口（根端口），每个网段选择一个指定端口（Designated Port），其余冗余端口被阻塞。</li>
<li><strong>改进</strong>：RSTP（快速 STP）实现了快速收敛（秒级→亚秒级），MSTP（多 STP）支持 VLAN 分组。</li>
</ul>
<h3 id="无线局域网wlan">无线局域网（WLAN）</h3>
<p>无线局域网（WLAN）被称为无线以太网，是非常重要的接入网络。本章主要介绍了 IEEE 802.11 系列标准（Wi-Fi）的发展和主要技术特点、介质访问控制方法 CSMA/CA、数据帧格式等。</p>
<ul>
<li><strong>CSMA/CA（冲突避免）</strong>：由于无线半双工环境下难以边发边听（无法同时检测冲突），采用发送前随机退避（DCF 机制）和可选 RTS/CTS 握手机制减少冲突。</li>
<li><strong>帧格式</strong>：包括帧控制（类型/子类型）、Duration/ID、地址 1~4（最多 4 个：目的、源、BSSID、发送/接收端）、序列控制、数据、FCS。</li>
<li><strong>Wi-Fi 标准演进</strong>：802.11b（11 Mbps）、a/g（54 Mbps）、n（600 Mbps，MIMO）、ac（6.9 Gbps，多用户 MIMO）、ax（Wi-Fi 6，OFDMA）。</li>
</ul>
<h3 id="蓝牙与物联网无线协议">蓝牙与物联网无线协议</h3>
<p>蓝牙技术是短距离、无线、低功耗通信的成功范例，广泛用于音频流、数据传输、定位服务和设备网络等领域。本章介绍了蓝牙网络的物理构成、蓝牙协议的体系结构和蓝牙帧的格式，还介绍了 ZigBee、6LoWPAN、Z-Wave 等无线协议，重点介绍了在物联网中广为使用的 ZigBee 技术的特点，并对蓝牙、ZigBee 和 Wi-Fi 三种无线连接技术进行了对照。</p>
<ul>
<li><strong>蓝牙</strong>：使用 2.4 GHz ISM 频段，跳频扩频（FHSS），主从结构，支持微微网和散射网。经典蓝牙（BR/EDR）用于音频，低功耗蓝牙（BLE）用于传感器。</li>
<li><strong>ZigBee（IEEE 802.15.4）</strong>：低速率（250 kbps）、低功耗、自组网，适合传感器网络、智能家居。支持星型、树型、网状拓扑。</li>
<li><strong>6LoWPAN</strong>：在 IEEE 802.15.4 上传输 IPv6 数据，实现低功耗设备接入互联网。</li>
<li><strong>Z-Wave</strong>：专有协议（868 MHz/900 MHz），用于智能家居，兼容性好。</li>
</ul>
<table>
	<thead>
			<tr>
					<th>技术</th>
					<th>速率</th>
					<th>功耗</th>
					<th>组网能力</th>
					<th>典型应用</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>蓝牙 BLE</td>
					<td>1–2 Mbps</td>
					<td>极低</td>
					<td>星型（主从）</td>
					<td>可穿戴、智能锁</td>
			</tr>
			<tr>
					<td>ZigBee</td>
					<td>250 kbps</td>
					<td>低</td>
					<td>网状，数百节点</td>
					<td>工业监控、智能照明</td>
			</tr>
			<tr>
					<td>Wi-Fi</td>
					<td>数十~数千 Mbps</td>
					<td>高</td>
					<td>星型，数十节点</td>
					<td>互联网接入、视频</td>
			</tr>
	</tbody>
</table>
<hr>
<ul>
<li><a href="/pdf/03-%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82%EF%BC%88%E5%85%A8%EF%BC%89.pdf">链路层</a></li>
<li><a href="/pdf/04-%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82-%E4%BB%8B%E8%B4%A8%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%E5%92%8C%E5%B1%80%E5%9F%9F%E7%BD%91.pdf">数据链路层-介质访问控制和局域网</a></li>
<li><a href="https://web.mit.edu/16.36/2006directory/lectures/Lecture_15.pdf">Cyclic Codes for Error Detection</a></li>
</ul>
]]></content:encoded></item><item><title>物理层</title><link>https://farmer3-c.github.io/posts/computer-networks/physical-layer/</link><pubDate>Wed, 27 Aug 2025 19:46:42 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/physical-layer/</guid><description>&lt;h1 id="物理层负责比特流的透明传输"&gt;物理层负责比特流的透明传输&lt;/h1&gt;
&lt;p&gt;物理层是参考模型中的最底层，是最基础的一层。本章探讨传输比特所需要的介质和所使用的技术。&lt;/p&gt;
&lt;h2 id="通信-信道"&gt;通信 信道&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;物理层通信&lt;/strong&gt;：利用物理传输介质，将计算机中的比特流（0、1）转换为电信号、光信号或电磁波信号，在物理链路上实现透明、原始的比特流传输，不负责数据含义与纠错，只负责信号的发送与接收。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;信道&lt;/strong&gt;：在物理层中，传送信号的通路，是传输比特流的逻辑通道，包含传输介质和相关通信设备。&lt;/p&gt;
&lt;h3 id="模拟和数字通信"&gt;模拟和数字通信&lt;/h3&gt;
&lt;p&gt;数字和模拟通信的区别在于使用数字信号还是模拟信号进行传递消息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模拟信号&lt;/strong&gt;：代表信息的信号及其参数（幅度、频率或相位）随着消息连续变化的信号，它在幅度上连续，但在时间上可以连续也可以不连续。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;波形连续，具有无穷多个幅度取值；&lt;/li&gt;
&lt;li&gt;易受干扰，噪声会累积且难以去除；&lt;/li&gt;
&lt;li&gt;不易加密，不易存储和处理（需先数字化）；&lt;/li&gt;
&lt;li&gt;典型例子：传统电话语音、模拟电视信号。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;数字信号&lt;/strong&gt;：不仅在时间上是离散的，而且在幅度上也是离散的信号，通常只取有限个离散值（如二进制信号取0和1）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;波形离散，只传送0和1；&lt;/li&gt;
&lt;li&gt;抗干扰能力强，噪声不会累积（可通过中继器再生）；&lt;/li&gt;
&lt;li&gt;易加密、易存储、易纠错，与计算机系统天然兼容；&lt;/li&gt;
&lt;li&gt;典型例子：以太网信号、USB信号、光纤通信信号。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="并行和串行通信"&gt;并行和串行通信&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;串行通信&lt;/strong&gt;：数据在传输过程中，逐位依次传输，一次只传输一个比特。数据通过单一的通信线路（如一根电线或一根光纤）按顺序发送和接收。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优点：节省线路资源，线缆成本低；远距离传输时不易出现信号间干扰（串扰）。&lt;/li&gt;
&lt;li&gt;缺点：传输速率相对较低（需通过提高时钟频率来提升速率）。&lt;/li&gt;
&lt;li&gt;典型应用：USB、RS-232、I²C、以太网（内部串行化）、SATA。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;并行通信&lt;/strong&gt;：数据在传输过程中，同时通过多条线路传输，一次可以传输多个比特。通常每条线路传输一个比特，多条线路同时传输数据。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优点：相同时钟频率下，数据吞吐量是串行的N倍（N为并行位数）。&lt;/li&gt;
&lt;li&gt;缺点：线路多，成本高；远距离时不同线路的信号到达时间可能不一致（时延偏移），限制传输距离和速率。&lt;/li&gt;
&lt;li&gt;典型应用：旧式打印机并口（Centronics）、IDE硬盘接口、芯片内部总线。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="同步和异步通信"&gt;同步和异步通信&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;异步通信&lt;/strong&gt;：收发双方时钟各自独立，以字符为单位传输，每个字符加起始位、停止位做同步。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;特点：
&lt;ul&gt;
&lt;li&gt;按字符逐个发送，字符之间的间隔不固定；&lt;/li&gt;
&lt;li&gt;无需统一的时钟信号，实现简单，成本低；&lt;/li&gt;
&lt;li&gt;每个字符需要额外的起始位和停止位（通常每8位数据需2-3位开销），传输效率较低；&lt;/li&gt;
&lt;li&gt;适用于低速、间歇性数据传输。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;例子：串口RS-232、键盘输入、鼠标通信。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;同步通信&lt;/strong&gt;：收发双方使用统一时钟信号（可由单独时钟线或从数据信号中提取），以数据块/帧为单位连续传输，不需每个字符加起止位。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;特点：
&lt;ul&gt;
&lt;li&gt;连续成块传输，数据块内比特间隔固定；&lt;/li&gt;
&lt;li&gt;收发双方时钟需严格同步（使用同步时钟或锁相环）；&lt;/li&gt;
&lt;li&gt;传输效率高，额外开销仅为帧头帧尾（如标志位或同步字符）；&lt;/li&gt;
&lt;li&gt;硬件复杂，适合高速、大块连续数据传输。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;例子：以太网、光纤通信（SONET/SDH）、USB高速模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="单工半双工和全双工通信"&gt;单工、半双工和全双工通信&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;单工通信&lt;/strong&gt;&lt;br&gt;
定义：信息只能单向传输，一方固定发送，一方固定接收，不能反向。&lt;br&gt;
例子：广播、电视、遥控器。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;半双工通信&lt;/strong&gt;&lt;br&gt;
定义：双方都能收发，但同一时刻只能单向，不能同时发和收。&lt;br&gt;
例子：对讲机、传统步话机、RS-485总线。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;全双工通信&lt;/strong&gt;&lt;br&gt;
定义：双方可同时发送和接收，双向互不干扰。&lt;br&gt;
例子：手机通话、以太网（使用独立收发线对）、微信语音通话。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="信号传输特性与信道容量"&gt;信号传输特性与信道容量&lt;/h2&gt;
&lt;p&gt;通过信号的傅里叶分析，本章解释了其传输过程存在的衰减、失真等现象，引入了截止频率、物理带宽的概念以及它们对信号传输的影响。&lt;/p&gt;
&lt;h3 id="傅里叶分析与信号失真"&gt;傅里叶分析与信号失真&lt;/h3&gt;
&lt;p&gt;任何周期信号都可以分解为一系列不同频率的正弦波（基波和谐波）的叠加。当信号通过实际信道时，不同频率分量会经历不同的衰减和相移，导致接收端波形发生畸变。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;幅度衰减&lt;/strong&gt;：高频分量衰减通常比低频分量更严重，导致信号边沿变缓。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;相位失真&lt;/strong&gt;：不同频率的传输延迟不同，造成码间干扰。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;信道带宽&lt;/strong&gt;：信道的截止频率范围，只有频率落在带宽内的分量才能被有效传输。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="信道带宽与截止频率"&gt;信道带宽与截止频率&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;物理带宽&lt;/strong&gt;：信道能够通过的最大频率与最小频率之差，单位为赫兹（Hz）。例如，话音信道带宽约为3.1 kHz（300 Hz～3.4 kHz）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;截止频率&lt;/strong&gt;：信号功率衰减超过某一阈值（通常为-3 dB）的频率点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;影响&lt;/strong&gt;：带宽越窄，可传输的高频分量越少，输出波形越接近“圆滑”，可能导致接收端无法区分相邻比特。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="信道容量奈奎斯特定理与香农定理"&gt;信道容量：奈奎斯特定理与香农定理&lt;/h3&gt;
&lt;p&gt;信道的物理带宽直接影响信道的传输性能，即它的传输速率，或者数字带宽。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;奈奎斯特定理（无噪声信道）&lt;/strong&gt;&lt;br&gt;
对于无噪声、带宽为 B 赫兹的理想信道，最大数据速率为：&lt;br&gt;
&lt;code&gt;最大数据速率 = 2B * log2(M)&lt;/code&gt;，其中 M 为信号电平数（如M=2，则速率为 2B bps）。&lt;br&gt;
该定理给出了在避免码间串扰条件下的理论上限。&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="物理层负责比特流的透明传输">物理层负责比特流的透明传输</h1>
<p>物理层是参考模型中的最底层，是最基础的一层。本章探讨传输比特所需要的介质和所使用的技术。</p>
<h2 id="通信-信道">通信 信道</h2>
<p><strong>物理层通信</strong>：利用物理传输介质，将计算机中的比特流（0、1）转换为电信号、光信号或电磁波信号，在物理链路上实现透明、原始的比特流传输，不负责数据含义与纠错，只负责信号的发送与接收。</p>
<p><strong>信道</strong>：在物理层中，传送信号的通路，是传输比特流的逻辑通道，包含传输介质和相关通信设备。</p>
<h3 id="模拟和数字通信">模拟和数字通信</h3>
<p>数字和模拟通信的区别在于使用数字信号还是模拟信号进行传递消息。</p>
<p><strong>模拟信号</strong>：代表信息的信号及其参数（幅度、频率或相位）随着消息连续变化的信号，它在幅度上连续，但在时间上可以连续也可以不连续。</p>
<ul>
<li>波形连续，具有无穷多个幅度取值；</li>
<li>易受干扰，噪声会累积且难以去除；</li>
<li>不易加密，不易存储和处理（需先数字化）；</li>
<li>典型例子：传统电话语音、模拟电视信号。</li>
</ul>
<p><strong>数字信号</strong>：不仅在时间上是离散的，而且在幅度上也是离散的信号，通常只取有限个离散值（如二进制信号取0和1）。</p>
<ul>
<li>波形离散，只传送0和1；</li>
<li>抗干扰能力强，噪声不会累积（可通过中继器再生）；</li>
<li>易加密、易存储、易纠错，与计算机系统天然兼容；</li>
<li>典型例子：以太网信号、USB信号、光纤通信信号。</li>
</ul>
<h3 id="并行和串行通信">并行和串行通信</h3>
<p><strong>串行通信</strong>：数据在传输过程中，逐位依次传输，一次只传输一个比特。数据通过单一的通信线路（如一根电线或一根光纤）按顺序发送和接收。</p>
<ul>
<li>优点：节省线路资源，线缆成本低；远距离传输时不易出现信号间干扰（串扰）。</li>
<li>缺点：传输速率相对较低（需通过提高时钟频率来提升速率）。</li>
<li>典型应用：USB、RS-232、I²C、以太网（内部串行化）、SATA。</li>
</ul>
<p><strong>并行通信</strong>：数据在传输过程中，同时通过多条线路传输，一次可以传输多个比特。通常每条线路传输一个比特，多条线路同时传输数据。</p>
<ul>
<li>优点：相同时钟频率下，数据吞吐量是串行的N倍（N为并行位数）。</li>
<li>缺点：线路多，成本高；远距离时不同线路的信号到达时间可能不一致（时延偏移），限制传输距离和速率。</li>
<li>典型应用：旧式打印机并口（Centronics）、IDE硬盘接口、芯片内部总线。</li>
</ul>
<h3 id="同步和异步通信">同步和异步通信</h3>
<p><strong>异步通信</strong>：收发双方时钟各自独立，以字符为单位传输，每个字符加起始位、停止位做同步。</p>
<ul>
<li>特点：
<ul>
<li>按字符逐个发送，字符之间的间隔不固定；</li>
<li>无需统一的时钟信号，实现简单，成本低；</li>
<li>每个字符需要额外的起始位和停止位（通常每8位数据需2-3位开销），传输效率较低；</li>
<li>适用于低速、间歇性数据传输。</li>
</ul>
</li>
<li>例子：串口RS-232、键盘输入、鼠标通信。</li>
</ul>
<p><strong>同步通信</strong>：收发双方使用统一时钟信号（可由单独时钟线或从数据信号中提取），以数据块/帧为单位连续传输，不需每个字符加起止位。</p>
<ul>
<li>特点：
<ul>
<li>连续成块传输，数据块内比特间隔固定；</li>
<li>收发双方时钟需严格同步（使用同步时钟或锁相环）；</li>
<li>传输效率高，额外开销仅为帧头帧尾（如标志位或同步字符）；</li>
<li>硬件复杂，适合高速、大块连续数据传输。</li>
</ul>
</li>
<li>例子：以太网、光纤通信（SONET/SDH）、USB高速模式。</li>
</ul>
<h3 id="单工半双工和全双工通信">单工、半双工和全双工通信</h3>
<ol>
<li>
<p><strong>单工通信</strong><br>
定义：信息只能单向传输，一方固定发送，一方固定接收，不能反向。<br>
例子：广播、电视、遥控器。</p>
</li>
<li>
<p><strong>半双工通信</strong><br>
定义：双方都能收发，但同一时刻只能单向，不能同时发和收。<br>
例子：对讲机、传统步话机、RS-485总线。</p>
</li>
<li>
<p><strong>全双工通信</strong><br>
定义：双方可同时发送和接收，双向互不干扰。<br>
例子：手机通话、以太网（使用独立收发线对）、微信语音通话。</p>
</li>
</ol>
<hr>
<h2 id="信号传输特性与信道容量">信号传输特性与信道容量</h2>
<p>通过信号的傅里叶分析，本章解释了其传输过程存在的衰减、失真等现象，引入了截止频率、物理带宽的概念以及它们对信号传输的影响。</p>
<h3 id="傅里叶分析与信号失真">傅里叶分析与信号失真</h3>
<p>任何周期信号都可以分解为一系列不同频率的正弦波（基波和谐波）的叠加。当信号通过实际信道时，不同频率分量会经历不同的衰减和相移，导致接收端波形发生畸变。</p>
<ul>
<li><strong>幅度衰减</strong>：高频分量衰减通常比低频分量更严重，导致信号边沿变缓。</li>
<li><strong>相位失真</strong>：不同频率的传输延迟不同，造成码间干扰。</li>
<li><strong>信道带宽</strong>：信道的截止频率范围，只有频率落在带宽内的分量才能被有效传输。</li>
</ul>
<h3 id="信道带宽与截止频率">信道带宽与截止频率</h3>
<ul>
<li><strong>物理带宽</strong>：信道能够通过的最大频率与最小频率之差，单位为赫兹（Hz）。例如，话音信道带宽约为3.1 kHz（300 Hz～3.4 kHz）。</li>
<li><strong>截止频率</strong>：信号功率衰减超过某一阈值（通常为-3 dB）的频率点。</li>
<li><strong>影响</strong>：带宽越窄，可传输的高频分量越少，输出波形越接近“圆滑”，可能导致接收端无法区分相邻比特。</li>
</ul>
<h3 id="信道容量奈奎斯特定理与香农定理">信道容量：奈奎斯特定理与香农定理</h3>
<p>信道的物理带宽直接影响信道的传输性能，即它的传输速率，或者数字带宽。</p>
<ul>
<li>
<p><strong>奈奎斯特定理（无噪声信道）</strong><br>
对于无噪声、带宽为 B 赫兹的理想信道，最大数据速率为：<br>
<code>最大数据速率 = 2B * log2(M)</code>，其中 M 为信号电平数（如M=2，则速率为 2B bps）。<br>
该定理给出了在避免码间串扰条件下的理论上限。</p>
</li>
<li>
<p><strong>香农定理（有噪声信道）</strong><br>
对于带宽为 B 赫兹、信噪比为 SNR（信号功率与噪声功率之比）的信道，最大数据速率为：<br>
<code>信道容量 C = B * log2(1 + SNR)</code>。<br>
该公式揭示了无论采用何种调制或编码技术，在有噪声信道中传输速率无法超过 C。信噪比常用分贝（dB）表示：<code>SNR(dB) = 10 * log10(SNR)</code>。</p>
</li>
</ul>
<hr>
<h2 id="基带传输技术">基带传输技术</h2>
<p>基带传输是指不经过载波调制，直接将原始数字信号（如曼彻斯特编码后的方波）在信道上传输。常见线路编码方法及其特点如下：</p>
<h3 id="1-nrz不归零编码">1. NRZ（不归零编码）</h3>
<ul>
<li><strong>原理</strong>：高电平表示1，低电平表示0（或相反）。</li>
<li><strong>优点</strong>：简单，占用带宽小。</li>
<li><strong>缺点</strong>：连续长串0或1时，接收端无法保持时钟同步；无法区分空闲和0信号。</li>
<li><strong>应用</strong>：早期低速串行链路，不单独用于现代高速网络。</li>
</ul>
<h3 id="2-nrzi不归零反相编码">2. NRZI（不归零反相编码）</h3>
<ul>
<li><strong>原理</strong>：电平在比特开始时反转表示1，不变表示0（或相反）。</li>
<li><strong>优点</strong>：解决了连续1的同步问题（因为每传1都会跳变）。</li>
<li><strong>缺点</strong>：连续长串0仍无跳变，同步仍会丢失。</li>
<li><strong>应用</strong>：USB 低速/全速模式。</li>
</ul>
<h3 id="3-曼彻斯特编码">3. 曼彻斯特编码</h3>
<ul>
<li><strong>原理</strong>：每个比特中间有一次电平跳变，从高到低表示1，从低到高表示0（或按IEEE 802.3标准：由高到低表示0，低到高表示1）。</li>
<li><strong>优点</strong>：每个比特都包含时钟跳变，自同步能力强；无直流分量。</li>
<li><strong>缺点</strong>：带宽效率低（有效数据率仅为信号波特率的一半）。</li>
<li><strong>应用</strong>：经典以太网（10BASE-T）。</li>
</ul>
<h3 id="4-4b5b-编码">4. 4B/5B 编码</h3>
<ul>
<li><strong>原理</strong>：每4位数据映射为5位编码组，保证编码序列中不会出现连续3个0；然后使用 NRZI 传输。</li>
<li><strong>优点</strong>：提高同步可靠性，带宽利用率（4/5 = 80%）高于曼彻斯特（50%）。</li>
<li><strong>缺点</strong>：需要查表映射，复杂度稍高。</li>
<li><strong>应用</strong>：快速以太网（100BASE-TX）、FDDI、USB 高速模式。</li>
</ul>
<hr>
<h2 id="通带传输技术">通带传输技术</h2>
<p>通带传输将数字信号通过调制加载到高频载波上，以适应带通信道（如无线电、同轴电缆）。常用的调制方法如下：</p>
<h3 id="基本调制方式">基本调制方式</h3>
<ul>
<li><strong>调幅（ASK）</strong>：载波幅度随数字信号变化（1有载波，0无载波）。易受幅度噪声干扰。</li>
<li><strong>调频（FSK）</strong>：载波频率随数字信号变化（1对应高频率，0对应低频率）。抗干扰能力强于ASK。</li>
<li><strong>调相（PSK）</strong>：载波相位随数字信号变化（例如0°表示0，180°表示1）。有较好的抗噪声性能。</li>
</ul>
<h3 id="正交幅度调制qam">正交幅度调制（QAM）</h3>
<p>QAM 是一种将 ASK 和 PSK 组合在一起的调制方式，可同时改变载波的幅度和相位，从而在一个符号周期内携带多个比特。</p>
<ul>
<li><strong>原理</strong>：使用两个正交载波（正弦和余弦），分别进行独立调制，然后叠加。每个符号可以表示 M 个不同的幅度-相位组合。</li>
<li><strong>星座图</strong>：每个点对应一个幅度和相位组合。例如 16-QAM 有16个点，每符号4比特；64-QAM 每符号6比特；256-QAM 每符号8比特。</li>
<li><strong>优缺点</strong>：频谱利用率高，但对线路信噪比要求更高（高阶QAM需要更高的SNR）。</li>
<li><strong>应用</strong>：WiFi（802.11ac 支持256-QAM）、4G/5G、数字电视（DVB-C）、有线宽带（DOCSIS 3.1支持4096-QAM）。</li>
</ul>
<p>不同级别的 QAM 正在各种计算机网络中起着非常重要的作用。</p>
<hr>
<h2 id="传输介质">传输介质</h2>
<p>传输介质分为导引性和非导引性两大类。</p>
<h3 id="导引性传输介质">导引性传输介质</h3>
<h4 id="双绞线">双绞线</h4>
<p>由两根绝缘铜导线相互绞合而成，绞合可减少电磁干扰。</p>
<ul>
<li><strong>屏蔽双绞线（STP）</strong>：外层有金属屏蔽层，抗干扰更好，但成本高、安装较硬。</li>
<li><strong>非屏蔽双绞线（UTP）</strong>：无屏蔽层，轻便、灵活，是局域网主流。</li>
<li><strong>分类</strong>：Cat5e（千兆）、Cat6（千兆/万兆短距）、Cat6a（万兆）、Cat7（屏蔽+万兆）。</li>
<li><strong>优点</strong>：成本低、布线灵活、连接方便（RJ45接口）。</li>
<li><strong>缺点</strong>：传输距离有限（最大100米），易受强电磁干扰。</li>
<li><strong>应用</strong>：以太网（10BASE-T ~ 10GBASE-T）、电话线、工业控制。</li>
</ul>
<h4 id="同轴电缆">同轴电缆</h4>
<p>中心铜导线、绝缘层、金属屏蔽层和外包层组成。</p>
<ul>
<li><strong>特性</strong>：抗干扰优于双绞线，带宽较宽（早期可达几百MHz），但比光纤笨重。</li>
<li><strong>类型</strong>：细缆（RG-58，阻抗50Ω，用于早期10BASE2以太网）、粗缆（RG-11，10BASE5）、视频电缆（RG-59，75Ω，用于有线电视）。</li>
<li><strong>应用</strong>：有线电视（CATV）、闭路监控、早期局域网（已淘汰）。</li>
</ul>
<h4 id="光纤">光纤</h4>
<p>利用光脉冲在玻璃或塑料纤维中全反射传输信号。</p>
<ul>
<li><strong>单模光纤</strong>：纤芯细（约9μm），只允许单一光模式传播，传输距离远（几十公里）、速率高（100Gbps+），使用激光源。</li>
<li><strong>多模光纤</strong>：纤芯粗（50μm或62.5μm），允许多种模式传播，存在模间色散，传输距离短（几百米至2公里），使用LED或VCSEL光源。</li>
<li><strong>优点</strong>：带宽极大（THz级别）、无电磁干扰、信号衰减极低、重量轻、保密性好（无辐射泄漏）。</li>
<li><strong>缺点</strong>：成本（尤其是单模光模块）、安装熔接需要专用工具、弯曲敏感。</li>
<li><strong>应用</strong>：网络主干线、数据中心互联、长距离骨干网（如海底光缆）、光纤到户（FTTH）。</li>
</ul>
<h3 id="非导引性传输介质">非导引性传输介质</h3>
<p>以空间电磁波为传输载体，无需物理线缆。</p>
<h4 id="无线电波">无线电波</h4>
<ul>
<li><strong>频率范围</strong>：3 Hz ~ 300 GHz（实际常用30 kHz ~ 3 GHz）</li>
<li><strong>特性</strong>：绕射能力强，可穿透建筑物，传播距离远（可达几十公里）。</li>
<li><strong>应用</strong>：广播（AM/FM）、移动通信（2G/3G/4G/5G部分频段）、WiFi（2.4 GHz）、蓝牙、物联网（LoRa、NB-IoT）。</li>
</ul>
<h4 id="微波">微波</h4>
<ul>
<li><strong>频率范围</strong>：约300 MHz ~ 300 GHz（通常指1 GHz以上，尤其2-40 GHz）</li>
<li><strong>特性</strong>：直线传播（视距），不能绕射；带宽高；受天气（雨衰）影响；需要抛物面天线对准。</li>
<li><strong>应用</strong>：点对点骨干链路、卫星通信（C/Ku/Ka波段）、WiFi（5 GHz）、4G/5G高频段（毫米波）。</li>
</ul>
<h4 id="红外线">红外线</h4>
<ul>
<li><strong>频率范围</strong>：约300 GHz ~ 400 THz</li>
<li><strong>特性</strong>：短距离（几米到几十米），需直视（不能穿透墙壁），不受无线电干扰。</li>
<li><strong>应用</strong>：遥控器（电视、空调）、近距离点对点通信（如IrDA）。</li>
</ul>
<h4 id="激光">激光</h4>
<ul>
<li><strong>特性</strong>：极高带宽（可达Gbps）、保密性强（波束窄，不易窃听）、直线传播，但受天气（雾、雨、雪）和大气扰动影响大。</li>
<li><strong>应用</strong>：楼宇间点对点无线通信（自由空间光通信 FSO），应急临时链路。</li>
</ul>
<hr>
<h2 id="用户接入技术">用户接入技术</h2>
<p>本章从物理层探讨了用户接入互联网的方式，从而引出了几种接入网络。以下为主要的接入网框架及技术。</p>
<h3 id="公共交换电话网络pstn接入">公共交换电话网络（PSTN）接入</h3>
<ul>
<li><strong>传统调制解调器（56K拨号）</strong>：利用话音信道（3.1 kHz带宽），通过V.90/V.92协议实现下行56 Kbps、上行33.6 Kbps。占用电话线，上网时无法通话。</li>
<li><strong>数字用户线路（xDSL）</strong>：在现有电话线上使用高频段传输数据，低频段保留话音。
<ul>
<li>ADSL（非对称）：下行可达8-24 Mbps，上行1-3.5 Mbps。</li>
<li>VDSL/VDSL2：下行可达100 Mbps以上，短距离内可对称。</li>
<li>需在局端和用户端分别安装DSLAM和调制解调器。</li>
</ul>
</li>
</ul>
<h3 id="蜂窝移动网络">蜂窝移动网络</h3>
<ul>
<li><strong>2G（GSM/CDMA）</strong>：最高约几百Kbps（GPRS/EDGE）。</li>
<li><strong>3G（UMTS/CDMA2000）</strong>：几Mbps，支持移动互联网初步应用。</li>
<li><strong>4G（LTE/LTE-Advanced）</strong>：下行百Mbps至1 Gbps，采用OFDM和MIMO技术，是全IP网络。</li>
<li><strong>5G（NR）</strong>：分低频（sub-6 GHz）和毫米波（24 GHz+），峰值速率可达10-20 Gbps，低时延（1 ms级），高连接密度。</li>
<li><strong>框架</strong>：终端 → 基站（gNB/eNB） → 核心网 → 互联网。</li>
</ul>
<h3 id="有线电视网络hfc">有线电视网络（HFC）</h3>
<ul>
<li><strong>混合光纤同轴网（HFC）</strong>：主干使用光纤，入户段使用同轴电缆。</li>
<li><strong>技术</strong>：DOCSIS（Data Over Cable Service Interface Specification）。DOCSIS 3.1 可提供下行10 Gbps、上行1-2 Gbps。</li>
<li><strong>特点</strong>：共享介质，下行通过广播、上行通过TDMA/SCDMA接入。需配合电缆调制解调器。</li>
</ul>
<h3 id="卫星通信网络">卫星通信网络</h3>
<ul>
<li><strong>传统卫星接入</strong>：使用地球静止轨道（GEO）卫星，覆盖广，但延迟高（约500-600 ms RTT）。</li>
<li><strong>低轨卫星星座</strong>：如Starlink（LEO，高度约550 km），延迟降至20-40 ms，带宽可达百Mbps甚至Gbps。</li>
<li><strong>应用场景</strong>：偏远地区、航海航空、应急通信、全球宽带覆盖。</li>
<li><strong>缺点</strong>：设备成本较高，受恶劣天气影响（雨衰）。</li>
</ul>
<p>以上接入技术正在不断融合，例如5G与光纤、卫星与地面网络互补，形成“天地一体化”网络，用户可实现按需接入、无缝切换。</p>
<hr>
<h2 id="物理层设备">物理层设备</h2>
<p>本章最后介绍物理层设备的功能、使用场景，并特别说明了光纤收发器和全光中继器的技术特点，以及冲突域等概念。</p>
<h3 id="中继器repeater与集线器hub">中继器（Repeater）与集线器（Hub）</h3>
<ul>
<li><strong>中继器</strong>：物理层设备，用于延长网络距离。它接收衰减和畸变的信号，进行再生、整形、放大，然后转发到另一端口。中继器不解析数据内容，只处理比特流。
<ul>
<li>作用：增加信号传输距离，克服介质衰减。</li>
<li>限制：不能连接不同速率的网络；不能隔离冲突域。</li>
</ul>
</li>
<li><strong>集线器（多端口中继器）</strong>：多个端口的中继器，一个端口收到信号后会向除接收口外的所有端口转发。所有端口共享同一冲突域。</li>
</ul>
<h3 id="冲突与冲突域">冲突与冲突域</h3>
<ul>
<li><strong>冲突</strong>：在共享介质型网络中，两个或多个节点同时发送数据时，信号在信道上叠加，导致接收端无法正确识别。</li>
<li><strong>冲突域</strong>：一组可能互相产生冲突的节点的集合。在集线器构建的网络中，所有节点位于同一个冲突域内。</li>
<li><strong>技术演变</strong>：由于冲突会大幅降低网络效率（尤其在节点多、流量大时），现代以太网使用<strong>交换式</strong>架构（交换机可隔离冲突域，每个端口为一个独立冲突域）或全双工模式（彻底消除冲突）。</li>
</ul>
<h3 id="电中继器和集线器的衰落">电中继器和集线器的衰落</h3>
<p>随着网络技术发展，电中继器和集线器逐渐消失，主要原因如下：</p>
<ol>
<li><strong>效率低下</strong>：共享带宽且冲突导致时延不确定性。</li>
<li><strong>扩展性差</strong>：级联受限（通常最多4个集线器，遵守5-4-3规则）。</li>
<li><strong>不支持全双工</strong>：无法同时收发，浪费链路能力。</li>
<li><strong>安全隐患</strong>：所有端口都能收到所有帧，易被嗅探。</li>
</ol>
<p>如今，集线器已被交换机（二层设备，但端口工作于物理层和MAC层）取代，仅在极少数调试或特定老旧系统中出现。</p>
<h3 id="光纤收发器">光纤收发器</h3>
<p>用于实现电信号（如RJ45以太网）与光信号（光纤）之间的转换，并完成媒体类型和接口的适配。</p>
<ul>
<li><strong>功能</strong>：将双绞线的电信号转换为光纤上的光信号（或反之），同时可能进行速率匹配和缓存。</li>
<li><strong>分类</strong>：
<ul>
<li>独立式外置收发器（用于连接不同介质设备）；</li>
<li>模块化收发器（如SFP、SFP+、QSFP等，可直接插入交换机或网卡）。</li>
</ul>
</li>
<li><strong>技术参数</strong>：支持速率（10/100/1000 Mbps、10G、25G、40G、100G+）、光纤类型（单模/多模）、波长（850 nm、1310 nm、1550 nm）、传输距离（几百米至120公里）。</li>
<li><strong>应用</strong>：升级旧网络到光纤、跨楼宇/跨园区连接、数据中心短距高速互联。</li>
</ul>
<h3 id="全光中继器">全光中继器</h3>
<p>用于长距离光纤传输，对光信号进行再生或放大，无需将光信号转换为电信号再处理。</p>
<ul>
<li><strong>传统光电光中继器（O-E-O）</strong>：光→电→再生整形→光，可重构帧但延迟大、功耗高、成本高。</li>
<li><strong>全光中继器（光放大器）</strong>：如EDFA（掺铒光纤放大器），在光域直接放大信号，透明、低延迟、高带宽。</li>
<li><strong>技术特点</strong>：
<ul>
<li>支持波分复用（WDM）所有波长同时放大；</li>
<li>不能消除色散引起的波形失真（需配合色散补偿模块）；</li>
<li>需避免放大器自发辐射（ASE）噪声积累。</li>
</ul>
</li>
<li><strong>应用场景</strong>：海底光缆、长途骨干网、数据中心间长距直连。</li>
</ul>
<hr>
<p><a href="/pdf/02-%E7%89%A9%E7%90%86%E5%B1%82%EF%BC%88%E5%85%A8%EF%BC%89.pdf">物理层</a></p>
]]></content:encoded></item><item><title>计算机网络概述</title><link>https://farmer3-c.github.io/posts/computer-networks/cw/</link><pubDate>Wed, 27 Aug 2025 19:40:32 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/cw/</guid><description>&lt;h3 id="计算机网络在信息时代的作用"&gt;计算机网络在信息时代的作用&lt;/h3&gt;
&lt;p&gt;计算机网络已经成为信息社会的核心基础设施。它使得人们可以随时随地访问、处理和交换信息，极大地促进了数字化、网络化和智能化的发展。具体作用包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;信息共享&lt;/strong&gt;：用户可以通过网络访问分布在世界各地的信息资源（网页、数据库、文件等）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通信协同&lt;/strong&gt;：电子邮件、即时消息、视频会议等应用支持人与人、人与机器之间的高效协作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;远程访问&lt;/strong&gt;：支持远程办公、在线教育、远程医疗等，打破了地理限制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;电子商务与金融&lt;/strong&gt;：网络支付、网上银行、在线购物等改变了传统商业模式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;娱乐与媒体&lt;/strong&gt;：流媒体、社交网络、在线游戏等丰富了人们的文化生活。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="互联网概述"&gt;互联网概述&lt;/h3&gt;
&lt;h4 id="网络的网络"&gt;网络的网络&lt;/h4&gt;
&lt;p&gt;互联网是由众多计算机网络（局域网、城域网、广域网）通过路由器互联而成的“网络的网络”。其两大基本特点是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;连通性&lt;/strong&gt;：任何接入互联网的用户（终端）之间都可以相互交换数据，仿佛彼此直接相连一样。这种连通性不受物理距离的限制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;共享性&lt;/strong&gt;：指资源共享，包括信息（网页、文件）、软件（在线服务、云应用）和硬件（如远程打印机、算力资源）。共享使得资源利用率大幅提升，降低了成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="picture1" loading="lazy" src="https://farmer3-c.github.io/img/in-post/copn1.png"&gt;
&lt;img alt="picture2" loading="lazy" src="https://farmer3-c.github.io/img/in-post/copn2.png"&gt;&lt;/p&gt;
&lt;h4 id="互联网基础结构发展三个阶段"&gt;互联网基础结构发展三个阶段&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;第一阶段（1969–1990）：ARPANET 到互联网雏形&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1969 年美国国防部建立 ARPANET，最初只有 4 个节点。&lt;/li&gt;
&lt;li&gt;20 世纪 70 年代提出 TCP/IP 协议体系。&lt;/li&gt;
&lt;li&gt;1983 年 ARPANET 全面采用 TCP/IP，标志着现代互联网的诞生。&lt;/li&gt;
&lt;li&gt;80 年代中期美国国家科学基金会建立 NSFNET，成为主干网。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;第二阶段（1990–2000）：商业化与万维网兴起&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1990 年 ARPANET 停止运行，NSFNET 成为骨干。&lt;/li&gt;
&lt;li&gt;1991 年万维网（WWW）公开，浏览器出现，互联网向公众开放。&lt;/li&gt;
&lt;li&gt;1995 年 NSFNET 退役，互联网完全由商业 ISP 运营，进入爆炸式增长。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;第三阶段（2000 至今）：移动互联网、物联网与高速宽带&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;光纤到户、4G/5G 移动通信普及。&lt;/li&gt;
&lt;li&gt;智能终端、云计算、社交网络、流媒体成为主流。&lt;/li&gt;
&lt;li&gt;物联网（IoT）将数十亿设备接入互联网，进入“万物互联”时代。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="互联网的标准化工作"&gt;互联网的标准化工作&lt;/h4&gt;
&lt;p&gt;互联网的标准化由 &lt;strong&gt;IETF（互联网工程任务组）&lt;/strong&gt; 等组织负责，遵循“ rough consensus and running code” 原则。主要成果以 &lt;strong&gt;RFC（Request For Comments）&lt;/strong&gt; 文档形式发布。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Internet Standard&lt;/strong&gt;：经过充分验证的正式标准（如 RFC 791 – IP、RFC 793 – TCP）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proposed Standard / Draft Standard&lt;/strong&gt;：处于不同成熟度的草案。&lt;/li&gt;
&lt;li&gt;此外还有 &lt;strong&gt;BCP（Best Current Practice）&lt;/strong&gt;、&lt;strong&gt;Informational&lt;/strong&gt; 等类型。&lt;/li&gt;
&lt;li&gt;标准化过程公开透明，任何人均可提交提案，保证了互联网的开放性和快速演进。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="互联网的组成"&gt;互联网的组成&lt;/h3&gt;
&lt;p&gt;互联网从物理结构上由以下四类元素构成：&lt;/p&gt;</description><content:encoded><![CDATA[<h3 id="计算机网络在信息时代的作用">计算机网络在信息时代的作用</h3>
<p>计算机网络已经成为信息社会的核心基础设施。它使得人们可以随时随地访问、处理和交换信息，极大地促进了数字化、网络化和智能化的发展。具体作用包括：</p>
<ul>
<li><strong>信息共享</strong>：用户可以通过网络访问分布在世界各地的信息资源（网页、数据库、文件等）。</li>
<li><strong>通信协同</strong>：电子邮件、即时消息、视频会议等应用支持人与人、人与机器之间的高效协作。</li>
<li><strong>远程访问</strong>：支持远程办公、在线教育、远程医疗等，打破了地理限制。</li>
<li><strong>电子商务与金融</strong>：网络支付、网上银行、在线购物等改变了传统商业模式。</li>
<li><strong>娱乐与媒体</strong>：流媒体、社交网络、在线游戏等丰富了人们的文化生活。</li>
</ul>
<h3 id="互联网概述">互联网概述</h3>
<h4 id="网络的网络">网络的网络</h4>
<p>互联网是由众多计算机网络（局域网、城域网、广域网）通过路由器互联而成的“网络的网络”。其两大基本特点是：</p>
<ul>
<li><strong>连通性</strong>：任何接入互联网的用户（终端）之间都可以相互交换数据，仿佛彼此直接相连一样。这种连通性不受物理距离的限制。</li>
<li><strong>共享性</strong>：指资源共享，包括信息（网页、文件）、软件（在线服务、云应用）和硬件（如远程打印机、算力资源）。共享使得资源利用率大幅提升，降低了成本。</li>
</ul>
<p><img alt="picture1" loading="lazy" src="/img/in-post/copn1.png">
<img alt="picture2" loading="lazy" src="/img/in-post/copn2.png"></p>
<h4 id="互联网基础结构发展三个阶段">互联网基础结构发展三个阶段</h4>
<ol>
<li>
<p><strong>第一阶段（1969–1990）：ARPANET 到互联网雏形</strong></p>
<ul>
<li>1969 年美国国防部建立 ARPANET，最初只有 4 个节点。</li>
<li>20 世纪 70 年代提出 TCP/IP 协议体系。</li>
<li>1983 年 ARPANET 全面采用 TCP/IP，标志着现代互联网的诞生。</li>
<li>80 年代中期美国国家科学基金会建立 NSFNET，成为主干网。</li>
</ul>
</li>
<li>
<p><strong>第二阶段（1990–2000）：商业化与万维网兴起</strong></p>
<ul>
<li>1990 年 ARPANET 停止运行，NSFNET 成为骨干。</li>
<li>1991 年万维网（WWW）公开，浏览器出现，互联网向公众开放。</li>
<li>1995 年 NSFNET 退役，互联网完全由商业 ISP 运营，进入爆炸式增长。</li>
</ul>
</li>
<li>
<p><strong>第三阶段（2000 至今）：移动互联网、物联网与高速宽带</strong></p>
<ul>
<li>光纤到户、4G/5G 移动通信普及。</li>
<li>智能终端、云计算、社交网络、流媒体成为主流。</li>
<li>物联网（IoT）将数十亿设备接入互联网，进入“万物互联”时代。</li>
</ul>
</li>
</ol>
<h4 id="互联网的标准化工作">互联网的标准化工作</h4>
<p>互联网的标准化由 <strong>IETF（互联网工程任务组）</strong> 等组织负责，遵循“ rough consensus and running code” 原则。主要成果以 <strong>RFC（Request For Comments）</strong> 文档形式发布。</p>
<ul>
<li><strong>Internet Standard</strong>：经过充分验证的正式标准（如 RFC 791 – IP、RFC 793 – TCP）。</li>
<li><strong>Proposed Standard / Draft Standard</strong>：处于不同成熟度的草案。</li>
<li>此外还有 <strong>BCP（Best Current Practice）</strong>、<strong>Informational</strong> 等类型。</li>
<li>标准化过程公开透明，任何人均可提交提案，保证了互联网的开放性和快速演进。</li>
</ul>
<h3 id="互联网的组成">互联网的组成</h3>
<p>互联网从物理结构上由以下四类元素构成：</p>
<ul>
<li><strong>主机（hosts）</strong>：包括个人电脑、服务器、智能手机、物联网设备等，位于互联网边缘，运行各种网络应用。</li>
<li><strong>交换设备</strong>：如交换机（链路层）和路由器（网络层），负责转发数据包，决定数据的传输路径。</li>
<li><strong>通信链路</strong>：光纤、双绞线、同轴电缆、无线电波、卫星链路等，提供比特流传输的物理介质。</li>
<li><strong>协议软件</strong>：TCP/IP 等协议栈，定义了数据如何封装、寻址、传输和解析。</li>
</ul>
<h4 id="边缘部分">边缘部分</h4>
<p>由所有连接在互联网上的主机组成，用户直接使用这些主机进行通信和资源共享。这些主机又称为<strong>端系统（end system）</strong>。</p>
<ul>
<li><strong>端系统</strong>可以是客户端（如 PC、手机）或服务器（如 Web 服务器、邮件服务器）。</li>
<li>边缘部分的主要通信方式有两种（见下文）。</li>
</ul>
<p><img alt="picture3" loading="lazy" src="/img/in-post/copn3.png">
<img alt="picture5" loading="lazy" src="/img/in-post/copn5.png"></p>
<h5 id="通信方式">通信方式</h5>
<ul>
<li>
<p><strong>客户-服务器方式（C/S 方式）</strong><br>
即 Client/Server 方式。服务器长期运行，被动等待请求；客户主动发起通信，获得服务后结束。特例是浏览器/服务器方式（B/S 方式），浏览器作为通用客户端访问 Web 服务器。<br>
特点：服务器需要高带宽和强处理能力；客户之间不直接通信。</p>
</li>
<li>
<p><strong>对等方式（P2P 方式）</strong><br>
即 Peer-to-Peer 方式。每个节点既是客户也是服务器，直接共享资源（文件、带宽、算力）。<br>
特点：可扩展性好，无需中心服务器；常用于文件共享（BitTorrent）、区块链、视频会议（WebRTC）等。</p>
</li>
</ul>
<h4 id="核心部分">核心部分</h4>
<p>由大量网络和连接这些网络的路由器组成，为边缘部分提供连通性和交换服务。</p>
<ul>
<li><strong>路由器</strong>：核心设备，负责分组存储转发，依据路由表选择最佳路径。</li>
<li><strong>核心网络</strong>：通常采用高带宽光纤链路，运行复杂的路由协议（如 OSPF、BGP），保证全球范围的数据传输。</li>
</ul>
<p><img alt="picture4" loading="lazy" src="/img/in-post/copn4.png"></p>
<h3 id="计算机网络在我国的发展">计算机网络在我国的发展</h3>
<ul>
<li><strong>起步（1980s–1994）</strong>：1987 年发出第一封国际电子邮件；1994 年全功能接入 Internet。</li>
<li><strong>加速（1995–2000）</strong>：中国公用计算机互联网（CHINANET）建成，互联网服务开始民用。</li>
<li><strong>普及（2001–2010）</strong>：宽带接入普及，网民数量激增，电子商务、社交网络兴起。</li>
<li><strong>领先（2011 至今）</strong>：4G/5G 网络大规模覆盖，光纤宽带用户数世界第一，IPv6 部署迅速，移动支付和物联网应用全球领先。</li>
</ul>
<h3 id="计算机网络的类别">计算机网络的类别</h3>
<h4 id="定义">定义</h4>
<p>计算机网络是由通信链路连接的、具有独立功能的计算机系统集合，遵循协议实现资源共享和信息交换。</p>
<h4 id="几种类别">几种类别</h4>
<p>按覆盖范围分类：</p>
<ul>
<li><strong>个人区域网（PAN）</strong>：范围约 10 米，如蓝牙、USB 连接个人设备。</li>
<li><strong>局域网（LAN）</strong>：覆盖一栋楼或一个园区，典型技术为以太网、Wi-Fi。</li>
<li><strong>城域网（MAN）</strong>：覆盖一个城市，常用技术如以太网汇聚、有线电视网。</li>
<li><strong>广域网（WAN）</strong>：跨越国家或大陆，如 Internet 骨干网、运营商核心网。</li>
</ul>
<p>按拓扑结构分类：总线型、星型、环型、网状型等。<br>
按交换方式分类：电路交换、报文交换、分组交换。<br>
按使用范围分类：公用网（Internet）、专用网（企业内部网、金融专网）。</p>
<h3 id="计算机网络的性能">计算机网络的性能</h3>
<h4 id="性能指标">性能指标</h4>
<ul>
<li><strong>速率</strong>：数据率（data rate）或比特率（bit rate），单位 b/s（bps），常用 kb/s, Mb/s, Gb/s 等。文献中的网络速率一般指额定/标称速率，即设备能够达到的最高速率，而非实际运行的速率。</li>
<li><strong>额定/标称速率</strong>：由于在每一帧被传送的数据量中还包括同步码、纠错码等辅助成分，实际有效数据传输速率会低于标称速率。</li>
<li><strong>有效速率</strong>：在标称速率中扣除辅助成分后，为理想信号条件下传送数据的理论最高速率。</li>
<li><strong>包转发率（Packet Per Second, PPS）</strong>：网络设备（如交换机、路由器）以包为单位的转发速率。线速转发指交换机端口在满负载下能够达到的最高速度（即端口带宽除以最小包长对应的包转发率）。</li>
</ul>
<p>其他重要性能指标：</p>
<ul>
<li><strong>带宽</strong>：模拟信号中指频率范围（Hz）；数字通信中指最大数据速率（b/s）。</li>
<li><strong>吞吐量</strong>：实际网络中端到端的传输速率，受拥塞、丢包等影响。</li>
<li><strong>时延</strong>：包括发送时延、传播时延、处理时延和排队时延。</li>
<li><strong>时延带宽积</strong>：传播时延 × 带宽，表示链路中正在传输的比特数量。</li>
<li><strong>丢包率</strong>：分组在传输过程中丢失的比例。</li>
<li><strong>往返时间（RTT）</strong>：从发送端发出数据到收到确认的时间间隔。</li>
</ul>
<h4 id="非性能特征">非性能特征</h4>
<ul>
<li><strong>可靠性</strong>：系统连续无故障运行的能力，常用平均故障间隔时间（MTBF）衡量。</li>
<li><strong>可扩展性</strong>：网络规模扩大时，性能和服务质量能否保持。</li>
<li><strong>可管理性</strong>：网络监控、配置、故障排除的难易程度。</li>
<li><strong>标准化程度</strong>：是否符合国际标准（IEEE、IETF、ITU-T）。</li>
<li><strong>成本</strong>：包括建设、运营、维护费用。</li>
</ul>
<h3 id="计算机网络体系结构">计算机网络体系结构</h3>
<h4 id="形成">形成</h4>
<p>为了降低网络设计的复杂性，采用分层体系结构。每层完成特定功能，下层为上层提供服务，层间通过接口交互。国际标准化组织（ISO）于 1984 年提出了 OSI 七层参考模型（物理层、数据链路层、网络层、传输层、会话层、表示层、应用层），但因实现复杂未被广泛采用。实际使用中，TCP/IP 四层模型成为事实标准。</p>
<h4 id="协议与划分层次">协议与划分层次</h4>
<ul>
<li><strong>协议</strong>：控制两个对等实体通信的规则集合，包括语法（格式）、语义（含义）、同步（时序）。</li>
<li><strong>分层原则</strong>：每一层独立完成特定功能；层间变化不影响其它层；提供标准化的服务接口。</li>
</ul>
<h4 id="具有五层协议的体系结构">具有五层协议的体系结构</h4>
<p>综合 OSI 和 TCP/IP，教学中常采用五层模型：</p>
<ol>
<li><strong>物理层</strong>：传输比特流，定义电压、接口、介质等。</li>
<li><strong>数据链路层</strong>：在相邻节点间可靠传输帧，处理差错控制和流量控制。</li>
<li><strong>网络层</strong>：负责分组从源到目的地的路由选择和转发（IP 协议）。</li>
<li><strong>传输层</strong>：提供端到端的可靠（TCP）或不可靠（UDP）数据传输。</li>
<li><strong>应用层</strong>：为用户应用提供协议支持（HTTP、SMTP、FTP 等）。</li>
</ol>
<h4 id="实体协议服务和服务访问点">实体、协议、服务和服务访问点</h4>
<ul>
<li><strong>实体</strong>：每一层中的活动元素（如进程、硬件模块），可以发送或接收信息。</li>
<li><strong>协议</strong>：同一层不同系统上的实体之间通信的规则。</li>
<li><strong>服务</strong>：下层为上层提供的一组操作，上层通过 <strong>服务访问点（SAP）</strong> 访问下层服务。例如传输层的 SAP 就是端口号。</li>
</ul>
<h4 id="tcpip-的体系结构">TCP/IP 的体系结构</h4>
<p>TCP/IP 协议栈包括四层（应用层、传输层、互联网层、网络接口层），并不严格区分物理层和数据链路层。其核心协议：</p>
<ul>
<li><strong>IP</strong>（互联网协议）：提供无连接、不可靠的分组交付。</li>
<li><strong>TCP</strong>（传输控制协议）：面向连接、可靠、有序的字节流传输。</li>
<li><strong>UDP</strong>（用户数据报协议）：无连接、不可靠但高效的数据报传输。</li>
</ul>
<p>TCP/IP 体系结构采用沙漏模型：IP 位于中央，支持多种上层协议和多种底层网络技术。</p>
<hr>
<ul>
<li><a href="/pdf/01-%E7%BB%AA%E8%AE%BA.pdf">绪论</a></li>
<li><a href="https://www.internetsociety.org/internet/history-internet/brief-history-internet/">A Brief History of the Internet</a></li>
</ul>
]]></content:encoded></item><item><title>计算机网络</title><link>https://farmer3-c.github.io/posts/computer-networks/post-2025-08-27/</link><pubDate>Wed, 27 Aug 2025 19:08:07 +0800</pubDate><guid>https://farmer3-c.github.io/posts/computer-networks/post-2025-08-27/</guid><description>Computer Networks</description><content:encoded><![CDATA[<h1 id="计算机网络">计算机网络</h1>
<ul>
<li><a href="/2025/08/27/cw/">概述</a></li>
<li><a href="/2025/08/27/1/">物理层</a></li>
<li><a href="/2025/08/27/2/">链路层</a></li>
<li><a href="/2025/08/27/4/">网络层</a></li>
<li><a href="/2025/08/27/3/">传输层</a></li>
<li><a href="/2025/08/27/5/">应用层</a></li>
</ul>
<h1 id="参考">参考</h1>
<hr>
<ul>
<li>计算机网络, 谢希仁</li>
<li><a href="https://github.com/CyC2018/CS-Notes/tree/master">CS-Notes</a></li>
<li><a href="https://textbook.cs168.io/">book</a></li>
</ul>
]]></content:encoded></item><item><title/><link>https://farmer3-c.github.io/posts/latex/latex/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://farmer3-c.github.io/posts/latex/latex/</guid><description>&lt;h2 id="mathjax-true"&gt;﻿&amp;mdash;
layout: post
title: &amp;ldquo;latex常用手册&amp;rdquo;
subtitle: &amp;ldquo;latex&amp;rdquo;
date: 2025-09-06 19:57:11 +0800
author: &amp;ldquo;farmer3-c&amp;rdquo;
header-img: &amp;ldquo;img/post-bg-2015.jpg&amp;rdquo;
tags: [latex]
mathjax: true&lt;/h2&gt;
&lt;h2 id="常用符号与表达式"&gt;常用符号与表达式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;根式：$\sqrt[n]{x}$&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-latex" data-lang="latex"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;\sqrt&lt;/span&gt;&lt;span class="na"&gt;[n]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;x&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分数：$\frac{x}{y}$&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-latex" data-lang="latex"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;\frac&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;x&lt;span class="nb"&gt;}{&lt;/span&gt;y&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;上下标：$x_i^2, a_{ij}^{kl}, \Gamma_{n}^{k}$&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-latex" data-lang="latex"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x&lt;span class="nb"&gt;_&lt;/span&gt;i&lt;span class="nb"&gt;^&lt;/span&gt;2, a&lt;span class="nb"&gt;_{&lt;/span&gt;ij&lt;span class="nb"&gt;}^{&lt;/span&gt;kl&lt;span class="nb"&gt;}&lt;/span&gt;, &lt;span class="k"&gt;\Gamma&lt;/span&gt;&lt;span class="nb"&gt;_{&lt;/span&gt;n&lt;span class="nb"&gt;}^{&lt;/span&gt;k&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;文本：$\textit{f}_a^b$&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-latex" data-lang="latex"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;\textit&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;f&lt;span class="nb"&gt;}_&lt;/span&gt;a&lt;span class="nb"&gt;^&lt;/span&gt;b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;算子与常见符号：$\nabla, \Delta, \mathrm{i}, \approx, \overline{A}$&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-latex" data-lang="latex"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;\nabla&lt;/span&gt;, &lt;span class="k"&gt;\Delta&lt;/span&gt;, &lt;span class="k"&gt;\mathrm&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;i&lt;span class="nb"&gt;}&lt;/span&gt;, &lt;span class="k"&gt;\approx&lt;/span&gt;, &lt;span class="k"&gt;\overline&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;A&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;希腊字母：$\alpha, \beta, \gamma, \eta, \xi, \phi, \psi, \omega, \theta, \lambda$&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-latex" data-lang="latex"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;\alpha&lt;/span&gt;, &lt;span class="k"&gt;\beta&lt;/span&gt;, &lt;span class="k"&gt;\gamma&lt;/span&gt;, &lt;span class="k"&gt;\eta&lt;/span&gt;, &lt;span class="k"&gt;\xi&lt;/span&gt;, &lt;span class="k"&gt;\phi&lt;/span&gt;, &lt;span class="k"&gt;\psi&lt;/span&gt;, &lt;span class="k"&gt;\omega&lt;/span&gt;, &lt;span class="k"&gt;\theta&lt;/span&gt;, &lt;span class="k"&gt;\lambda&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;向量与矩阵运算：$\mathbf{a} \times \mathbf{b},\ \mathbf{A + B = C}$&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="mathjax-true">﻿&mdash;
layout: post
title: &ldquo;latex常用手册&rdquo;
subtitle: &ldquo;latex&rdquo;
date: 2025-09-06 19:57:11 +0800
author: &ldquo;farmer3-c&rdquo;
header-img: &ldquo;img/post-bg-2015.jpg&rdquo;
tags: [latex]
mathjax: true</h2>
<h2 id="常用符号与表达式">常用符号与表达式</h2>
<ul>
<li>
<p>根式：$\sqrt[n]{x}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\sqrt</span><span class="na">[n]</span><span class="nb">{</span>x<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>分数：$\frac{x}{y}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\frac</span><span class="nb">{</span>x<span class="nb">}{</span>y<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>上下标：$x_i^2, a_{ij}^{kl}, \Gamma_{n}^{k}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">x<span class="nb">_</span>i<span class="nb">^</span>2, a<span class="nb">_{</span>ij<span class="nb">}^{</span>kl<span class="nb">}</span>, <span class="k">\Gamma</span><span class="nb">_{</span>n<span class="nb">}^{</span>k<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>文本：$\textit{f}_a^b$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\textit</span><span class="nb">{</span>f<span class="nb">}_</span>a<span class="nb">^</span>b
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>算子与常见符号：$\nabla, \Delta, \mathrm{i}, \approx, \overline{A}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\nabla</span>, <span class="k">\Delta</span>, <span class="k">\mathrm</span><span class="nb">{</span>i<span class="nb">}</span>, <span class="k">\approx</span>, <span class="k">\overline</span><span class="nb">{</span>A<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>希腊字母：$\alpha, \beta, \gamma, \eta, \xi, \phi, \psi, \omega, \theta, \lambda$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\alpha</span>, <span class="k">\beta</span>, <span class="k">\gamma</span>, <span class="k">\eta</span>, <span class="k">\xi</span>, <span class="k">\phi</span>, <span class="k">\psi</span>, <span class="k">\omega</span>, <span class="k">\theta</span>, <span class="k">\lambda</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>向量与矩阵运算：$\mathbf{a} \times \mathbf{b},\ \mathbf{A + B = C}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\mathbf</span><span class="nb">{</span>a<span class="nb">}</span> <span class="k">\times</span> <span class="k">\mathbf</span><span class="nb">{</span>b<span class="nb">}</span>
</span></span><span class="line"><span class="cl"><span class="k">\mathbf</span><span class="nb">{</span>A + B = C<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="关系与逻辑">关系与逻辑</h2>
<ul>
<li>
<p>不等式：$a \le b,\ a \ge b,\ a \neq b,\ a \ll b,\ a \gg b$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">a <span class="k">\le</span> b,<span class="k">\ </span>a <span class="k">\ge</span> b,<span class="k">\ </span>a <span class="k">\neq</span> b,<span class="k">\ </span>a <span class="k">\ll</span> b,<span class="k">\ </span>a <span class="k">\gg</span> b
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>蕴含与等价：$p \implies q,\ p \iff q$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">p <span class="k">\implies</span> q,<span class="k">\ </span>p <span class="k">\iff</span> q
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>逻辑运算：$p \land q,\ p \lor q$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">p <span class="k">\land</span> q,<span class="k">\ </span>p <span class="k">\lor</span> q
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>全称与存在：$\forall x,\ \exists x$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\forall</span> x,<span class="k">\ \exists</span> x
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>无穷：$\infty$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\infty</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="集合与算子">集合与算子</h2>
<ul>
<li>
<p>集合表示：$A = \{ x \mid x > 0 \}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">A = <span class="k">\{</span> x <span class="k">\mid</span> x &gt; 0 <span class="k">\}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>元素关系：$a \in A,\ b \notin A$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">a <span class="k">\in</span> A,<span class="k">\ </span>b <span class="k">\notin</span> A
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>包含关系：$A \subset B,\ A \subsetneq B,\ B \supset A$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">A <span class="k">\subset</span> B,<span class="k">\ </span>A <span class="k">\subsetneq</span> B,<span class="k">\ </span>B <span class="k">\supset</span> A
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>常见集合：$\mathbb{R}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\mathbb</span><span class="nb">{</span>R<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="矩阵与行列式">矩阵与行列式</h2>
<ul>
<li>
<p>基本矩阵：
</p>
$$
  \begin{matrix}
  a & b & c \\
  d & e & f \\
  g & h & i
  \end{matrix}
  $$</li>
<li>
<p>常用矩阵环境：</p>
<ul>
<li><code>matrix</code>：无括号</li>
<li><code>pmatrix</code>：圆括号</li>
<li><code>bmatrix</code>：方括号</li>
<li><code>Bmatrix</code>：花括号</li>
<li><code>vmatrix</code>：行列式竖线</li>
<li><code>Vmatrix</code>：双竖线</li>
</ul>
</li>
<li>
<p>雅可比行列式：
</p>
$$
  \frac{\partial (f,g)}{\partial (x,y)} =
  \begin{vmatrix}
  \frac{\partial f}{\partial x} & \frac{\partial f}{\partial y} \\
  \frac{\partial g}{\partial x} & \frac{\partial g}{\partial y}
  \end{vmatrix}
  $$<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> (f,g)<span class="nb">}{</span><span class="k">\partial</span> (x,y)<span class="nb">}</span> =
</span></span><span class="line"><span class="cl"><span class="k">\begin</span><span class="nb">{</span>vmatrix<span class="nb">}</span>
</span></span><span class="line"><span class="cl"><span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> f<span class="nb">}{</span><span class="k">\partial</span> x<span class="nb">}</span> <span class="nb">&amp;</span> <span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> f<span class="nb">}{</span><span class="k">\partial</span> y<span class="nb">}</span> <span class="k">\\</span>
</span></span><span class="line"><span class="cl"><span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> g<span class="nb">}{</span><span class="k">\partial</span> x<span class="nb">}</span> <span class="nb">&amp;</span> <span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> g<span class="nb">}{</span><span class="k">\partial</span> y<span class="nb">}</span>
</span></span><span class="line"><span class="cl"><span class="k">\end</span><span class="nb">{</span>vmatrix<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="微积分与导数">微积分与导数</h2>
<ul>
<li>
<p>定积分：$\int_{a}^{b} f(x) \, dx$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\int</span><span class="nb">_{</span>a<span class="nb">}^{</span>b<span class="nb">}</span> f(x) <span class="k">\,</span> dx
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>极限：$\lim_{x \to 0} f(x)$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\lim</span><span class="nb">_{</span>x <span class="k">\to</span> 0<span class="nb">}</span> f(x)
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>偏导数：$\frac{\partial f}{\partial x},\ \frac{\partial^2 f}{\partial x \partial y}$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> f<span class="nb">}{</span><span class="k">\partial</span> x<span class="nb">}</span>,<span class="k">\ \frac</span><span class="nb">{</span><span class="k">\partial</span><span class="nb">^</span>2 f<span class="nb">}{</span><span class="k">\partial</span> x <span class="k">\partial</span> y<span class="nb">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="分段函数与条件表达">分段函数与条件表达</h2>
$$
f(x)=
\begin{cases}
 x^2,      & x>0 \\
 0,        & x=0 \\
 -x^2,     & x<0
\end{cases}
$$<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb">f</span><span class="o">(</span><span class="nb">x</span><span class="o">)=</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\begin</span><span class="nb">{cases}
</span></span></span><span class="line"><span class="cl"><span class="nb"> x^</span><span class="m">2</span><span class="nb">,      &amp; x&gt;</span><span class="m">0</span><span class="nb"> </span><span class="nv">\\</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb"> </span><span class="m">0</span><span class="nb">,        &amp; x</span><span class="o">=</span><span class="m">0</span><span class="nb"> </span><span class="nv">\\</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nb"> </span><span class="o">-</span><span class="nb">x^</span><span class="m">2</span><span class="nb">,     &amp; x&lt;</span><span class="m">0</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\end</span><span class="nb">{cases}
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p>带条件的箭头：$A \xrightarrow[\text{下方条件}]{\text{上方条件}} B$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl">A <span class="k">\xrightarrow</span><span class="na">[\text{下方条件}]</span><span class="nb">{</span><span class="k">\text</span><span class="nb">{</span>上方条件<span class="nb">}}</span> B
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="优化与极值">优化与极值</h2>
<ul>
<li>
<p>目标函数：
</p>
$$
  \min_{\substack{x_1, x_2}} \left( x_1 + x_2 + P(x_1^2 + x_2^2 - 1) \right)
  $$<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="sb">$$</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="nv">\min</span><span class="nb">_{</span><span class="nv">\substack</span><span class="nb">{x_</span><span class="m">1</span><span class="nb">, x_</span><span class="m">2</span><span class="nb">}} </span><span class="nv">\left</span><span class="o">(</span><span class="nb"> x_</span><span class="m">1</span><span class="nb"> </span><span class="o">+</span><span class="nb"> x_</span><span class="m">2</span><span class="nb"> </span><span class="o">+</span><span class="nb"> P</span><span class="o">(</span><span class="nb">x_</span><span class="m">1</span><span class="nb">^</span><span class="m">2</span><span class="nb"> </span><span class="o">+</span><span class="nb"> x_</span><span class="m">2</span><span class="nb">^</span><span class="m">2</span><span class="nb"> </span><span class="o">-</span><span class="nb"> </span><span class="m">1</span><span class="o">)</span><span class="nb"> </span><span class="nv">\right</span><span class="o">)</span><span class="nb">
</span></span></span><span class="line"><span class="cl"><span class="s">$$</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>对偶问题：
</p>
$$
  \underset{x_1, x_2}{\text{Min.}}\, x_1 + x_2 + \underset{\lambda \ge 0}{\text{Max.}}\, \lambda(x_1^2 + x_2^2 - 1)
  $$<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\underset</span><span class="nb">{</span>x<span class="nb">_</span>1, x<span class="nb">_</span>2<span class="nb">}{</span><span class="k">\text</span><span class="nb">{</span>Min.<span class="nb">}}</span><span class="k">\,</span> x<span class="nb">_</span>1 + x<span class="nb">_</span>2 + <span class="k">\underset</span><span class="nb">{</span><span class="k">\lambda</span> <span class="k">\ge</span> 0<span class="nb">}{</span><span class="k">\text</span><span class="nb">{</span>Max.<span class="nb">}}</span><span class="k">\,</span> <span class="k">\lambda</span>(x<span class="nb">_</span>1<span class="nb">^</span>2 + x<span class="nb">_</span>2<span class="nb">^</span>2 - 1)
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>KKT 梯度条件：
</p>
$$
  \frac{\partial L(x,\lambda^*,\mu^*)}{\partial x}\Big|_{x=x^*}
  = \nabla f(x^*) + \sum_{i=1}^{m} \lambda_i^* \nabla g_i(x^*) + \sum_{j=1}^{p} \mu_j^* \nabla h_j(x^*) = 0
  $$<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-latex" data-lang="latex"><span class="line"><span class="cl"><span class="k">\frac</span><span class="nb">{</span><span class="k">\partial</span> L(x,<span class="k">\lambda</span><span class="nb">^</span>*,<span class="k">\mu</span><span class="nb">^</span>*)<span class="nb">}{</span><span class="k">\partial</span> x<span class="nb">}</span><span class="k">\Big</span>|<span class="nb">_{</span>x=x<span class="nb">^</span>*<span class="nb">}</span>
</span></span><span class="line"><span class="cl">= <span class="k">\nabla</span> f(x<span class="nb">^</span>*) + <span class="k">\sum</span><span class="nb">_{</span>i=1<span class="nb">}^{</span>m<span class="nb">}</span> <span class="k">\lambda</span><span class="nb">_</span>i<span class="nb">^</span>* <span class="k">\nabla</span> g<span class="nb">_</span>i(x<span class="nb">^</span>*) + <span class="k">\sum</span><span class="nb">_{</span>j=1<span class="nb">}^{</span>p<span class="nb">}</span> <span class="k">\mu</span><span class="nb">_</span>j<span class="nb">^</span>* <span class="k">\nabla</span> h<span class="nb">_</span>j(x<span class="nb">^</span>*) = 0
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>矩阵正定性：</p>
<ul>
<li>$A \succ 0$：严格正定</li>
<li>$A \succeq 0$：半正定</li>
<li>$A \prec 0$：严格负定</li>
<li>$A \preceq 0$：半负定</li>
</ul>
</li>
</ul>
<h2 id="常用数学公式">常用数学公式</h2>
<ul>
<li>
<p>二次公式：
</p>
$$
  x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
  $$</li>
<li>
<p>勾股定理：
</p>
$$
  a^2 + b^2 = c^2
  $$</li>
<li>
<p>完全平方：
</p>
$$
  (a+b)^2 = a^2 + 2ab + b^2
  $$</li>
<li>
<p>三角恒等式：
</p>
$$
  \sin^2 x + \cos^2 x = 1
  $$</li>
<li>
<p>幂函数导数：
</p>
$$
  \frac{d}{dx} x^n = nx^{n-1}
  $$</li>
<li>
<p>积分基本公式：
</p>
$$
  \int_a^b f(x)\,dx = F(b)-F(a)
  $$</li>
<li>
<p>欧拉公式：
</p>
$$
  e^{\mathrm{i}\theta} = \cos\theta + \mathrm{i}\sin\theta
  $$</li>
<li>
<p>指数函数展开：
</p>
$$
  e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!}
  $$</li>
</ul>
]]></content:encoded></item><item><title>什么是云计算</title><link>https://farmer3-c.github.io/posts/post-2025-08-25/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-08-25/</guid><description>What is cloud computing</description><content:encoded><![CDATA[<h1 id="definition">Definition</h1>
<p>云计算是一种技术，它允许你通过互联网存储和访问数据及应用程序，而不是使用计算机的硬盘驱动器或本地服务器。在云计算中，你可以将不同类型的数据（如文件、图像、视频和文档）存储在远程服务器上，并随时从任何连接到互联网的设备访问它们。</p>
<ul>
<li>基础设施：云计算依赖于互联网上托管的远程网络服务器来存储、管理和处理数据。</li>
<li>按需访问：用户可以按需访问云服务和资源，无需投资物理硬件即可进行扩展或缩减。</li>
<li>服务类型：云计算提供多种好处，如节省成本、可扩展性、可靠性和可访问性。它减少了资本支出，并提高了效率。</li>
</ul>
<h1 id="architecture-of-cloud-computing">Architecture Of Cloud Computing</h1>
<ol>
<li>
<p>前端（用户交互增强）
云计算的用户界面由两部分客户端组成。瘦客户端使用网络浏览器，提供便携和轻量级的访问方式；而胖客户端则使用多种功能，提供强大的用户体验。</p>
</li>
<li>
<p>后端平台（云计算引擎）<br>
云计算的核心是在后端平台，使用多个服务器进行存储和计算处理。应用程序逻辑的管理通过服务器进行，而有效的数据处理由存储提供。这些后端平台的结合提供了处理能力，以及管理和存储云端数据的能力。</p>
</li>
<li>
<p>基于云的交付和网络
通过互联网、内网和云间网提供按需访问计算机和资源。互联网具有全球可访问性，内网有助于组织内部服务之间的通信，而云间网则实现不同云服务之间的互操作性。这种动态的网络连接确保了云计算架构的一个基本组成部分，即保证轻松访问和数据传输。</p>
</li>
</ol>
<p><img alt="cloud" loading="lazy" src="/img/in-post/cloud_computing_architecture.png"></p>
]]></content:encoded></item><item><title>什么是边缘计算</title><link>https://farmer3-c.github.io/posts/post-2025-08-27/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-08-27/</guid><description>What is edge computing</description><content:encoded><![CDATA[<h1 id="definition">Definition</h1>
<p>本质上，边缘计算是指尽可能在数据产生和指令执行的地方进行计算。这种计算形式可能直接在客户端设备上进行——例如智能手机、监控摄像头、无人机或自动驾驶汽车——也可能在临近的网络节点进行，例如在蜂窝塔旁边的本地连接服务器或小型本地数据中心。重要的是，边缘计算是尽可能在数据源附近进行，以减少网络流量和延迟。</p>
<p>这是在 5G 通信和云计算可能已经普及的情况下进行的，因为将请求发送到中央服务器并获取响应所需的时间可能仍然过长，特别是对于时间关键任务，如自动驾驶汽车。合适的边缘设备，无论是边缘服务器还是强大的客户端设备，都能够绕过延迟、带宽和响应时间的问题。在隐私或安全问题可能存在的情况下，边缘计算也可能更可取。人工智能和物联网（IoT）等下一代智能技术的现代实例严重依赖于边缘设备的部署。</p>
<h1 id="example">Example</h1>
<p>想象一座由数十个高清 IoT 摄像机监控的建筑物。这些“笨拙的”摄像头仅仅输出原始视频信号，持续将信号串流到云服务器。在云服务器上，来自所有摄像头的视频输出都会通过运动检测应用程序，以确保仅将有活动的剪辑保存到服务器的数据库中。这意味着建筑物的互联网基础设施将承受持续且显著的压力，因为高容量的视频素材传输会消耗大量带宽。此外，云服务器上的负载极高，因为必须同时处理来自所有摄像头的视频素材。</p>
<p>现在，假设运动传感器计算移至网络边缘。如果每个摄像头都使用自己的内部计算机来运行运动检测应用程序，然后根据需要将素材发送到云服务器，这样会如何？这将导致带宽使用量显著减少，因为很多镜头永远不必传输到云服务器。</p>
<p>此外，云服务器现在仅负责存储重要素材，这意味着服务器可以与更多数量的摄像头通信而不会过载</p>
<center>
Kubernetes Native Edge Computing Framework (project under CNCF)</center>
<p><img alt="kube" loading="lazy" src="/img/in-post/kubeedge_arch.png"></p>
<h2 id="reference">Reference</h2>
<hr>
<p>1.<a href="https://www.gigabyte.com/Article/living-on-the-edge">What is Edge Computing? Definition and Cases Explained</a><br>
2.<a href="https://github.com/kubeedge/kubeedge/tree/master">kubeedge</a><br>
3.<a href="https://www.cloudflare.com/zh-cn/learning/serverless/glossary/what-is-edge-computing/">什么是边缘计算？</a></p>
]]></content:encoded></item><item><title>我的第一篇文章</title><link>https://farmer3-c.github.io/posts/post-2025-08-20/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-08-20/</guid><description>开始我的博客之旅</description><content:encoded><![CDATA[<h1 id="前言">前言</h1>
<p>一直想搭建一个自己的个人博客，苦于网上的教程说的云里雾里，于是未果。<br>
忽然发现 <a href="https://github.com/Huxpro/huxpro.github.io">Hux Blog</a>，得以顺利搭建，将搭建过程作为第一篇博客发布。</p>
<h1 id="详细搭建步骤">详细搭建步骤</h1>
<ol>
<li>
<p>环境准备
首先需要安装必要的开发环境 ：</p>
<ul>
<li>安装Ruby和Bundler</li>
<li>安装项目依赖：
<blockquote>
<p>$ bundle install</p>
</blockquote>
</li>
</ul>
</li>
<li>
<p>启动本地开发服务器</p>
<ul>
<li>运行以下命令启动本地预览（默认端口4000）：
<blockquote>
<p>$ bundle exec jekyll serve  # 或者使用 npm start</p>
</blockquote>
</li>
</ul>
</li>
<li>
<p>基础配置定制</p>
<ul>
<li>
<p>修改_config.yml文件进行个性化配置 ：</p>
<pre><code>  ##### Site settings  
  title: 你的博客标题  
  SEOTitle: 你的SEO标题  
  description: &quot;博客描述&quot;  

  ##### SNS settings        
  github_username: 你的github用户名  
  weibo_username: 你的微博用户名  

  ##### Build settings  
  paginate: 10  # 每页文章数量
</code></pre>
</li>
</ul>
</li>
<li>
<p>创建博客文章</p>
<ul>
<li>手动创建
在_posts/目录下创建Markdown文件，包含YAML头文件 ：</li>
</ul>
</li>
</ol>
<hr>
<pre><code>    layout:     post  
    title:      &quot;文章标题&quot;  
    subtitle:   &quot;副标题&quot;  
    date:       2015-01-29 12:00:00  
    author:     &quot;作者名&quot;  
    header-img: &quot;img/post-bg-2015.jpg&quot;  
    catalog: true  
    tags:  
        - 标签1  
        - 标签2  
</code></pre>
<hr>
<ul>
<li>
<p>使用Rake工具自动生成
使用命令自动生成文章模板：</p>
<blockquote>
<p>rake post title=&ldquo;文章标题&rdquo; subtitle=&ldquo;副标题&rdquo;</p>
</blockquote>
<p>这个命令会在_posts/目录下自动创建带有正确格式的文章文件。</p>
</li>
</ul>
<ol start="5">
<li>高级功能配置</li>
</ol>
<ul>
<li>
<p>侧边栏设置
在_config.yml中配置侧边栏：</p>
<pre><code>  ##### Sidebar settings  
  sidebar: true  
  sidebar-about-description: &quot;个人描述&quot;  
  sidebar-avatar: /img/avatar.jpg
  推荐标签功能
  配置标签推荐功能：

  ##### Featured Tags  
  featured-tags: true    
  featured-condition-size: 1  # 标签文章数量阈值
  友链配置
  添加友情链接：

  ##### Friends  
  friends: [  
      {  
          title: &quot;朋友博客&quot;,  
          href: &quot;http://friend.github.io/&quot;  
      }  
  ]
</code></pre>
</li>
</ul>
<ol start="6">
<li>部署到GitHub Pages
<ul>
<li>
<p>这个博客系统的核心优势在于GitHub Pages + Jekyll的部署方案 ：</p>
<ul>
<li>Markdown优雅写作体验</li>
<li>熟悉的Git工作流，Git Commit即Blog Post</li>
<li>利用GitHub Pages免费域名和无限空间</li>
<li>Jekyll自定制容易</li>
<li>只需要将代码推送到GitHub仓库，GitHub Pages会自动构建和部署你的博客。</li>
</ul>
</li>
</ul>
</li>
</ol>
]]></content:encoded></item><item><title>纠删码是什么</title><link>https://farmer3-c.github.io/posts/post-2025-08-24/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://farmer3-c.github.io/posts/post-2025-08-24/</guid><description>What is erasure coding</description><content:encoded><![CDATA[<h1 id="definition">Definition</h1>
<p>纠删码是一种系统设计中的数据保护方法，用于确保数据的可靠性和可用性。它通过将数据分割成更小的数据块，并使用数学算法创建额外的数据片段（称为校验数据），从而实现这一功能。这使得系统即使在某些数据块丢失或损坏的情况下也能恢复原始数据。</p>
<ul>
<li>数据分片：原始数据被分割成多个数据块。</li>
<li>校验和生成：使用 Reed-Solomon 等算法生成额外的校验和块。</li>
<li>存储：数据和校验块被分布到不同的存储节点或设备上。</li>
<li>恢复：如果某些数据块丢失或损坏，系统可以使用剩余的数据块和校验数据来重建原始数据。</li>
</ul>
<h1 id="reed-solomon-encoding-matrix-example">Reed-Solomon Encoding Matrix Example</h1>
<p>数学家们已经几个世纪以来一直在研究矩阵代数、群论和信息论。Reed 和 Solomon 利用这些知识创造了一种看似神奇的编码系统。它可以将信息分解成 n 个部分，添加 k 个“校验”部分，然后从 (n+k) 个部分中的 n 个部分中重建原始信息。</p>
<p>下面的示例使用“4+2”编码系统，其中原始文件被分成四块，然后添加两块校验块。</p>
<p><strong>原始数据</strong></p>
<p><img alt="原始数据" loading="lazy" src="/img/in-post/blog-rs-1.png"></p>
<p>在这个例子中，文件的四个部分每个都是四个字节长。每个部分是矩阵的一行。第一个是“ABCD”。第二个是“EFGH”。以此类推。Reed-Solomon 算法创建一个编码矩阵，你用这个矩阵乘以你的数据矩阵来生成编码数据。该矩阵的设置方式是，结果的前四行与输入的前四行相同。这意味着数据保持完整，它实际上只是在计算校验位。</p>
<p><strong>应用编码矩阵</strong>
<img alt="应用编码矩阵" loading="lazy" src="/img/in-post/blog-rs-2.png"></p>
<p>结果是比原始矩阵多两行的矩阵。这两行是校验位。<br>
编码矩阵的每一行都会生成结果矩阵的一行。因此编码矩阵的每一行都会生成文件结果的一部分。由于行是独立的，你可以划掉两行，方程仍然成立。
<strong>数据丢失：六行中有两行“丢失”</strong>
<img alt="loss" loading="lazy" src="/img/in-post/blog-rs-3.png"></p>
<p>那些行完全消失后，看起来是这样的：</p>
<p><img alt="loss2" loading="lazy" src="/img/in-post/RS-post-pic-4.png"></p>
<p>由于数学家多年来所做的所有工作，我们知道编码矩阵，即左侧的矩阵，是可逆的。存在一个逆矩阵，当它与编码矩阵相乘时，会产生单位矩阵。就像在基础代数中一样，在矩阵代数中你可以用相同的东西乘以等式的两边。在这种情况下，我们将用单位矩阵从左侧进行相乘：</p>
<p><strong>将方程两边乘以逆矩阵</strong>
<img alt="loss3" loading="lazy" src="/img/in-post/RS-post-pic-5.png">
<strong>逆矩阵和编码矩阵相互抵消</strong>
<img alt="loss4" loading="lazy" src="/img/in-post/RS-post-pic-5-5.png"></p>
<p><strong>重建原始数据</strong>
<img alt="loss6" loading="lazy" src="/img/in-post/blog-rs-7.png"></p>
<p>因此，要制作解码矩阵，过程是取原始编码矩阵，划去缺失部分的行，然后找到逆矩阵。接着，你可以将逆矩阵与可用的数据部分相乘，以重建原始数据。</p>
<h2 id="reference">Reference</h2>
<p>1.<a href="https://www.backblaze.com/blog/reed-solomon/">Backblaze Open-sources Reed-Solomon Erasure Coding Source Code</a><br>
2.<a href="https://www.geeksforgeeks.org/system-design/erasure-coding-in-system-design/">Erasure Coding in System Design</a></p>
]]></content:encoded></item></channel></rss>