{
    "version": "https://jsonfeed.org/version/1",
    "title": "Jiankychen's Blog",
    "subtitle": "Never put off till tomorrow what you can do today",
    "icon": "https://jiankychen.github.io/assets/favicon.ico",
    "description": "",
    "home_page_url": "https://jiankychen.github.io",
    "items": [
        {
            "id": "https://jiankychen.github.io/latex-to-word.html",
            "url": "https://jiankychen.github.io/latex-to-word.html",
            "title": "LaTeX 转 Word",
            "date_published": "2023-02-16T09:26:05.000Z",
            "content_html": "<h1 id=\"pandoc\"><a class=\"anchor\" href=\"#pandoc\">#</a> Pandoc</h1>\n<p>利用 Pandoc 读取 tex 源码并输出 docx 文件</p>\n<h2 id=\"安装\"><a class=\"anchor\" href=\"#安装\">#</a> 安装</h2>\n<p>Pandoc 下载地址：<a href=\"https://pandoc.org/installing.html\">Pandoc</a></p>\n<p>按默认配置安装即可</p>\n<h2 id=\"使用\"><a class=\"anchor\" href=\"#使用\">#</a> 使用</h2>\n<p>步骤：</p>\n<ul>\n<li>\n<p>配置路径：打开 cmd ，切换到需转换的 LaTeX 文件所在的路径</p>\n</li>\n<li>\n<p>转换：在 cmd 中输入转换命令</p>\n</li>\n</ul>\n<p>命令模板（不可执行）：</p>\n<figure class=\"highlight powershell\"><figcaption data-lang=\"PowerShell\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pandoc main<span class=\"token punctuation\">.</span>tex <span class=\"token operator\">-</span>o output<span class=\"token punctuation\">.</span>docx ^</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token operator\">--</span>reference-doc template<span class=\"token punctuation\">.</span>docx ^</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token operator\">--</span><span class=\"token keyword\">filter</span> pandoc-crossref <span class=\"token operator\">-</span>M tableEqns <span class=\"token operator\">-</span>M autoEqnLabels ^</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token operator\">--</span>resource-path=<span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span>Figures ^</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token operator\">--</span>bibliography ref<span class=\"token punctuation\">.</span>bib ^</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token operator\">--</span>citeproc ^</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token operator\">--</span>csl references_style<span class=\"token punctuation\">.</span>csl ^</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token operator\">-</span>M reference-section-title=Reference ^</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token operator\">--</span>number-sections ^</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token operator\">--</span>toc</pre></td></tr></table></figure><p>相关命令及参数介绍：</p>\n<ul>\n<li>\n<p><code>main.tex</code> ：输入 LaTeX 文件名</p>\n</li>\n<li>\n<p><code>-o output.docx</code> ：输出 Word 文件名</p>\n</li>\n<li>\n<p><code>--reference-doc template.docx</code> ：参考模板 Docx 文件，可从 <a href=\"https://template-selector.ieee.org/secure/templateSelector/publicationType\">IEEE article template</a> 下载【可选】</p>\n</li>\n<li>\n<p><code>--filter pandoc-crossref</code> ：用于公式、图片、表格等的交叉引用【可选】</p>\n<ul>\n<li>需要从 Github 下载 <a href=\"https://github.com/lierdakil/pandoc-crossref/releases\">pandoc-crossref</a> ，并将 pandoc-crossref.exe 放到 Pandoc 的安装目录中</li>\n<li><code>-M tableEqns -M autoEqnLabels</code> ： <code>autoEqnLabels</code>  为公式编号， <code>tableEqns</code>  以表格形式显示公式编号（即：创建一个两列表，将公式放在左边列，将公式编号放在右边列）（具体可查看 <a href=\"http://lierdakil.github.io/pandoc-crossref/\">pandoc-crossref 文档</a>）</li>\n</ul>\n</li>\n<li>\n<p><code>--resource-path=.;Figures</code> ：指定 tex 源图片的存放文件夹</p>\n<ul>\n<li><code>.;Figures</code> ： <code>.</code>  表示当前工作目录， <code>;</code>  是 Windows 系统的分隔符（Linux、Unix、macOs 用  <code>:</code>  ）， <code>Figures</code>  是存放 tex 源图片的子文件夹的名称</li>\n<li>eps、pdf 等格式无法正常转化进 Word 文件，需提前将图片转为 jpg 等格式</li>\n</ul>\n</li>\n<li>\n<p><code>--bibliography ref.bib</code> ：参考文献 bib 文件 【可选】</p>\n</li>\n<li>\n<p><code>--citeproc</code> ：用于参考文献的引用 【可选】</p>\n</li>\n<li>\n<p><code>--csl references_style.csl</code> ：参考文献的样式文件，可从 <a href=\"https://www.zotero.org/styles\">Zotero Style Repository</a> 下载 【可选】</p>\n</li>\n<li>\n<p><code>-M reference-section-title=Reference</code> ：添加参考文献的章节名 【可选】</p>\n</li>\n<li>\n<p><code>--number-sections</code> ：用于章节自动编号 【可选】</p>\n</li>\n<li>\n<p><code>--toc</code> ：生成目录 【可选】</p>\n</li>\n</ul>\n<p>详细信息请查看：<a href=\"https://pandoc.org/MANUAL.html\">Pandoc User's Guide</a></p>\n<p>示例：</p>\n<figure class=\"highlight powershell\"><figcaption data-lang=\"PowerShell\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pandoc input<span class=\"token punctuation\">.</span>tex <span class=\"token operator\">--</span><span class=\"token keyword\">filter</span> pandoc-crossref <span class=\"token operator\">-</span>M tableEqns <span class=\"token operator\">-</span>M autoEqnLabels <span class=\"token operator\">--</span>bibliography ref<span class=\"token punctuation\">.</span>bib <span class=\"token operator\">--</span>citeproc <span class=\"token operator\">--</span>csl ieee-wireless-communications-letters<span class=\"token punctuation\">.</span>csl <span class=\"token operator\">--</span>resource-path=<span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span>Figures <span class=\"token operator\">--</span>number-sections <span class=\"token operator\">-</span>M reference-section-title=Reference <span class=\"token operator\">-</span>o output<span class=\"token punctuation\">.</span>docx</pre></td></tr></table></figure><h2 id=\"注意事项\"><a class=\"anchor\" href=\"#注意事项\">#</a> 注意事项</h2>\n<ul>\n<li>\n<p>带  <code>*</code>  的图表不能正确转化，例如： <code>\\begin&#123;figure*&#125;</code>  应改为  <code>\\begin&#123;figure&#125;</code></p>\n</li>\n<li>\n<p>表格中带子 tabular 的不能正确生成</p>\n</li>\n<li>\n<p>由于 pandoc-crossref 使用与 citeproc 相同的引用语法，因此，pandoc-crossref 相关命令必须放在 citeproc 前面</p>\n</li>\n<li>\n<p>LaTeX 伪代码算法无法正常转化，可通过第三方工具实现（例如：Aurora 插件）</p>\n</li>\n</ul>\n<blockquote>\n<p>经测试，图片、表格、章节的交叉引用可以显示编号，但公式的交叉引用无法显示编号（无论是  <code>\\ref</code>  命令还是  <code>\\eqref</code>  命令都无法显示）。</p>\n</blockquote>\n<h2 id=\"参考资料\"><a class=\"anchor\" href=\"#参考资料\">#</a> 参考资料</h2>\n<p>Pandoc：</p>\n<ul>\n<li><a href=\"https://blog.csdn.net/qq_31375855/article/details/122044004\">Pandoc: LaTeX 转 Word 文档 （含参考文献样式）</a></li>\n<li><a href=\"https://blog.csdn.net/u013256285/article/details/128219495\">pandoc LaTeX 转 Word (.docx) 踩坑记录</a></li>\n<li><a href=\"https://blog.csdn.net/qq_27464321/article/details/88853270\">Windows 下 Pandoc 转换 LaTex 成 Word 最全指令</a></li>\n<li><a href=\"https://ge-chunyu.github.io/posts/2019-11-pandoc-large-document/\">用 Pandoc 生成大型中文文档的痛点与解决方案</a></li>\n</ul>\n<p>Aurora：</p>\n<ul>\n<li><a href=\"https://callmejacky.blog.csdn.net/article/details/98615124\">Aurora：在 Word 中插入算法伪代码、表格和公式</a></li>\n<li><a href=\"https://blog.csdn.net/jucksu/article/details/116307244\">使用 Aurora 在 Word 中插入算法伪代码教程</a></li>\n<li><a href=\"https://zhuanlan.zhihu.com/p/367884765\">使用 Aurora + Algorithm2e 在 Word 中输入伪代码</a></li>\n</ul>\n<h1 id=\"acrobat\"><a class=\"anchor\" href=\"#acrobat\">#</a> Acrobat</h1>\n<p>直接使用 Adobe Acrobat Pro DC 软件将 PDF 文件转换成 Word 文件</p>\n<p>除部分公式无法准确转换外，其余的转换效果都挺不错的</p>\n<p>可以考虑将 Acrobat 与 Pandoc 结合使用，取长补短</p>\n",
            "tags": [
                "Tutorial",
                "LaTeX"
            ]
        },
        {
            "id": "https://jiankychen.github.io/sql-basics.html",
            "url": "https://jiankychen.github.io/sql-basics.html",
            "title": "SQL 基础",
            "date_published": "2023-02-04T14:43:13.000Z",
            "content_html": "<h1 id=\"sql-简介\"><a class=\"anchor\" href=\"#sql-简介\">#</a> SQL 简介</h1>\n<p>SQL（Structured Query Language），结构化查询语言，用于访问和处理数据库的标准的计算机语言</p>\n<p>SQL 语法特征：</p>\n<ul>\n<li>\n<p>大小写不敏感</p>\n</li>\n<li>\n<p>可以单行或多行书写，最后以  <code>;</code>  号结束</p>\n</li>\n<li>\n<p>支持单行、多行注释：</p>\n<ul>\n<li>单行注释： <code>-- 注释内容</code> （-- 后面一定要有一个空格）</li>\n<li>单行注释： <code># 注释内容</code> （# 后面可以不加空格，但推荐加上）</li>\n<li>多行注释： <code>/*  注释内容  */</code></li>\n</ul>\n</li>\n</ul>\n<p>根据 SQL 语句的功能，可将其分为四类：</p>\n<ul>\n<li>\n<p>数据定义：DDL（Data Definition Language）</p>\n<ul>\n<li>库的创建删除、表的创建删除等</li>\n</ul>\n</li>\n<li>\n<p>数据操纵：DML（Data Manipulation Language）</p>\n<ul>\n<li>新增数据、删除数据、修改数据等</li>\n</ul>\n</li>\n<li>\n<p>数据控制：DCL（Data Control Language）</p>\n<ul>\n<li>新增用户、删除用户、密码修改、权限管理等</li>\n</ul>\n</li>\n<li>\n<p>数据查询：DQL（Data Query Language）</p>\n<ul>\n<li>基于需求查询和计算数据</li>\n</ul>\n</li>\n</ul>\n<h1 id=\"ddl\"><a class=\"anchor\" href=\"#ddl\">#</a> DDL</h1>\n<h2 id=\"数据库操作\"><a class=\"anchor\" href=\"#数据库操作\">#</a> 数据库操作</h2>\n<p>查看所有数据库</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">show</span> <span class=\"token keyword\">databases</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>查看当前使用的数据库</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> <span class=\"token keyword\">database</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>创建数据库</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">create</span> <span class=\"token keyword\">database</span> 数据库名 <span class=\"token keyword\">charset</span> utf8<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>删除数据库</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">drop</span> <span class=\"token keyword\">database</span> 数据库名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>使用数据库</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">use</span> 数据库名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h2 id=\"表操作\"><a class=\"anchor\" href=\"#表操作\">#</a> 表操作</h2>\n<p>查看数据库中所有表（需要先选择数据库）</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">show</span> <span class=\"token keyword\">tables</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>查看表结构</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">desc</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>创建表</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">create</span> <span class=\"token keyword\">table</span> 表名<span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  列名 列类型 <span class=\"token punctuation\">[</span>约束条件<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  列名 列类型 <span class=\"token punctuation\">[</span>约束条件<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>）<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p><code>[]</code>  表示可选的内容</p>\n</blockquote>\n<p>其中，列类型有：</p>\n<ul>\n<li><code>int</code>  ：整数</li>\n<li><code>float</code>  ：浮点数</li>\n<li><code>varchar(长度)</code>  ：文本（长度填写整数类型，用于限制文本长度，可填的最大数字为 255）</li>\n<li><code>date</code>  ：日期类型</li>\n<li><code>timestamp</code>  ：时间戳类型</li>\n</ul>\n<p>修改表–添加字段</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">alter</span> <span class=\"token keyword\">table</span> 表名 <span class=\"token keyword\">add</span> 列名 类型<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>修改表–修改字段–重命名版</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>alert <span class=\"token keyword\">table</span> 表名 change 原名 新名 类型及约束<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>修改表–修改字段–不重命名</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">alter</span> <span class=\"token keyword\">table</span> 表名 <span class=\"token keyword\">modify</span> 列名 类型及约束<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>删除表–删除字段</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">alter</span> <span class=\"token keyword\">table</span> 表名 <span class=\"token keyword\">drop</span> 列名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>删除表</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">drop</span> <span class=\"token keyword\">table</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 如果表存在，则删除；如不存在，则跳过</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">drop</span> <span class=\"token keyword\">table</span> <span class=\"token keyword\">if</span> <span class=\"token keyword\">exists</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p>有些数据库系统不支持  <code>if exists</code>  选项，支持  <code>if exists</code>  选项的有：MySQL，PostgreSQL 和 SQL Server 2016</p>\n</blockquote>\n<p>查看表的创建语句–详细过程</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">show</span> <span class=\"token keyword\">create</span> <span class=\"token keyword\">table</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h1 id=\"dml\"><a class=\"anchor\" href=\"#dml\">#</a> DML</h1>\n<h2 id=\"数据插入\"><a class=\"anchor\" href=\"#数据插入\">#</a> 数据插入</h2>\n<p>全列插入：值的顺序与表结构字段的顺序完全对应，此时可以省略列名的列表</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> 表名 <span class=\"token keyword\">values</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>部分列插入：值的顺序与给出的列名顺序对应</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> 表名 <span class=\"token punctuation\">(</span>列<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 列<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">values</span> <span class=\"token punctuation\">(</span>值<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 值<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>全列多行插入</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> 表名 <span class=\"token keyword\">values</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>部分列多行插入</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> 表名 <span class=\"token punctuation\">(</span>列<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 列<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">values</span> <span class=\"token punctuation\">(</span>值<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 值<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>值<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 值<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p>注意：如果数据是字符型，必须使用单引号或双引号包围</p>\n</blockquote>\n<p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 创建名为 test 的数据库</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">create</span> <span class=\"token keyword\">database</span> test <span class=\"token keyword\">charset</span> UTF8<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 使用名为 test 的数据库</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">use</span> test<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 创建表</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">create</span> <span class=\"token keyword\">table</span> student<span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>\tid <span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>\tname <span class=\"token keyword\">varchar</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>\tage <span class=\"token keyword\">int</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 为 id 列插入多行数据</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> student<span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span> <span class=\"token keyword\">values</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token comment\"># 为 id 列和 name 列插入多行数据</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> student<span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">)</span> <span class=\"token keyword\">values</span><span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Ellon'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'John'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token comment\"># 为全部列插入数据</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> student <span class=\"token keyword\">values</span><span class=\"token punctuation\">(</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Ale'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">20</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h2 id=\"数据删除\"><a class=\"anchor\" href=\"#数据删除\">#</a> 数据删除</h2>\n<p>清空表（删除整个表中的数据）</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">delete</span> <span class=\"token keyword\">from</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>按特定条件删除数据</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">delete</span> <span class=\"token keyword\">from</span> 表名 <span class=\"token keyword\">where</span> 条件<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 删除 id 为 3 的行</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">delete</span> <span class=\"token keyword\">from</span> student <span class=\"token keyword\">where</span> id <span class=\"token operator\">=</span> <span class=\"token number\">3</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"where\"><a class=\"anchor\" href=\"#where\">#</a> where</h3>\n<p><code>where</code>  后面跟条件语句，以进行条件处理</p>\n<p>条件语句支持以下运算符：</p>\n<ul>\n<li>比较运算符\n<ul>\n<li>等于： <code>=</code></li>\n<li>大于： <code>&gt;</code></li>\n<li>大于等于： <code>&gt;=</code></li>\n<li>小于： <code>&lt;</code></li>\n<li>小于等于： <code>&lt;=</code></li>\n<li>不等于： <code>!=</code>  或  <code>&lt;&gt;</code></li>\n</ul>\n</li>\n<li>逻辑运算符\n<ul>\n<li>与： <code>and</code></li>\n<li>或： <code>or</code></li>\n<li>非： <code>not</code></li>\n</ul>\n</li>\n<li>使用 like 关键字的模糊查询\n<ul>\n<li><code>%</code>  通配符：表示任意多个任意字符</li>\n<li><code>_</code>  通配符：表示一个任意字符</li>\n</ul>\n</li>\n<li>范围查询\n<ul>\n<li>连续范围查询： <code>between ... and ...</code></li>\n<li>非连续范围查询： <code>in(... , ...)</code></li>\n</ul>\n</li>\n<li>空判断\n<ul>\n<li>判断为空： <code>is null</code></li>\n<li>判断不为空： <code>is not null</code></li>\n</ul>\n</li>\n</ul>\n<p>条件的优先级：</p>\n<ul>\n<li>优先级由高到低的顺序为：小括号， <code>not</code> ，比较运算符，逻辑运算符</li>\n<li><code>and</code>  比  <code>or</code>  先运算（如果同时出现并希望先算  <code>or</code>  ，需要结合  <code>()</code>  使用）</li>\n</ul>\n<p>参考资料：</p>\n<ul>\n<li><a href=\"http://c.biancheng.net/view/2559.html\">MySQL WHERE：条件查询</a></li>\n<li><a href=\"https://blog.csdn.net/benxiaohai888/article/details/77657108\">SQL 条件 (限定) 查询</a></li>\n</ul>\n<h2 id=\"数据修改\"><a class=\"anchor\" href=\"#数据修改\">#</a> 数据修改</h2>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">update</span> 表名 <span class=\"token keyword\">set</span> 列名 <span class=\"token operator\">=</span> 值 <span class=\"token punctuation\">[</span><span class=\"token keyword\">where</span> 条件<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 将 id 为 2 所对应的 name 修改为 Mike</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">update</span> student <span class=\"token keyword\">set</span> name <span class=\"token operator\">=</span> <span class=\"token string\">'Mike'</span> <span class=\"token keyword\">where</span> id <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p><code>update 表名 set 列名 = 值</code>  会修改整列的数据</p>\n</blockquote>\n<h1 id=\"dql\"><a class=\"anchor\" href=\"#dql\">#</a> DQL</h1>\n<h2 id=\"基础查询\"><a class=\"anchor\" href=\"#基础查询\">#</a> 基础查询</h2>\n<p>查询所有列</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>查询指定列</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> 列<span class=\"token number\">1</span>，列<span class=\"token number\">2</span>，<span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token keyword\">from</span> 表名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>条件查询</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> 列<span class=\"token number\">1</span>，列<span class=\"token number\">2</span>，<span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token keyword\">from</span> 表名 <span class=\"token keyword\">where</span> 条件<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查询 id 和 name 两列，年龄小于 35</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">select</span> id<span class=\"token punctuation\">,</span> name <span class=\"token keyword\">from</span> student <span class=\"token keyword\">where</span> age <span class=\"token operator\">>=</span> <span class=\"token number\">18</span> <span class=\"token operator\">and</span> age <span class=\"token operator\">&lt;</span> <span class=\"token number\">35</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h2 id=\"分组聚合\"><a class=\"anchor\" href=\"#分组聚合\">#</a> 分组聚合</h2>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> 字段<span class=\"token punctuation\">,</span> 聚合函数 <span class=\"token keyword\">from</span> 表名 <span class=\"token punctuation\">[</span><span class=\"token keyword\">where</span> 条件<span class=\"token punctuation\">]</span> <span class=\"token keyword\">group</span> <span class=\"token keyword\">by</span> 列名<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>聚合函数：</p>\n<ul>\n<li>求和： <code>sum(列)</code></li>\n<li>求平均值： <code>avg(列)</code></li>\n<li>求最小值： <code>min(列)</code></li>\n<li>求最大值： <code>max(列)</code></li>\n<li>求数量： <code>count(列/*)</code></li>\n</ul>\n<p>注意：</p>\n<ul>\n<li>一条 SQL 查询语句可以写多个聚合函数，以同时展示多个统计信息</li>\n<li>除了聚合函数外， <code>select 字段</code>  中的 字段 只能包含  <code>GROUP BY 列名</code>  中出现的 列名</li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">create</span> <span class=\"token keyword\">table</span> person<span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  id <span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  name <span class=\"token keyword\">varchar</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  age <span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>  gender <span class=\"token keyword\">varchar</span><span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">insert</span> <span class=\"token keyword\">into</span> person <span class=\"token keyword\">values</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Tom'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">23</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'male'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Jerry'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">22</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'male'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> </pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Morty'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">21</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'male'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Rick'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">26</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'male'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Marry'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">23</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'female'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'Angel'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">22</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'female'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 按性别分组，统计各组人数</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">select</span> gender<span class=\"token punctuation\">,</span> <span class=\"token function\">count</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">group</span> <span class=\"token keyword\">by</span> gender<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 按性别分组，统计平均年龄</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">select</span> gender<span class=\"token punctuation\">,</span> <span class=\"token function\">avg</span><span class=\"token punctuation\">(</span>age<span class=\"token punctuation\">)</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">group</span> <span class=\"token keyword\">by</span> gender<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token comment\"># 按性别分组，统计最大年龄和最小年龄</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token keyword\">select</span> gender<span class=\"token punctuation\">,</span> <span class=\"token function\">max</span><span class=\"token punctuation\">(</span>age<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">min</span><span class=\"token punctuation\">(</span>age<span class=\"token punctuation\">)</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">group</span> <span class=\"token keyword\">by</span> gender<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h2 id=\"排序分页\"><a class=\"anchor\" href=\"#排序分页\">#</a> 排序分页</h2>\n<h3 id=\"结果排序\"><a class=\"anchor\" href=\"#结果排序\">#</a> 结果排序</h3>\n<p>可以对查询的结果使用  <code>order by</code>  关键字，指定某个列进行排序</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> 列<span class=\"token operator\">|</span>聚合函数<span class=\"token operator\">|</span><span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> 表名</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">where</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">group</span> <span class=\"token keyword\">by</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">order</span> <span class=\"token keyword\">by</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token punctuation\">[</span><span class=\"token keyword\">asc</span> <span class=\"token operator\">/</span> <span class=\"token keyword\">desc</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li>升序（默认）: <code>asc</code></li>\n<li>降序： <code>desc</code></li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 显示 age > 22 的所有数据（按 age 列降序排列）</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">select</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">where</span> age <span class=\"token operator\">></span> <span class=\"token number\">22</span> <span class=\"token keyword\">order</span> <span class=\"token keyword\">by</span> age <span class=\"token keyword\">desc</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"结果分页\"><a class=\"anchor\" href=\"#结果分页\">#</a> 结果分页</h3>\n<p>可以使用  <code>limit</code>  关键字，对查询结果进行数量限制或者分页显示</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">select</span> 列<span class=\"token operator\">|</span>聚合函数<span class=\"token operator\">|</span><span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> 表名</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">where</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">group</span> <span class=\"token keyword\">by</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">order</span> <span class=\"token keyword\">by</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token punctuation\">[</span><span class=\"token keyword\">asc</span> <span class=\"token operator\">/</span> <span class=\"token keyword\">desc</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">limit</span> n<span class=\"token punctuation\">[</span><span class=\"token punctuation\">,</span> m<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li><code>n</code>  表示：显示  <code>n</code>  条数据</li>\n<li><code>n, m</code>  表示：跳过前  <code>n</code>  条数据，显示后续的  <code>m</code>  条数据</li>\n</ul>\n<p>注意：</p>\n<ul>\n<li><code>select</code>  和  <code>from</code>  是必写的， <code>where</code> 、 <code>group by</code> 、 <code>order by</code> 、 <code>limit</code>  均可按需求省略</li>\n<li>执行顺序：from -&gt;  <code>where</code>  -&gt;  <code>group by</code>  和聚合函数 -&gt;  <code>select</code>  -&gt;  <code>order by</code>  -&gt;  <code>limit</code></li>\n<li><code>limit</code>  后面不可以直接加公式</li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 按 age 列升序排列，查询结果只保留 5 条数据</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">select</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">limit</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 筛选出年龄最大的 5 人</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">select</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">order</span> <span class=\"token keyword\">by</span> age <span class=\"token keyword\">desc</span> <span class=\"token keyword\">limit</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 按 age 列升序排列，查询结果只保留从第 3 条开始的 2 条数据</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">select</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">from</span> person <span class=\"token keyword\">order</span> <span class=\"token keyword\">by</span> age <span class=\"token keyword\">limit</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>参考资料：</p>\n<ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/43036664\">SQL 常用语句总结</a></li>\n<li><a href=\"https://www.bilibili.com/video/BV1qW4y1a7fU?p=128\">黑马程序员 Python 教程：数据库介绍</a></li>\n<li><a href=\"https://blog.csdn.net/sfz1234567890/article/details/110791280\">面试必备 ——SQL 基础语句大全 (详细）</a></li>\n</ul>\n",
            "tags": [
                "SQL"
            ]
        },
        {
            "id": "https://jiankychen.github.io/python-oop.html",
            "url": "https://jiankychen.github.io/python-oop.html",
            "title": "Python 面向对象",
            "date_published": "2023-02-02T09:48:52.000Z",
            "content_html": "<p>Python 是一种面向对象的编程语言</p>\n<p>简单理解 面向对象 ：基于模板（类）去创建实体（对象），使用对象完成功能开发</p>\n<p>面向对象的三大特征：</p>\n<ul>\n<li>封装</li>\n<li>继承</li>\n<li>多态</li>\n</ul>\n<p>面向对象技术简介</p>\n<ul>\n<li>类（Class）: 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例</li>\n<li>对象：通过类定义的数据结构实例。对象包括两个数据成员（类变量和实例变量）和方法</li>\n<li>实例化：创建一个类的实例（类的具体对象）</li>\n<li>方法：类中定义的函数</li>\n<li>类变量：类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用</li>\n<li>数据成员：类变量或者实例变量用于处理类及其实例对象的相关的数据</li>\n<li>方法重写：如果从父类继承的方法不能满足子类的需求，可以对其进行改写，这个过程叫方法的覆盖（override），也称为方法的重写</li>\n<li>局部变量：定义在方法中的变量，只作用于当前实例的类</li>\n<li>实例变量：在类的声明中，属性是用变量来表示的，这种变量就称为实例变量，实例变量就是一个用 self 修饰的变量</li>\n<li>继承：即一个派生类（derived class）继承基类（base class）的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如，有这样一个设计：一个 Dog 类型的对象派生自 Animal 类，这是模拟 &quot;是一个（is-a）&quot; 关系（即，Dog 是一个 Animal）</li>\n</ul>\n<h1 id=\"类和对象\"><a class=\"anchor\" href=\"#类和对象\">#</a> 类和对象</h1>\n<p>类的组成：</p>\n<ul>\n<li>成员变量：定义在类中的属性（变量）</li>\n<li>成员方法：定义在类中的行为（函数）</li>\n</ul>\n<h2 id=\"类定义\"><a class=\"anchor\" href=\"#类定义\">#</a> 类定义</h2>\n<p>使用关键字  <code>class</code>  定义类：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Class_Name</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token operator\">&lt;</span>statement<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token operator\">&lt;</span>statement<span class=\"token operator\">-</span>N<span class=\"token operator\">></span></pre></td></tr></table></figure><p>其中， <code>Class_Name</code>  表示类的名称，通常需要首字母大写</p>\n<h2 id=\"类对象\"><a class=\"anchor\" href=\"#类对象\">#</a> 类对象</h2>\n<p>创建对象（实例化）：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>obj <span class=\"token operator\">=</span> Class_Name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>修改对象属性：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>obj<span class=\"token punctuation\">.</span>var_name <span class=\"token operator\">=</span> xx</pre></td></tr></table></figure><p>删除对象属性：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 使用 del 关键字删除对象的属性</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">del</span> obj<span class=\"token punctuation\">.</span>var_name</pre></td></tr></table></figure><p>删除对象：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 使用 del 关键字删除对象</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">del</span> obj</pre></td></tr></table></figure><h2 id=\"类的成员方法\"><a class=\"anchor\" href=\"#类的成员方法\">#</a> 类的成员方法</h2>\n<ul>\n<li>函数：定义在类的外部</li>\n<li>方法：定义在类的内部</li>\n</ul>\n<p>在类的内部，使用  <code>def</code>  关键字来定义一个方法，与一般函数定义不同，类的成员方法必须必须有一个额外的第一个参数名称，按照惯例它的名称是  <code>self</code>  ，即：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func_name</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> parameter_1<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">,</span> parameter_N<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li>\n<p><code>self</code>  参数是对类的当前实例的引用，用于访问属于该类的变量。它不必被命名为  <code>self</code> ，但它必须是类中任意函数的首个参数</p>\n</li>\n<li>\n<p>在方法内部，想要访问类的成员变量，必须使用  <code>self</code>  。即，使用  <code>self.var_name</code>  访问成员变量  <code>var_nam</code></p>\n</li>\n<li>\n<p>调用类的成员方法时， <code>self</code>  会被自动传入，即，不需要在实参列表中写出  <code>self</code></p>\n</li>\n</ul>\n<h2 id=\"构造方法\"><a class=\"anchor\" href=\"#构造方法\">#</a> 构造方法</h2>\n<p>Python 类中的  <code>__init__</code>  方法，称之为 构造方法</p>\n<p>每次使用类创建新对象时，都会自动调用  <code>__init__</code>  方法，并且会将创建类对象时的传入参数自动传递给  <code>__init__</code>  方法</p>\n<p>因此，使用  <code>__init__</code>  方法可以将值赋给对象属性，或者在创建对象时需要执行的其他操作</p>\n<p>注意，构造方法 也是 成员方法，因此：</p>\n<ul>\n<li>定义构造方法时需要在形参列表中写上  <code>self</code>  参数</li>\n<li>在构造方法内部访问成员变量需要使用  <code>self.var_name</code></li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 定义类</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Person</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    name <span class=\"token operator\">=</span> <span class=\"token boolean\">None</span>     <span class=\"token comment\"># 由于定义了 __init__ 方法，可以省略这里的初始化</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    age <span class=\"token operator\">=</span> <span class=\"token boolean\">None</span>      <span class=\"token comment\"># 由于定义了 __init__ 方法，可以省略这里的初始化</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> age<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        self<span class=\"token punctuation\">.</span>name <span class=\"token operator\">=</span> name</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        self<span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> age</pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 创建类对象</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>p <span class=\"token operator\">=</span> Person<span class=\"token punctuation\">(</span><span class=\"token string\">\"John\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">24</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 打印类对象的属性</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">.</span>age<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"魔术方法\"><a class=\"anchor\" href=\"#魔术方法\">#</a> 魔术方法</h2>\n<p>魔术方法（Magic Methods）是 Python 中的内置方法，一般以  <code>__</code>  （双下划线）为开头和结尾</p>\n<p>例如：</p>\n<ul>\n<li><code>__init__</code>  ：构造方法，当一个实例被创建的时候调用的初始化方法</li>\n<li><code>__del__</code>  ：析构方法，当一个实例被销毁的时候调用的方法</li>\n<li><code>__str__</code>  ：字符串方法，定义当被  <code>str()</code>  调用或者打印对象时的行为</li>\n<li><code>__lt__</code>  ：定义小于号的行为： <code>x &lt; y</code>  调用  <code>x.__lt__(y)</code></li>\n<li><code>__le__</code>  ：定义小于等于号的行为： <code>x &lt;= y</code>  调用  <code>x.__le__(y)</code></li>\n<li><code>__eq__</code>  ：定义等于号的行为： <code>x == y</code>  调用  <code>x.__eq__(y)</code></li>\n</ul>\n<p>之所以称之为魔法方法，是因为这些方法会在进行特定的操作时会被自动调用</p>\n<p>如果希望根据自己的程序定制自己特殊功能的类，那么就需要对这些方法进行重写</p>\n<p>参考：<a href=\"https://www.cnblogs.com/dachenzi/p/8185792.html\">Python 中类的魔术方法</a></p>\n<h2 id=\"pass-语句\"><a class=\"anchor\" href=\"#pass-语句\">#</a> pass 语句</h2>\n<p><code>pass</code>  是占位语句，用来保证函数（方法）或类定义的完整性，表示无内容</p>\n<p>如果因为某种原因写了无内容的函数定义或类定义，需使用  <code>pass</code>  语句来避免错误</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 继承</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">DerivedClassName</span><span class=\"token punctuation\">(</span>BaseClassName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">pass</span></pre></td></tr></table></figure><p>参考资料：</p>\n<ul>\n<li><a href=\"https://www.w3school.com.cn/python/python_classes.asp\">W3school：Python 类和对象</a></li>\n<li><a href=\"https://www.runoob.com/python3/python3-class.html\">菜鸟教程：Python3 面向对象</a></li>\n</ul>\n<h1 id=\"封装\"><a class=\"anchor\" href=\"#封装\">#</a> 封装</h1>\n<p>在程序设计中，封装（Encapsulation）是对具体对象的一种抽象，即将某些部分隐藏起来（即，定义成私有成员），在程序外部看不到（即，其他程序无法调用）</p>\n<ul>\n<li>封装数据：保护隐私</li>\n<li>封装方法：隔离复杂度（只保留部分接口对外使用）</li>\n</ul>\n<h2 id=\"私有成员\"><a class=\"anchor\" href=\"#私有成员\">#</a> 私有成员</h2>\n<p>类对象无法直接访问私有成员，但类内其它成员可以直接使用私有成员</p>\n<p>私有成员变量：</p>\n<ul>\n<li>定义：变量名以  <code>__</code>  （2 个下划线）开头，例如： <code>__private_attrs</code></li>\n<li>声明该属性为私有属性，只能在类的内部使用，不能在类的外部使用或直接访问</li>\n<li>在类内部的访问方式为： <code>self.__private_attrs</code></li>\n</ul>\n<p>私有成员方法（封装的方法）：</p>\n<ul>\n<li>方法名以  <code>__</code>  （2 个下划线）开头，例如： <code>__private_method</code></li>\n<li>声明该方法为私有方法，只能在类的内部调用，不能在类的外部调用</li>\n<li>在类内部的调用方式为： <code>self.__private_method()</code></li>\n</ul>\n<blockquote>\n<p>与 java 等语言不同，Python 的封装并不是真正意义上的外部无法调用。在 Python 中，如果需要在类外调用封装的属性或方法，须采用  <code>对象名._类名__方法名</code>  和  <code>对象名._类名__变量名</code>  的方式（不建议调用）</p>\n</blockquote>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Foo</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> height<span class=\"token punctuation\">,</span> weight<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>     <span class=\"token comment\"># 构造方法</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        self<span class=\"token punctuation\">.</span>height <span class=\"token operator\">=</span> height</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        self<span class=\"token punctuation\">.</span>weight <span class=\"token operator\">=</span> weight</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">__heightpow</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>      <span class=\"token comment\"># 私有方法</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">.</span>height <span class=\"token operator\">*</span> self<span class=\"token punctuation\">.</span>height</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">tell_bmi</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">.</span>weight <span class=\"token operator\">/</span> self<span class=\"token punctuation\">.</span>__heightpow<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token comment\"># 私有成员可以被类内其它成员直接使用</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>egon <span class=\"token operator\">=</span> Foo<span class=\"token punctuation\">(</span><span class=\"token number\">1.7</span><span class=\"token punctuation\">,</span> <span class=\"token number\">120</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>egon<span class=\"token punctuation\">.</span>tell_bmi<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>egon<span class=\"token punctuation\">.</span>_Foo__heightpow<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>   <span class=\"token comment\"># 尽管是私有成员方法，但也可以在类外调用以供查看</span></pre></td></tr></table></figure><h2 id=\"property\"><a class=\"anchor\" href=\"#property\">#</a> property</h2>\n<p>property 是一种特殊的属性，访问它时会执行一段功能（函数）然后返回值（就是一个装饰器）</p>\n<p>将一个类的方法  <code>func_name</code>  用 propery 装饰以后，类对象  <code>obj</code>  可直接通过  <code>obj.func_name</code>  去使用，以遵循统一访问的原则</p>\n<blockquote>\n<p>被 property 装饰的属性会优先于对象的属性被使用</p>\n</blockquote>\n<p>被 propery 装饰的属性分成三种：</p>\n<ul>\n<li>property</li>\n<li>被装饰的函数名.setter</li>\n<li>被装饰的函数名.deleter</li>\n</ul>\n<p>例如， <code>@property</code>  把类中的方法伪装成属性：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> math <span class=\"token keyword\">import</span> pi</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Circle</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        self<span class=\"token punctuation\">.</span>radius <span class=\"token operator\">=</span> radius</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token decorator annotation punctuation\">@property</span>   <span class=\"token comment\"># 装饰器：将一个方法当成一个属性用</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">area</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">.</span>radius <span class=\"token operator\">*</span> self<span class=\"token punctuation\">.</span>radius <span class=\"token operator\">*</span> pi</pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token decorator annotation punctuation\">@property</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">peimeter</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token number\">2</span> <span class=\"token operator\">*</span> pi <span class=\"token operator\">*</span> self<span class=\"token punctuation\">.</span>radius</pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>c <span class=\"token operator\">=</span> Circle<span class=\"token punctuation\">(</span><span class=\"token number\">10</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>c<span class=\"token punctuation\">.</span>area<span class=\"token punctuation\">)</span>       <span class=\"token comment\"># 当成一个属性来调用（即，不需要加括号）</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>c<span class=\"token punctuation\">.</span>peimeter<span class=\"token punctuation\">)</span>   <span class=\"token comment\"># 当成一个属性来调用（即，不需要加括号）</span></pre></td></tr></table></figure><p>注意：此时的特性 area 和 perimeter 不能被赋值</p>\n<p>参考资料：</p>\n<ul>\n<li><a href=\"https://www.cnblogs.com/Michael--chen/p/6740455.html\">Python 基础之封装</a></li>\n<li><a href=\"https://www.cnblogs.com/haiyan123/p/7367343.html\">Python 封装</a></li>\n</ul>\n<h1 id=\"继承\"><a class=\"anchor\" href=\"#继承\">#</a> 继承</h1>\n<p>继承允许我们定义继承（复制）另一个类的所有方法和属性的类</p>\n<p>继承可以分为：</p>\n<ul>\n<li>单继承：一个类继承另一个类</li>\n<li>多继承：一个类继承多个类，按照顺序从左向右依次继承</li>\n</ul>\n<p>父类是被继承的类，也称为基类</p>\n<p>子类是从另一个类继承所得的类，也称为派生类</p>\n<h2 id=\"单继承\"><a class=\"anchor\" href=\"#单继承\">#</a> 单继承</h2>\n<blockquote>\n<p>任何类都可以是父类，因此，创建父类的语法与创建任何其他类相同</p>\n</blockquote>\n<p>要创建从其他类继承功能的类，只需在创建子类时将父类作为参数传递即可：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">DerivedClassName</span><span class=\"token punctuation\">(</span>BaseClassName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token operator\">&lt;</span>statement<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token operator\">&lt;</span>statement<span class=\"token operator\">-</span>N<span class=\"token operator\">></span></pre></td></tr></table></figure><p>其中， <code>DerivedClassName</code>  为子类名， <code>BaseClassName</code>  为父类名</p>\n<blockquote>\n<p>如果不希望向子类中添加任何其他属性或方法，可使用  <code>pass</code>  关键字</p>\n</blockquote>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 创建 Person 类</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Person</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> fname<span class=\"token punctuation\">,</span> lname<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        self<span class=\"token punctuation\">.</span>firstname <span class=\"token operator\">=</span> fname</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        self<span class=\"token punctuation\">.</span>lastname <span class=\"token operator\">=</span> lname</pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">print_name</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">.</span>firstname<span class=\"token punctuation\">,</span> self<span class=\"token punctuation\">.</span>lastname<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 创建 Person 类对象，并执行 print_name 方法</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>x <span class=\"token operator\">=</span> Person<span class=\"token punctuation\">(</span><span class=\"token string\">\"Bill\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Gates\"</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>x<span class=\"token punctuation\">.</span>print_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token comment\"># 创建继承自 Person 类的子类 Student</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Student</span><span class=\"token punctuation\">(</span>Person<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> fname<span class=\"token punctuation\">,</span> lname<span class=\"token punctuation\">,</span> gra<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        self<span class=\"token punctuation\">.</span>firstname <span class=\"token operator\">=</span> fname</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        self<span class=\"token punctuation\">.</span>lastname <span class=\"token operator\">=</span> lname</pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        self<span class=\"token punctuation\">.</span>grade <span class=\"token operator\">=</span> gra</pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">print_info</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">.</span>firstname<span class=\"token punctuation\">,</span> self<span class=\"token punctuation\">.</span>lastname<span class=\"token punctuation\">,</span> self<span class=\"token punctuation\">.</span>grade<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token comment\"># 使用 Student 类创建一个对象，然后执行 print_name 和 print_info 方法</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>y <span class=\"token operator\">=</span> Student<span class=\"token punctuation\">(</span><span class=\"token string\">\"Elon\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"Musk\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">6</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>y<span class=\"token punctuation\">.</span>print_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>y<span class=\"token punctuation\">.</span>print_info<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"多继承\"><a class=\"anchor\" href=\"#多继承\">#</a> 多继承</h2>\n<p>创建子类的语法：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">DerivedClassName</span><span class=\"token punctuation\">(</span>Base1<span class=\"token punctuation\">,</span> Base2<span class=\"token punctuation\">,</span> Base3<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token operator\">&lt;</span>statement<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token operator\">&lt;</span>statement<span class=\"token operator\">-</span>N<span class=\"token operator\">></span></pre></td></tr></table></figure><p>如果多个父类中含有同名的成员，那么默认按照从左向右顺序依次继承，先继承的保留，后继承的被覆盖</p>\n<h2 id=\"方法重写\"><a class=\"anchor\" href=\"#方法重写\">#</a> 方法重写</h2>\n<p>子类继承父类的成员属性和成员方法后，如果对其 “不满意”，可以在子类重写父类的方法</p>\n<p>即：在子类中重新定义同名的属性或方法</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Parent</span><span class=\"token punctuation\">:</span>           <span class=\"token comment\"># 定义父类</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">myMethod</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">print</span> <span class=\"token punctuation\">(</span><span class=\"token string\">'调用父类方法'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Child</span><span class=\"token punctuation\">(</span>Parent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>    <span class=\"token comment\"># 定义子类</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">myMethod</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 重写父类方法</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">print</span> <span class=\"token punctuation\">(</span><span class=\"token string\">'调用子类方法'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>c <span class=\"token operator\">=</span> Child<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>          <span class=\"token comment\"># 子类实例</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>c<span class=\"token punctuation\">.</span>myMethod<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>         <span class=\"token comment\"># 子类调用重写方法</span></pre></td></tr></table></figure><h2 id=\"调用父类同名成员\"><a class=\"anchor\" href=\"#调用父类同名成员\">#</a> 调用父类同名成员</h2>\n<p>一旦在子类中重写父类成员以后，子类的类对象调用成员时将是调用复写后的新成员</p>\n<p>如果需要使用被复写的父类的成员，需要特殊的调用方式:</p>\n<ul>\n<li>\n<p>方式一：通过父类调用（单继承</p>\n<ul>\n<li>调用父类成员变量： <code>父类名.成员变量</code></li>\n<li>调用父类成员方法： <code>父类名.成员方法(self)</code></li>\n</ul>\n</li>\n<li>\n<p>方式二：使用  <code>super()</code>  调用</p>\n<ul>\n<li>调用父类成员变量： <code>super().成员变量</code></li>\n<li>调用父类成员方法： <code>super().成员方法()</code></li>\n</ul>\n</li>\n</ul>\n<p>如果是单继承的情况，可以直接用父类名调用父类方法</p>\n<p>但是，如果是多继承的情况，可能会涉及到查找顺序（MRO）、重复调用（钻石继承）等种种问题，此时，推荐采用  <code>super()</code>  函数调用，以解决多重继承问题。具体可参考：<a href=\"https://www.runoob.com/python/python-func-super.html\">Python super () 函数</a></p>\n<p>参考资料：</p>\n<ul>\n<li><a href=\"https://www.w3school.com.cn/python/python_inheritance.asp\">Python 继承</a></li>\n</ul>\n<h1 id=\"类型注解\"><a class=\"anchor\" href=\"#类型注解\">#</a> 类型注解</h1>\n<p>类型注解：在代码中涉及数据交互的地方，提供数据类型的注解（显式的说明）</p>\n<ul>\n<li>帮助第三方 IDE 工具（如 PyCharm）对代码进行类型推断，协助做代码提示</li>\n<li>帮助开发者自身对变量进行类型注释</li>\n</ul>\n<p>有两种注解：</p>\n<ul>\n<li>变量的类型注解</li>\n<li>函数（方法）的类型注解</li>\n</ul>\n<p>需注意：类型注解仅仅是提示性的，不是决定性的，并不会真正地对类型做验证和判断（也就是说：即使注解的数据类型与实际数据类型不一致，程序也不会报错）</p>\n<h2 id=\"变量的类型注解\"><a class=\"anchor\" href=\"#变量的类型注解\">#</a> 变量的类型注解</h2>\n<p>事实上，对于显式的变量定义，一般无需注解。即便不写类型注解，也可以明确知晓变量的类型</p>\n<p>一般而言，在无法直接看出变量类型时（例如，将函数返回值赋给一个变量时），才会添加变量的类型注解</p>\n<h3 id=\"方式一常用\"><a class=\"anchor\" href=\"#方式一常用\">#</a> 方式一（常用）</h3>\n<p>基础语法：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>变量<span class=\"token punctuation\">:</span> 类型</pre></td></tr></table></figure><p>例如：</p>\n<p>基础数据类型注解：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>var1<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span> <span class=\"token operator\">=</span> <span class=\"token number\">3</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>var2<span class=\"token punctuation\">:</span> <span class=\"token builtin\">float</span> <span class=\"token operator\">=</span> <span class=\"token number\">3.14</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>var3<span class=\"token punctuation\">:</span> <span class=\"token builtin\">bool</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">True</span></pre></td></tr></table></figure><p>类对象类型注解:</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Person</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">pass</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>p<span class=\"token punctuation\">:</span> Person <span class=\"token operator\">=</span> Person<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>容器类型简易注解：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>mylist<span class=\"token punctuation\">:</span> <span class=\"token builtin\">list</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>mytuple<span class=\"token punctuation\">:</span> <span class=\"token builtin\">tuple</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>myset<span class=\"token punctuation\">:</span> <span class=\"token builtin\">set</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>mydict<span class=\"token punctuation\">:</span> <span class=\"token builtin\">dict</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"b\"</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>mystr<span class=\"token punctuation\">:</span> <span class=\"token builtin\">str</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"Jiankychen\"</span></pre></td></tr></table></figure><p>容器类型详细注解：</p>\n<ul>\n<li>元组类型设置类型详细注解：需要将每一个元素都标记出来</li>\n<li>字典类型设置类型详细注解：需要 2 个类型，第一个是 key ，第二个是 value</li>\n</ul>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>mylist<span class=\"token punctuation\">:</span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>mytuple<span class=\"token punctuation\">:</span> <span class=\"token builtin\">tuple</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">str</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">bool</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">True</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>myset<span class=\"token punctuation\">:</span> <span class=\"token builtin\">set</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>mydict<span class=\"token punctuation\">:</span> <span class=\"token builtin\">dict</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"a\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"b\"</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"方式二\"><a class=\"anchor\" href=\"#方式二\">#</a> 方式二</h3>\n<p>除了使用  <code>变量: 类型</code>  这种语法做注解外，也可以 <strong>在注释中进行类型注解</strong></p>\n<p>基础语法：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># type: 类型</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Person</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">pass</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">3.14159</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>var1 <span class=\"token operator\">=</span> random<span class=\"token punctuation\">.</span>randint<span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">10</span><span class=\"token punctuation\">)</span>    <span class=\"token comment\"># type: int</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>var2 <span class=\"token operator\">=</span> Person<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>                 <span class=\"token comment\"># type: Person</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>var3 <span class=\"token operator\">=</span> func<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>                   <span class=\"token comment\"># type: float</span></pre></td></tr></table></figure><h2 id=\"函数方法的类型注解\"><a class=\"anchor\" href=\"#函数方法的类型注解\">#</a> 函数（方法）的类型注解</h2>\n<h3 id=\"形参注解\"><a class=\"anchor\" href=\"#形参注解\">#</a> 形参注解</h3>\n<p>函数（方法）的形参类型注解语法：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func_name</span><span class=\"token punctuation\">(</span>形参名<span class=\"token punctuation\">:</span> 类型<span class=\"token punctuation\">,</span> 形参名<span class=\"token punctuation\">:</span> 类型<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">add</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">return</span> x <span class=\"token operator\">+</span> y</pre></td></tr></table></figure><h3 id=\"返回值注解\"><a class=\"anchor\" href=\"#返回值注解\">#</a> 返回值注解</h3>\n<p>函数（方法）的返回值也是可以添加类型注解的，语法如下：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func_name</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> 返回值类型<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">:</span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">return</span> data</pre></td></tr></table></figure><h2 id=\"union-类型\"><a class=\"anchor\" href=\"#union-类型\">#</a> Union 类型</h2>\n<p>通过  <code>Union</code>  可以定义联合类型</p>\n<ul>\n<li>导包： <code>from typing import Union</code></li>\n<li>使用： <code>Union[类型, ..., 类型]</code></li>\n</ul>\n<p>在变量注解、函数（方法）形参和返回值注解中，均可使用  <code>Union</code>  联合类型</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> typing <span class=\"token keyword\">import</span> Union</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>mylist<span class=\"token punctuation\">:</span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">[</span>Union<span class=\"token punctuation\">[</span><span class=\"token builtin\">str</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"3\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"4\"</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\"># list 元素的数据类型可能是 str ，也可能是 int</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>mydict<span class=\"token punctuation\">:</span> <span class=\"token builtin\">dict</span><span class=\"token punctuation\">[</span><span class=\"token builtin\">str</span><span class=\"token punctuation\">,</span> Union<span class=\"token punctuation\">[</span><span class=\"token builtin\">str</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Jiankychen\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"age\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">24</span><span class=\"token punctuation\">&#125;</span>      <span class=\"token comment\"># value 的数据类型可能是 str ，也可能是 int</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">:</span> Union<span class=\"token punctuation\">[</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> Union<span class=\"token punctuation\">[</span><span class=\"token builtin\">int</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">return</span> data</pre></td></tr></table></figure><p>参考资料：</p>\n<ul>\n<li><a href=\"https://www.bilibili.com/video/BV1qW4y1a7fU?p=122\">黑马程序员 Python 教程：类型注解</a></li>\n</ul>\n<h1 id=\"多态\"><a class=\"anchor\" href=\"#多态\">#</a> 多态</h1>\n<p>多态：多种状态，即：对于某个行为（函数），使用不同的对象将会得到不同的状态</p>\n<p>例如： <code>Cat</code>  类和  <code>Dog</code>  类都有  <code>speak</code>  成员方法， <code>Cat</code>  类对象和  <code>Dog</code>  类对象都能被传入  <code>command</code>  函数；但是由于两个类定义的  <code>speak</code>  方法的功能不一致，传入不同类的对象就会得到不同的状态</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Cat</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">speak</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">print</span> <span class=\"token string\">\"meow!\"</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Dog</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">speak</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">print</span> <span class=\"token string\">\"woof!\"</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">command</span><span class=\"token punctuation\">(</span>pet<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    pet<span class=\"token punctuation\">.</span>speak<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>cat <span class=\"token operator\">=</span> Cat<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>command<span class=\"token punctuation\">(</span>cat<span class=\"token punctuation\">)</span>    <span class=\"token comment\"># 输出：meow!</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>dog <span class=\"token operator\">=</span> Dog<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>command<span class=\"token punctuation\">(</span>dog<span class=\"token punctuation\">)</span>    <span class=\"token comment\"># 输出：woof!</span></pre></td></tr></table></figure><p>多态常作用在继承关系上，比如：定义函数（方法），通过类型注解声明需要父类对象，实际传入子类对象进行工作，从而获得不同的工作状态</p>\n<p>例如，可以将上例中的代码修改为：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Pet</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">speak</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">pass</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Cat</span><span class=\"token punctuation\">(</span>Pet<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">speak</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">print</span> <span class=\"token string\">\"meow!\"</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Dog</span><span class=\"token punctuation\">(</span>Pet<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">def</span> <span class=\"token function\">speak</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">print</span> <span class=\"token string\">\"woof!\"</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">command</span><span class=\"token punctuation\">(</span>pet<span class=\"token punctuation\">:</span> Pet<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>  <span class=\"token comment\"># 函数形参的类型注解</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    pet<span class=\"token punctuation\">.</span>speak<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>cat <span class=\"token operator\">=</span> Cat<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>command<span class=\"token punctuation\">(</span>cat<span class=\"token punctuation\">)</span>    <span class=\"token comment\"># 输出：meow!</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>dog <span class=\"token operator\">=</span> Dog<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>command<span class=\"token punctuation\">(</span>dog<span class=\"token punctuation\">)</span>    <span class=\"token comment\"># 输出：woof!</span></pre></td></tr></table></figure><h2 id=\"抽象类接口\"><a class=\"anchor\" href=\"#抽象类接口\">#</a> 抽象类（接口）</h2>\n<p>抽象方法：没有具体实现的方法（即：方法体是  <code>pass</code>  语句）</p>\n<p>抽象类：包含抽象方法的类，也可以称之为 接口，比如上例中的  <code>Pet</code>  类</p>\n<p>抽象类相当于定义一个标准，包含了一些抽象的方法，要求子类必须实现</p>\n<p>这种设计的意义在于：</p>\n<ul>\n<li>父类用来确定有哪些方法</li>\n<li>具体的方法实现，由子类自行决定</li>\n</ul>\n<p>参考资料：</p>\n<ul>\n<li><a href=\"https://www.bilibili.com/video/BV1qW4y1a7fU?p=123\">黑马程序员 Python 教程：多态</a></li>\n</ul>\n",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/python-pandas.html",
            "url": "https://jiankychen.github.io/python-pandas.html",
            "title": "pandas 基础",
            "date_published": "2023-01-20T13:02:02.000Z",
            "content_html": "<h1 id=\"安装及导入\"><a class=\"anchor\" href=\"#安装及导入\">#</a> 安装及导入</h1>\n<h2 id=\"安装\"><a class=\"anchor\" href=\"#安装\">#</a> 安装</h2>\n<p>可以使用 pip 安装</p>\n<pre><code>pip install pandas\n</code></pre>\n<h2 id=\"导入\"><a class=\"anchor\" href=\"#导入\">#</a> 导入</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">import</span> pandas <span class=\"token keyword\">as</span> pd</pre></td></tr></table></figure><h1 id=\"数据结构\"><a class=\"anchor\" href=\"#数据结构\">#</a> 数据结构</h1>\n<h2 id=\"series\"><a class=\"anchor\" href=\"#series\">#</a> Series</h2>\n<p>Series 是一种类似于一维数组的对象，它由一组数据（各种 Numpy 数据类型）以及一组与之相关的数据标签（即索引）组成</p>\n<blockquote>\n<p>Series 只有行索引</p>\n</blockquote>\n<p>例如，创建一个 Series 对象：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>ser <span class=\"token operator\">=</span> pd<span class=\"token punctuation\">.</span>Series<span class=\"token punctuation\">(</span>data <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> index <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'a'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'c'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>其内容为：</p>\n<pre><code>a   1\nb   2\nc   3\n</code></pre>\n<p><a href=\"https://pandas.pydata.org/docs/reference/series.html\">Series 的各种方法</a></p>\n<h2 id=\"dataframe\"><a class=\"anchor\" href=\"#dataframe\">#</a> DataFrame</h2>\n<p>DataFrame 是一个表格型的数据结构，它含有一组有序的列，每列可以是不同的值类型（数值、字符串、布尔型值）</p>\n<blockquote>\n<p>DataFrame 既有行索引又有列索引</p>\n</blockquote>\n<p>例如，创建一个 DataFrame 对象：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>df <span class=\"token operator\">=</span> pd<span class=\"token punctuation\">.</span>DataFrame<span class=\"token punctuation\">(</span>data <span class=\"token operator\">=</span> np<span class=\"token punctuation\">.</span>array<span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> columns <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'a'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'c'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>其内容为：</p>\n<pre><code>   a  b  c\n0  1  2  3\n1  4  5  6\n</code></pre>\n<p><a href=\"https://pandas.pydata.org/docs/reference/frame.html\">DataFrame 的各种方法</a></p>\n<p>下面将以 DataFrame 对象为例来介绍 pandas 的基本用法</p>\n<h1 id=\"数据输入\"><a class=\"anchor\" href=\"#数据输入\">#</a> 数据输入</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 使用 read_csv 读取 csv 文件</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df <span class=\"token operator\">=</span> pd<span class=\"token punctuation\">.</span>read_csv<span class=\"token punctuation\">(</span><span class=\"token string\">'file_name'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 或者：使用 read_csv 读取 csv 文件</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># read_csv 默认使用 '\\t' 作为数据分隔符，需将分隔符设为 ','</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>df <span class=\"token operator\">=</span> pd<span class=\"token punctuation\">.</span>read_table<span class=\"token punctuation\">(</span><span class=\"token string\">'file_name'</span><span class=\"token punctuation\">,</span> sep<span class=\"token operator\">=</span><span class=\"token string\">','</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\"># 读取 excel 文件</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>pd<span class=\"token punctuation\">.</span>read_excel<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 读取 json 文件</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>pd<span class=\"token punctuation\">.</span>json<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 读取 xml 文件</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>pd<span class=\"token punctuation\">.</span>read_xml<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h1 id=\"数据输出\"><a class=\"anchor\" href=\"#数据输出\">#</a> 数据输出</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 将 DataFrame 对象写入 csv 文件</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df<span class=\"token punctuation\">.</span>to_csv<span class=\"token punctuation\">(</span><span class=\"token string\">'file_name'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 写入 excel 文件</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>df<span class=\"token punctuation\">.</span>to_excel<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 写入 json 文件</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>to_json<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 写入 xml 文件</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>df<span class=\"token punctuation\">.</span>to_xml<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p><a href=\"http://pandas.pydata.org/docs/reference/io.html\">pandas 读取 / 写入文件</a></p>\n<h1 id=\"查看数据\"><a class=\"anchor\" href=\"#查看数据\">#</a> 查看数据</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的头部数据（默认显示 5 条数据）</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df<span class=\"token punctuation\">.</span>head<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的尾部数据（默认显示 5 条数据）</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>df<span class=\"token punctuation\">.</span>tail<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的索引</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>index</pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的列名</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>df<span class=\"token punctuation\">.</span>columns</pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的统计信息</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>df<span class=\"token punctuation\">.</span>describe<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的摘要</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>df<span class=\"token punctuation\">.</span>info<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token comment\"># DataFrame 对象的形状</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>df<span class=\"token punctuation\">.</span>shape</pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token comment\"># 查看数据是否为空</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>df<span class=\"token punctuation\">.</span>isnull<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token comment\"># 查看各数据类型</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>df<span class=\"token punctuation\">.</span>dtypes</pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token comment\"># 查看某一列的所有值</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>df<span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token string\">'column_name'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>         <span class=\"token comment\"># 方法一</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>df<span class=\"token punctuation\">.</span>loc<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'column_name'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>  <span class=\"token comment\"># 方法二</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token comment\"># 查看某一列的变量名及种类</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>df<span class=\"token punctuation\">[</span><span class=\"token string\">'column_name'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value_counts<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>    <span class=\"token comment\"># 方法一</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>df<span class=\"token punctuation\">[</span><span class=\"token string\">'column_name'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>unique<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>          <span class=\"token comment\"># 方法二</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre></pre></td></tr><tr><td data-num=\"36\"></td><td><pre><span class=\"token comment\"># 查看满足条件的值</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>df<span class=\"token punctuation\">[</span>condition<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre></pre></td></tr><tr><td data-num=\"39\"></td><td><pre><span class=\"token comment\"># 最大值对应的索引</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>df<span class=\"token punctuation\">.</span>idxmax<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre></pre></td></tr><tr><td data-num=\"42\"></td><td><pre><span class=\"token comment\"># 最小值对应的索引</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>df<span class=\"token punctuation\">.</span>idxmin<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h1 id=\"缺失值处理\"><a class=\"anchor\" href=\"#缺失值处理\">#</a> 缺失值处理</h1>\n<p>pandas 主要用  <code>np.nan</code>  表示缺失数据</p>\n<p>一般情况下，运算时默认排除缺失值</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查找缺失值</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df<span class=\"token punctuation\">.</span>isnull<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 查找非缺失值</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>df<span class=\"token punctuation\">.</span>notnull<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 删除所有含缺失值的行</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>dropna<span class=\"token punctuation\">(</span>how<span class=\"token operator\">=</span><span class=\"token string\">'any'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 用 0 填充缺失值</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>df<span class=\"token punctuation\">.</span>fillna<span class=\"token punctuation\">(</span>value<span class=\"token operator\">=</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h1 id=\"重复值处理\"><a class=\"anchor\" href=\"#重复值处理\">#</a> 重复值处理</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查看 DataFrame 数据中的重复值</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df<span class=\"token punctuation\">.</span>duplicated<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 统计 DataFrame 数据中重复值的个数</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>df<span class=\"token punctuation\">.</span>duplicated<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token builtin\">sum</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 删除 DataFrame 数据中的重复值</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>drop_duplicates<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h1 id=\"索引变换\"><a class=\"anchor\" href=\"#索引变换\">#</a> 索引变换</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 重置索引</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df<span class=\"token punctuation\">.</span>reset_index<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 将现有的列设为索引</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>df<span class=\"token punctuation\">.</span>set_index<span class=\"token punctuation\">(</span><span class=\"token string\">'column_name'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 修改索引与列标签</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>reindex<span class=\"token punctuation\">(</span>index<span class=\"token operator\">=</span>index_labels<span class=\"token punctuation\">,</span> columns<span class=\"token operator\">=</span>column_labels<span class=\"token punctuation\">)</span>   <span class=\"token comment\"># 方法一</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>df<span class=\"token punctuation\">.</span>rename<span class=\"token punctuation\">(</span>index<span class=\"token operator\">=</span>index_labels<span class=\"token punctuation\">,</span> columns<span class=\"token operator\">=</span>column_labels<span class=\"token punctuation\">)</span>    <span class=\"token comment\"># 方法二</span></pre></td></tr></table></figure><p><a href=\"https://zhuanlan.zhihu.com/p/277008403\">reindex 和 rename</a></p>\n<h1 id=\"排序\"><a class=\"anchor\" href=\"#排序\">#</a> 排序</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 按索引排序</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df<span class=\"token punctuation\">.</span>sort_index<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 按行列的值排序</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>df<span class=\"token punctuation\">.</span>sort_values<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 按某一列排序</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>sort_values<span class=\"token punctuation\">(</span>by<span class=\"token operator\">=</span><span class=\"token string\">'column_name'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 按多列排序</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>df<span class=\"token punctuation\">.</span>sort_values<span class=\"token punctuation\">(</span>by<span class=\"token operator\">=</span><span class=\"token punctuation\">[</span><span class=\"token string\">'column_name_1'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'column_name_2'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>特别地，如果数据含有空值，可以用  <code>na_position</code>  参数处理空值，例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>df<span class=\"token punctuation\">.</span>sort_values<span class=\"token punctuation\">(</span>na_position<span class=\"token operator\">=</span><span class=\"token string\">'first'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h1 id=\"特征处理\"><a class=\"anchor\" href=\"#特征处理\">#</a> 特征处理</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>按照数据的值进行离散化</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>pd<span class=\"token punctuation\">.</span>cut<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 按照数据的数量进行离散化</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>pd<span class=\"token punctuation\">.</span>qcut<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 替换数据值</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>replace<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 替换数据值</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>df<span class=\"token punctuation\">.</span><span class=\"token builtin\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\"># one-hot 编码</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>pd<span class=\"token punctuation\">.</span>get_dummies<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>具体用法请参考 <a href=\"http://pandas.pydata.org/docs/reference/\">pandas Document</a></p>\n<h1 id=\"数据拼接\"><a class=\"anchor\" href=\"#数据拼接\">#</a> 数据拼接</h1>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 既可以横向拼接，又可以纵向拼接</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>pd<span class=\"token punctuation\">.</span>concat<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 横向拼接</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>pd<span class=\"token punctuation\">.</span>merge<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 横向拼接 DataFrame 对象</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>df<span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 纵向拼接 DataFrame 对象</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>df<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p><a href=\"https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html#\">Merge, join, concatenate and compare</a></p>\n<h1 id=\"数据分组\"><a class=\"anchor\" href=\"#数据分组\">#</a> 数据分组</h1>\n<ul>\n<li>分割：按条件把数据分割成多组</li>\n<li>应用：为每组单独应用函数</li>\n<li>组合：将处理结果组合成一个数据结构</li>\n</ul>\n<p>具体请参考：<a href=\"https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html#\">Groupby API</a></p>\n<h1 id=\"参考资料\"><a class=\"anchor\" href=\"#参考资料\">#</a> 参考资料</h1>\n<ul>\n<li><a href=\"http://pandas.pydata.org/docs/reference/\">pandas 官方文档</a></li>\n<li><a href=\"https://www.pypandas.cn/docs/getting_started/tutorials.html\">pandas 教程资料</a></li>\n<li><a href=\"https://www.pypandas.cn/docs/getting_started/10min.html\">十分钟入门 pandas</a></li>\n</ul>\n",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/python-conda.html",
            "url": "https://jiankychen.github.io/python-conda.html",
            "title": "conda 常用命令",
            "date_published": "2023-01-19T03:47:56.000Z",
            "content_html": "<h1 id=\"conda-基本操作\"><a class=\"anchor\" href=\"#conda-基本操作\">#</a> conda 基本操作</h1>\n<h2 id=\"查看-conda-版本\"><a class=\"anchor\" href=\"#查看-conda-版本\">#</a> 查看 conda 版本</h2>\n<pre><code>conda --version\n</code></pre>\n<h2 id=\"更新-conda\"><a class=\"anchor\" href=\"#更新-conda\">#</a> 更新 conda</h2>\n<pre><code>conda update conda\n</code></pre>\n<h2 id=\"查看-conda-环境配置\"><a class=\"anchor\" href=\"#查看-conda-环境配置\">#</a> 查看 conda 环境配置</h2>\n<pre><code>conda config --show\n</code></pre>\n<h2 id=\"设置镜像源\"><a class=\"anchor\" href=\"#设置镜像源\">#</a> 设置镜像源</h2>\n<pre><code># 设置清华镜像\nconda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/\nconda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/\nconda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/\nconda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda/\n\n# 设置 bioconda\nconda config --add channels bioconda\nconda config --add channels conda-forge\n\n# 设置搜索时显示通道地址\nconda config --set show_channel_urls yes\n</code></pre>\n<h2 id=\"查询指定命令的功能\"><a class=\"anchor\" href=\"#查询指定命令的功能\">#</a> 查询指定命令的功能</h2>\n<pre><code>conda command_name --help\n</code></pre>\n<h1 id=\"管理环境\"><a class=\"anchor\" href=\"#管理环境\">#</a> 管理环境</h1>\n<h2 id=\"显示所有虚拟环境\"><a class=\"anchor\" href=\"#显示所有虚拟环境\">#</a> 显示所有虚拟环境</h2>\n<pre><code>conda env list\n</code></pre>\n<h2 id=\"创建虚拟环境\"><a class=\"anchor\" href=\"#创建虚拟环境\">#</a> 创建虚拟环境</h2>\n<pre><code>conda create -n env_name package_name\n</code></pre>\n<p>如果需要指定 package 版本，可直接在 package_name 之后加上  <code>=</code>  号以及 package 版本号，例如：</p>\n<pre><code>conda create -n env_name python=3.x\n</code></pre>\n<p>如果需要安装多个 package ，在 env_name 之后用空格分隔多个 package_name 即可，例如：</p>\n<pre><code>conda create -n python310 python=3.10 numpy pandas\n</code></pre>\n<h2 id=\"激活环境\"><a class=\"anchor\" href=\"#激活环境\">#</a> 激活环境</h2>\n<pre><code>activate env_name\n</code></pre>\n<h2 id=\"退出环境\"><a class=\"anchor\" href=\"#退出环境\">#</a> 退出环境</h2>\n<pre><code>deactivate env_name\n</code></pre>\n<h2 id=\"删除虚拟环境\"><a class=\"anchor\" href=\"#删除虚拟环境\">#</a> 删除虚拟环境</h2>\n<pre><code>conda env remove -n env_name\n</code></pre>\n<h2 id=\"导出虚拟环境\"><a class=\"anchor\" href=\"#导出虚拟环境\">#</a> 导出虚拟环境</h2>\n<pre><code>conda env export --name env_name &gt; environment.yml\n</code></pre>\n<h2 id=\"导入虚拟环境\"><a class=\"anchor\" href=\"#导入虚拟环境\">#</a> 导入虚拟环境</h2>\n<pre><code>conda env create -n env_name -f environment.yml\n</code></pre>\n<h1 id=\"管理-package\"><a class=\"anchor\" href=\"#管理-package\">#</a> 管理 package</h1>\n<h2 id=\"查看当前环境包含的所有-package\"><a class=\"anchor\" href=\"#查看当前环境包含的所有-package\">#</a> 查看当前环境包含的所有 package</h2>\n<pre><code>conda list\n</code></pre>\n<h2 id=\"更新当前环境包含的所有-package\"><a class=\"anchor\" href=\"#更新当前环境包含的所有-package\">#</a> 更新当前环境包含的所有 package</h2>\n<pre><code>conda upgrade --all\n</code></pre>\n<h2 id=\"更新指定-package\"><a class=\"anchor\" href=\"#更新指定-package\">#</a> 更新指定 package</h2>\n<pre><code>conda update package_name\n</code></pre>\n<h2 id=\"安装指定-package\"><a class=\"anchor\" href=\"#安装指定-package\">#</a> 安装指定 package</h2>\n<pre><code>conda install package_name\n</code></pre>\n<p>安装装多个 package ：</p>\n<pre><code>conda installl package_name_1 package_name_2 package_name_3\n</code></pre>\n<p>安装固定版本的 package ：</p>\n<pre><code>conda install package_name=package_version_number\n</code></pre>\n<h2 id=\"移除指定-package\"><a class=\"anchor\" href=\"#移除指定-package\">#</a> 移除指定 package</h2>\n<pre><code>conda remove package_name \n</code></pre>\n<p>参考资料：</p>\n<ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/67745160\">conda 常用命令</a></li>\n<li><a href=\"https://blog.csdn.net/chenxy_bwave/article/details/119996001\">Anaconda conda 常用命令：从入门到精通</a></li>\n</ul>\n",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/python-modules.html",
            "url": "https://jiankychen.github.io/python-modules.html",
            "title": "Python 异常、模块、包",
            "date_published": "2023-01-15T10:19:13.000Z",
            "content_html": "<h1 id=\"异常\"><a class=\"anchor\" href=\"#异常\">#</a> 异常</h1>\n<p>异常是指程序运行的过程中出现了错误</p>\n<blockquote>\n<p>bug 就是指异常，历史上因为小虫子导致计算机失灵，所以延续至今，bug 就代表软件出现错误</p>\n</blockquote>\n<h2 id=\"异常的捕获\"><a class=\"anchor\" href=\"#异常的捕获\">#</a> 异常的捕获</h2>\n<p>异常处理（捕获异常）：针对可能出现的异常，提前做好准备，当真的出现异常时，可以有后续处置，以免其导致程序无法正常运行</p>\n<h3 id=\"捕获常规异常\"><a class=\"anchor\" href=\"#捕获常规异常\">#</a> 捕获常规异常</h3>\n<p>语法：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    尝试执行的代码</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    若出现异常，将会执行本段代码</pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 尝试以 'r' 模式打开文件，如果文件不存在，则以 'w' 方式打开</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    f <span class=\"token operator\">=</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'linux.txt'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'r'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    f <span class=\"token operator\">=</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'linux.txt'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'w'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"捕获指定异常\"><a class=\"anchor\" href=\"#捕获指定异常\">#</a> 捕获指定异常</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    尝试执行的代码</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> ErrorType <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    若出现类型为 ErrorType 的异常，将会执行本段代码</pre></td></tr></table></figure><p>其中，ErrorType 是指要捕获的异常类型</p>\n<p>注意：如果 “尝试执行的代码” 的异常类型和要捕获的异常类型不一致，则无法捕获异常</p>\n<p>常见的异常类型如下表所示：</p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:center\">类名</th>\n<th style=\"text-align:center\">描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\"><code>SyntaxError</code></td>\n<td style=\"text-align:center\">发生语法错误时引发</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>FileNotFoundError</code></td>\n<td style=\"text-align:center\">未找到指定文件或目录时引发</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>NameError</code></td>\n<td style=\"text-align:center\">找不到指定名称的变量时引发</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>ZeroDivisionError</code></td>\n<td style=\"text-align:center\">除数为 0 时的异常</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>IndexError</code></td>\n<td style=\"text-align:center\">当使用超出列表范围的索引时引发</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>KeyError</code></td>\n<td style=\"text-align:center\">当使用映射不存在的键时引发</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>AttributeError</code></td>\n<td style=\"text-align:center\">当尝试访问未知对象属性时引发</td>\n</tr>\n<tr>\n<td style=\"text-align:center\"><code>TypeError</code></td>\n<td style=\"text-align:center\">当试图在使用 a 类型的场合使用 b 类型时引发</td>\n</tr>\n</tbody>\n</table>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> NameError <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'未定义 name 变量'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"捕获多个异常\"><a class=\"anchor\" href=\"#捕获多个异常\">#</a> 捕获多个异常</h3>\n<p>当需要捕获多个异常时，可以把要捕获的异常类型的名字，放到 except 后，并使用元组的方式进行书写</p>\n<p>例如：</p>\n<p>捕获多个异常（但不输出异常的具体描述）：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span> <span class=\"token operator\">/</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> <span class=\"token punctuation\">(</span>NameError<span class=\"token punctuation\">,</span> ZeroDivisionError<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">'错误...'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>捕获多个异常并输出异常的具体信息：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> <span class=\"token punctuation\">(</span>NameError<span class=\"token punctuation\">,</span> ZeroDivisionError<span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"捕获所有异常\"><a class=\"anchor\" href=\"#捕获所有异常\">#</a> 捕获所有异常</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    尝试执行的代码</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> Exception <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    若出现异常，将会执行本段代码</pre></td></tr></table></figure><p>注意： <code>except:</code>  与  <code>except Exception as e:</code>  这两种方式都可以捕获全部的异常</p>\n<h3 id=\"异常-else\"><a class=\"anchor\" href=\"#异常-else\">#</a> 异常 else</h3>\n<p><code>else</code>  表示没有异常时要执行的代码</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    尝试执行的代码</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> Exception <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    若出现异常，将会执行本段代码</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    若没有出现异常，将会执行本段代码</pre></td></tr></table></figure><h3 id=\"异常-finally\"><a class=\"anchor\" href=\"#异常-finally\">#</a> 异常 finally</h3>\n<p><code>finally</code>  表示无论是否异常都要执行的代码，例如关闭文件</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    尝试执行的代码</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">except</span> Exception <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    若出现异常，将会执行本段代码</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    若没有出现异常，将会执行本段代码</pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">finally</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    无论是否出现异常，都会执行本段代码</pre></td></tr></table></figure><h3 id=\"异常的传递\"><a class=\"anchor\" href=\"#异常的传递\">#</a> 异常的传递</h3>\n<p>异常具有传递性：</p>\n<ul>\n<li>\n<p>当函数 / 方法执行出现异常，会将异常传递给函数 / 方法的调用一方</p>\n</li>\n<li>\n<p>如果传递到主程序，仍然没有异常处理，程序才会被终止</p>\n</li>\n</ul>\n<p>利用异常具有传递性的特点，当我们想要保证程序不会因为异常崩溃的时候，就可以在  <code>main</code>  函数中设置异常捕获，由于无论在整个程序哪里发生异常，最终都会传递到  <code>main</code>  函数中，这样就可以确保所有的异常都会被捕获</p>\n<h1 id=\"模块\"><a class=\"anchor\" href=\"#模块\">#</a> 模块</h1>\n<p>Python 模块（Module），是一个 Python 文件，以  <code>.py</code>  为后缀名</p>\n<p>模块能定义函数、类和变量，模块里也能包含可执行的代码</p>\n<p>可以认为一个模块就是一个工具包，每一个工具包中都有各种不同的工具供我们使用，以实现各种不同的功能</p>\n<h2 id=\"导入模块\"><a class=\"anchor\" href=\"#导入模块\">#</a> 导入模块</h2>\n<p>在使用模块之前，需要先将模块导入 Python 程序</p>\n<p>常用的导入模块方式：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">import</span> module_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">from</span> module_name <span class=\"token keyword\">import</span> class_name<span class=\"token punctuation\">,</span> var_name<span class=\"token punctuation\">,</span> func_name</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">from</span> module_name <span class=\"token keyword\">import</span> <span class=\"token operator\">*</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">import</span> module_name <span class=\"token keyword\">as</span> nick_name</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">from</span> module_name <span class=\"token keyword\">import</span> func_name <span class=\"token keyword\">as</span> nick_name</pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li>module_name 表示模块</li>\n<li>class_name 表示模块内的类</li>\n<li>var_name 表示模块内的变量</li>\n<li>func_name 表示模块内的函数</li>\n<li>nick_name 表示为模块自定义的别名</li>\n</ul>\n<p>注意：导入模块时，module_name 不需要包含  <code>.py</code>  后缀</p>\n<h3 id=\"import-module_name\"><a class=\"anchor\" href=\"#import-module_name\">#</a> import module_name</h3>\n<p>使用  <code>import</code>  导入模块后，可以通过  <code>'.'</code>  来使用模块中的函数或类</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">import</span> module_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>module_name<span class=\"token punctuation\">.</span>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>module_name<span class=\"token punctuation\">.</span>class_name</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>module_name<span class=\"token punctuation\">.</span>var_name</pre></td></tr></table></figure><h3 id=\"from-module_name-import-func_name\"><a class=\"anchor\" href=\"#from-module_name-import-func_name\">#</a> from module_name import func_name</h3>\n<p>使用  <code>from … import …</code>  方式导入之后，无需添加前缀，直接调用即可</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> module_name <span class=\"token keyword\">import</span> func_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意，利用  <code>from</code>  把内容从模块中导入后，会导致相同名称的内容被覆盖，也就是说，不同模块的命名空间会在此处重叠</p>\n<h3 id=\"from-module_name-import\"><a class=\"anchor\" href=\"#from-module_name-import\">#</a> from module_name import *</h3>\n<p>导入模块全部内容</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> module_name <span class=\"token keyword\">import</span> <span class=\"token operator\">*</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>class_name</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>var_name</pre></td></tr></table></figure><h3 id=\"as-nick_name\"><a class=\"anchor\" href=\"#as-nick_name\">#</a> as nick_name</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 模块定义别名</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">import</span> module_name <span class=\"token keyword\">as</span> nick_name</pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 功能定义别名</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">from</span> module_name <span class=\"token keyword\">import</span> func_name <span class=\"token keyword\">as</span> func_nick_name</pre></td></tr></table></figure><h2 id=\"自定义模块\"><a class=\"anchor\" href=\"#自定义模块\">#</a> 自定义模块</h2>\n<p>每个 Python 文件都可以作为一个模块，模块的名字就是文件的名字</p>\n<p>因此，自定义模块只需在 Python 代码文件中正常写代码即可，通过 import、from 关键字导入（与导入 Python 内置模块一样）即可使用。但是需要注意，自定义模块名必须要符合标识符命名规则</p>\n<h3 id=\"__main__-变量\"><a class=\"anchor\" href=\"#__main__-变量\">#</a> __main__ 变量</h3>\n<p><code>if __main__ == “__main__”</code>  语句的作用：只有当含有该语句的 Python 程序是被直接 run 时，才会进入  <code>if</code>  内部。如果是被导入的，则无法进入  <code>if</code></p>\n<p>该功能常用于测试模块（即，希望某些代码在测试时运行、而在被导入时不运行）</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">test</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>a <span class=\"token operator\">+</span> b<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 只在当前文件中调用该函数，其他导入的文件内均不执行 test 函数调用</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">if</span> __name__ <span class=\"token operator\">==</span> <span class=\"token string\">'__main__'</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    test <span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>如果不加  <code>if __name__ == &quot;__main__&quot;</code>  语句：无论是当前文件，还是其他已经导入了该模块的文件，在运行的时候都会自动执行  <code>test</code>  函数的调用</p>\n<h3 id=\"__all__-变量\"><a class=\"anchor\" href=\"#__all__-变量\">#</a> __all__ 变量</h3>\n<p>如果一个模块文件中有  <code>__all__</code>  变量（该变量为列表对象），在使用  <code>from xxx import *</code>  导入该模块时，只能导入  <code>__all__</code>  列表中的元素</p>\n<p>因此， <code>__all__</code>  变量可以控制  <code>import *</code>  导入模块时的导入内容</p>\n<p>注意： <code>__all__</code>  变量 仅影响  <code>from ... import *</code>  这一导入方式</p>\n<p>例如，自定义如下模块：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>__all__ <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'Test_A'</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">Test_A</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    xxx</pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">Test_B</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    xxx</pre></td></tr></table></figure><p>通过  <code>from ... import *</code>  导入该模块后，只能使用  <code>Test_A</code>  函数，而不能使用  <code>Test_B</code>  函数</p>\n<h1 id=\"包\"><a class=\"anchor\" href=\"#包\">#</a> 包</h1>\n<p>如果 Python 模块太多，可以通过 Python 包（Package）来管理</p>\n<p>当我们的模块文件非常多时，包可以帮助我们管理这些模块，包的作用就是包含多个模块，但包的本质依然是模块</p>\n<ul>\n<li>\n<p>从物理上看：包就是一个文件夹，在该文件夹下包含了一个  <code>__init__.py</code>  文件，该文件夹可包含多个模块文件</p>\n</li>\n<li>\n<p>从逻辑上看：包的本质依然是模块</p>\n</li>\n</ul>\n<h2 id=\"自定义包\"><a class=\"anchor\" href=\"#自定义包\">#</a> 自定义包</h2>\n<p>基本步骤：</p>\n<ul>\n<li>新建 Python Package</li>\n<li>新建 Python 模块</li>\n</ul>\n<p>在 Pycharm 中，点击  <code>new --&gt; Python Package</code>  新建包后，包内部会自动创建  <code>__init__.py</code>  文件，这个文件控制着包的导入行为</p>\n<h2 id=\"导入包\"><a class=\"anchor\" href=\"#导入包\">#</a> 导入包</h2>\n<h3 id=\"import-xxx\"><a class=\"anchor\" href=\"#import-xxx\">#</a> import xxx</h3>\n<h4 id=\"导入所有模块\"><a class=\"anchor\" href=\"#导入所有模块\">#</a> 导入所有模块</h4>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">import</span> package_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>package_name<span class=\"token punctuation\">.</span>module_name<span class=\"token punctuation\">.</span>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h4 id=\"导入指定模块\"><a class=\"anchor\" href=\"#导入指定模块\">#</a> 导入指定模块</h4>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">import</span> package_name<span class=\"token punctuation\">.</span>module_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>package_name<span class=\"token punctuation\">.</span>module_name<span class=\"token punctuation\">.</span>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li>package_name 表示 Python Package 名称</li>\n<li>module_name 表示 Python Package 中的模块名称</li>\n<li>func_name 表示模块中的函数名称</li>\n</ul>\n<h3 id=\"from-xxx-import\"><a class=\"anchor\" href=\"#from-xxx-import\">#</a> from xxx import</h3>\n<h4 id=\"导入所有模块-2\"><a class=\"anchor\" href=\"#导入所有模块-2\">#</a> 导入所有模块</h4>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> package_name <span class=\"token keyword\">import</span> <span class=\"token operator\">*</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>module_name<span class=\"token punctuation\">.</span>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意：必须在  <code>__init__.py</code>  文件中添加  <code>__all__</code>  变量，用于控制  <code>from package_name import *</code>  导入的模块列表（类似于模块文件中的  <code>__all__</code>  变量）</p>\n<h4 id=\"导入指定模块-2\"><a class=\"anchor\" href=\"#导入指定模块-2\">#</a> 导入指定模块</h4>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> package_name <span class=\"token keyword\">import</span> module_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>module_name<span class=\"token punctuation\">.</span>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h4 id=\"导入指定模块中的指定函数\"><a class=\"anchor\" href=\"#导入指定模块中的指定函数\">#</a> 导入指定模块中的指定函数</h4>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">from</span> package_name<span class=\"token punctuation\">.</span>module_name <span class=\"token keyword\">import</span> func_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>func_name<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"第三方包\"><a class=\"anchor\" href=\"#第三方包\">#</a> 第三方包</h2>\n<p>在 Python 程序的生态中，有许多非常多的第三方包（非 Python 官方），可以极大的帮助我们提高开发效率，如：</p>\n<ul>\n<li>科学计算：numpy</li>\n<li>数据分析：pandas</li>\n<li>大数据计算：pyspark、apache-flink</li>\n<li>图形可视化：matplotlib、pyecharts</li>\n<li>人工智能：tensorflow</li>\n</ul>\n<p>注意，Python 没有内置这些第三方包，需要安装它们才可以导入使用</p>\n<p>可通过 Python 内置的 pip 安装指定的第三方包</p>\n<p>即，在命令行中输入：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pip install package_name</pre></td></tr></table></figure><p>pip 是连接外网进行下载，若下载速度相对较慢，可考虑通过国内的镜像源下载</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pip install <span class=\"token operator\">-</span>i https<span class=\"token punctuation\">:</span><span class=\"token operator\">//</span>pypi<span class=\"token punctuation\">.</span>tuna<span class=\"token punctuation\">.</span>tsinghua<span class=\"token punctuation\">.</span>edu<span class=\"token punctuation\">.</span>cn<span class=\"token operator\">/</span>simple package_name</pre></td></tr></table></figure>",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/python-files.html",
            "url": "https://jiankychen.github.io/python-files.html",
            "title": "Python 文件操作",
            "date_published": "2023-01-14T09:51:32.000Z",
            "content_html": "<h1 id=\"文件编码\"><a class=\"anchor\" href=\"#文件编码\">#</a> 文件编码</h1>\n<p>编码：一种规则集合，记录了内容和二进制间进行相互转换的逻辑</p>\n<p>计算机中有许多可用编码，例如：</p>\n<ul>\n<li>UTF-8</li>\n<li>GBK</li>\n<li>Big5</li>\n</ul>\n<p>UTF-8 是目前全球通用的编码格式</p>\n<p>除非有特殊需求，否则，一律以 UTF-8 格式进行文件编码即可</p>\n<h1 id=\"文件的读取\"><a class=\"anchor\" href=\"#文件的读取\">#</a> 文件的读取</h1>\n<h2 id=\"访问模式\"><a class=\"anchor\" href=\"#访问模式\">#</a> 访问模式</h2>\n<p>常用的三种基础访问模式：</p>\n<ul>\n<li><code>'r'</code>  ：以 <strong>只读</strong> 方式打开文件（默认模式）。文件的指针将会放在文件的开头</li>\n<li><code>'w'</code>  ：打开文件只用于 <strong>写入</strong> 。如果该文件已存在，则打开文件，并从开头开始编辑（原有内容会被删除）；如果该文件不存在，创建新文件</li>\n<li><code>'a'</code>  ：打开一个文件用于 <strong>追加</strong> 。如果该文件已存在，新的内容将会被写入到已有内容之后；如果该文件不存在，创建新文件进行写入</li>\n</ul>\n<h2 id=\"打开文件\"><a class=\"anchor\" href=\"#打开文件\">#</a> 打开文件</h2>\n<p>使用  <code>open</code>  函数可以打开一个已经存在的文件，或者创建一个新文件（使用  <code>'w'</code>  模式时）</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">,</span> mode<span class=\"token punctuation\">,</span> encoding<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li>name：字符串，表示目标文件的文件名（可以包含文件所在的路径）</li>\n<li>mode：设置打开文件的模式（访问模式）：只读、写入、追加等</li>\n<li>encoding：编码格式（推荐使用 UTF-8）</li>\n</ul>\n<p><strong>操作文件需要通过  <code>open</code>  函数打开文件得到文件对象</strong></p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># encoding 不是第三个位置参数，需要采用关键字传参</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>file_obj <span class=\"token operator\">=</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">'python.txt'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'r'</span><span class=\"token punctuation\">,</span> encoding<span class=\"token operator\">=</span><span class=\"token string\">'UTF-8'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意：此时的  <code>file_obj</code>  是  <code>open</code>  函数的文件对象（Python 中一种特殊的数据类型），拥有属性和方法，可以使用  <code>对象.属性</code>  或  <code>对象.方法</code>  对其进行访问</p>\n<h2 id=\"关闭文件\"><a class=\"anchor\" href=\"#关闭文件\">#</a> 关闭文件</h2>\n<p><code>close</code>  关闭文件对象，即，关闭对文件的占用</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>close<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>如果不调用  <code>close</code>  ，并且程序没有停止运行，那么这个文件将一直被 Python 程序占用（除  <code>with open</code>  语法外）</p>\n<h2 id=\"读操作\"><a class=\"anchor\" href=\"#读操作\">#</a> 读操作</h2>\n<h3 id=\"read-方法\"><a class=\"anchor\" href=\"#read-方法\">#</a> read 方法</h3>\n<p><code>read</code>  可以读取给定长度的数据</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>其中，num 表示要从文件中读取的数据的长度（字节数）。如果没有传入 num，表示读取文件中所有的数据</p>\n<h3 id=\"readlines-方法\"><a class=\"anchor\" href=\"#readlines-方法\">#</a> readlines 方法</h3>\n<p><code>readlines</code>  可以一次性读取整个文件中的内容。 <code>readlines</code>  返回的是一个列表，其中，文件每一行的数据对应列表的一个元素</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>readlines<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"readline-方法\"><a class=\"anchor\" href=\"#readline-方法\">#</a> readline 方法</h3>\n<p><code>readline</code>  一次读取一行数据</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>readline<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"for-循环读取文件行\"><a class=\"anchor\" href=\"#for-循环读取文件行\">#</a> for 循环读取文件行</h3>\n<p>可以使用  <code>for</code>  循环遍历读取文件的每一行内容</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 临时变量 line 记录文件的一行数据</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">for</span> line <span class=\"token keyword\">in</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">,</span> mode<span class=\"token punctuation\">,</span> encoding<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>line<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"with-open-语法\"><a class=\"anchor\" href=\"#with-open-语法\">#</a> with open 语法</h3>\n<p>通过在  <code>with open</code>  的语句块中对文件进行操作，可以在操作完成后自动关闭文件，避免因忘记  <code>close</code>  文件对象而导致文件被占用</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">with</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">,</span> mode<span class=\"token punctuation\">,</span> encoding<span class=\"token punctuation\">)</span> <span class=\"token keyword\">as</span> file_obj<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    file_obj<span class=\"token punctuation\">.</span>readlines<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h1 id=\"文件的写入\"><a class=\"anchor\" href=\"#文件的写入\">#</a> 文件的写入</h1>\n<h2 id=\"打开文件-2\"><a class=\"anchor\" href=\"#打开文件-2\">#</a> 打开文件</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj <span class=\"token operator\">=</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">,</span> mode<span class=\"token operator\">=</span><span class=\"token string\">'w'</span><span class=\"token punctuation\">,</span> encoding<span class=\"token operator\">=</span><span class=\"token string\">'UTF-8'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>使用  <code>'w'</code>  模式时：</p>\n<ul>\n<li>如果文件不存在，会创建新文件</li>\n<li>如果文件存在，会将原有内容清空</li>\n</ul>\n<h2 id=\"写操作\"><a class=\"anchor\" href=\"#写操作\">#</a> 写操作</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>write<span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p><code>content</code>  表示需要写入的内容</p>\n<p>注意：调用  <code>write</code>  时，内容并未真正写入文件，而是会积攒在程序的内存中，称之为缓冲区</p>\n<p>当调用  <code>flush</code>  时，内容会真正写入文件</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>flush<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><blockquote>\n<p><code>write</code>  写入内容 +  <code>flush</code>  刷新内容到硬盘，这样做是避免因频繁操作硬盘而导致效率下降</p>\n</blockquote>\n<h2 id=\"关闭文件-2\"><a class=\"anchor\" href=\"#关闭文件-2\">#</a> 关闭文件</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>close<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意： <code>close</code>  方法内置了  <code>flush</code>  的功能</p>\n<h1 id=\"文件的追加写入\"><a class=\"anchor\" href=\"#文件的追加写入\">#</a> 文件的追加写入</h1>\n<h2 id=\"打开文件-3\"><a class=\"anchor\" href=\"#打开文件-3\">#</a> 打开文件</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj <span class=\"token operator\">=</span> <span class=\"token builtin\">open</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">,</span> <span class=\"token string\">'a'</span><span class=\"token punctuation\">,</span> encoding<span class=\"token operator\">=</span><span class=\"token string\">'UTF-8'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>使用 'a' 模式时：</p>\n<ul>\n<li>如果文件不存在，会创建文件</li>\n<li>如果文件存在，会在文件最后追加写入</li>\n</ul>\n<h2 id=\"追加写入操作\"><a class=\"anchor\" href=\"#追加写入操作\">#</a> 追加写入操作</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 写入内容 content</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>write<span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 刷新内容</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>flush<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"关闭文件-3\"><a class=\"anchor\" href=\"#关闭文件-3\">#</a> 关闭文件</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>file_obj<span class=\"token punctuation\">.</span>close<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>参考：<a href=\"https://www.bilibili.com/video/BV1qW4y1a7fU/\">黑马程序员</a></p>\n",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/job.html",
            "url": "https://jiankychen.github.io/job.html",
            "title": "23 求职笔面试",
            "date_published": "2022-12-07T13:13:47.000Z",
            "content_html": "<h1 id=\"tp-link嵌入式软件\"><a class=\"anchor\" href=\"#tp-link嵌入式软件\">#</a> TP-Link（嵌入式软件）</h1>\n<h2 id=\"笔试\"><a class=\"anchor\" href=\"#笔试\">#</a> 笔试</h2>\n<p>选择题：</p>\n<ul>\n<li>物理层设备</li>\n<li>可能会出现进程饿死的进程调度算法</li>\n<li>调用 Fork 后，产生的子进程保留了父进程的什么</li>\n<li>Huffman 编码</li>\n<li>采用 LRU 算法时，进程访问过程中的缺页次数、缺页率</li>\n<li>二叉树中序遍历所需栈高度与什么有关</li>\n<li>利用栈来执行带括号的算术表达式，对于某个表达式所需的最小栈大小</li>\n<li>排序算法的时间复杂度</li>\n<li>给出两段程序（递归版本、非递归版本），比较</li>\n<li>回文字符串的判断（选出一项，补全代码）</li>\n</ul>\n<p>简答题：</p>\n<ul>\n<li>内存越界是什么，内存越界是否会导致程序崩溃，为什么，举例说明内存越界会造成那些后果</li>\n<li>Java 中的 CAS 机制原理（选做）</li>\n<li>双向链表中的节点替换（补全代码）</li>\n<li>7 位电话号码，给定超过一百万个的电话号码，对电话号码去重，排序，存储号码的内存 buffer 限制为 1MB</li>\n</ul>\n<p>编程题：</p>\n<ul>\n<li>环形链表 II （<a href=\"https://leetcode.cn/problems/linked-list-cycle-ii/\">力扣 142</a>）：核心代码模式</li>\n<li>乘积最大子数组（<a href=\"https://leetcode.cn/problems/maximum-product-subarray/\">力扣 152</a>）：ACM 模式</li>\n</ul>\n<p>选择题、简答题、编程题一共 60 分钟</p>\n<p>行测：（每部分 10 分钟）</p>\n<ul>\n<li>言语理解与表达</li>\n<li>判断推理</li>\n<li>图形推理</li>\n<li>数量关系</li>\n</ul>\n<h2 id=\"一面\"><a class=\"anchor\" href=\"#一面\">#</a> 一面</h2>\n<p>宏</p>\n<p>快速排序、选择排序的基本原理</p>\n<p>全局变量、局部变量、静态变量</p>\n<p>解决哈希冲突的方法</p>\n<p>介绍拉链法的原理</p>\n<p>OSI 参考模型：应用层、表示层、会话层、传输层、网络层、数据链路层、物理层</p>\n<p>第一轮面试一共 10 分钟</p>\n<h2 id=\"二面\"><a class=\"anchor\" href=\"#二面\">#</a> 二面</h2>\n<p>智力题：7g 砝码和 2g 砝码各一个，天平一个，如何用最少次数将 140g 盐分成 50g 和 90g 各一份？</p>\n<ul>\n<li>正确答案：最少需要操作三次\n<ul>\n<li>利用天平将 140g 盐分成两份 70g</li>\n<li>利用 9g 砝码将 70g 盐分成 9g 和 61g</li>\n<li>利用 2g 砝码与 9g 盐将 61g 盐分成 11g 和 50g</li>\n</ul>\n</li>\n</ul>\n<p>算法题：二叉树的最近公共祖先（<a href=\"https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/\">力扣 236</a>）</p>\n<ul>\n<li>先讲思路，再在自己的 IDE 上编程实现（核心代码模式）</li>\n</ul>\n<p>最后问了项目，大概 10 分钟左右</p>\n<p>第二轮面试一共 40 分钟</p>\n<h2 id=\"三面\"><a class=\"anchor\" href=\"#三面\">#</a> 三面</h2>\n<p>自我介绍</p>\n<p>本科成绩是什么情况？是保研的吗？</p>\n<p>为嵌入式软件岗做了哪些相关准备？</p>\n<p>计算机网络、操作系统、数据结构与算法学过吗？</p>\n<p>数据结构与算法刷了多少题？</p>\n<p>TCP 与 UDP 有什么区别？</p>\n<p>如何理解 TCP 的可靠传输？</p>\n<p>TCP/IP 网络模型是怎样的？每一层对应有哪些协议？</p>\n<p>如何用两个队列实现一个栈？</p>\n<p>研究生课题的主要内容？目的是什么？是不是自己一个人完成的？成果？</p>\n<p>有哪些兴趣爱好？是否拿出摄影作品去参加过学校的展览？骑行都去过哪些地方？</p>\n<p>父母的工作</p>\n<p>兄弟姐妹的情况</p>\n<p>反问：</p>\n<ul>\n<li>部门 / 分组是怎么确定的？入职以后确定</li>\n<li>主要用的编程语言是什么？用的最多的是 C/C++ ，会经常使用数据结构与算法、操作系统的相关内容</li>\n</ul>\n<p>最后，面试官建议认真学一下操作系统</p>\n<p>第三轮面试一共 18 分钟</p>\n<h1 id=\"shein算法工程师-运筹预测方向\"><a class=\"anchor\" href=\"#shein算法工程师-运筹预测方向\">#</a> SHEIN（算法工程师 - 运筹预测方向）</h1>\n<h2 id=\"测评\"><a class=\"anchor\" href=\"#测评\">#</a> 测评</h2>\n<p>一共包含四个模块，全都是选择题</p>\n<ul>\n<li>言语表达，10 题，限时 10 分钟左右</li>\n<li>图表分析，10 题，限时 10 分钟左右</li>\n<li>图形推理，10 题，限时 10 分钟左右</li>\n<li>性格测评，158 题，不限时</li>\n</ul>\n<h2 id=\"笔试-2\"><a class=\"anchor\" href=\"#笔试-2\">#</a> 笔试</h2>\n<p>题型：15 道单选题，2 道算法题，2 道问答题</p>\n<p>限时 60 分钟</p>\n<p>单选题涉及的知识：</p>\n<ul>\n<li>机器学习</li>\n<li>python</li>\n<li>排序算法</li>\n</ul>\n<p>算法题：</p>\n<ul>\n<li>最长回文子序列（<a href=\"https://leetcode.cn/problems/longest-palindromic-subsequence/\">力扣 516</a>）：ACM 模式</li>\n<li>二叉树的层序遍历（<a href=\"https://leetcode.cn/problems/binary-tree-level-order-traversal/\">力扣 102</a>）：核心代码模式</li>\n</ul>\n<p>问答题：</p>\n<ul>\n<li>AUC 的计算</li>\n<li>SQL 语句</li>\n</ul>\n<h1 id=\"蔚来智能调度和控制算法工程师\"><a class=\"anchor\" href=\"#蔚来智能调度和控制算法工程师\">#</a> 蔚来（智能调度和控制算法工程师）</h1>\n<h2 id=\"提前批\"><a class=\"anchor\" href=\"#提前批\">#</a> 提前批</h2>\n<h3 id=\"笔试大数据的试卷\"><a class=\"anchor\" href=\"#笔试大数据的试卷\">#</a> 笔试（大数据的试卷）</h3>\n<p>10 道单选题：设计模式、概率论相关知识点</p>\n<p>9 道不定项选择题：操作系统、数据库相关知识点</p>\n<p>3 道算法题（核心代码模式）：</p>\n<ul>\n<li>合并二叉树（<a href=\"https://leetcode.cn/problems/merge-two-binary-trees/\">力扣 617</a>）</li>\n<li>爬楼梯（<a href=\"https://leetcode.cn/problems/climbing-stairs/\">力扣 70</a> ）进阶版：每次可以爬 1 或 2 或 3 个台阶</li>\n<li>滑动窗口最大值（<a href=\"https://leetcode.cn/problems/sliding-window-maximum/\">力扣 239</a>）</li>\n</ul>\n<h2 id=\"正式批\"><a class=\"anchor\" href=\"#正式批\">#</a> 正式批</h2>\n<h3 id=\"测评北森系统\"><a class=\"anchor\" href=\"#测评北森系统\">#</a> 测评（北森系统）</h3>\n<p>10 道言语理解，每小题有相应限时</p>\n<p>10 道图表分析，每小题有相应限时</p>\n<p>10 道图形推理，每小题有相应限时</p>\n<p>99 道性格测试，每小题有相应限时</p>\n<h1 id=\"三一算法工程师\"><a class=\"anchor\" href=\"#三一算法工程师\">#</a> 三一（算法工程师）</h1>\n<h2 id=\"测评北森\"><a class=\"anchor\" href=\"#测评北森\">#</a> 测评（北森）</h2>\n<p>行测，每题都有对应的限时：</p>\n<ul>\n<li>言语理解与表达，一共 11 题</li>\n<li>图表分析，一共 10 题</li>\n<li>图形推理，一共 10 题</li>\n</ul>\n<p>性格测评，不限时：</p>\n<ul>\n<li>98 道选择题：每题需从三个选项中选出最符合、最不符合</li>\n<li>100 道单选题</li>\n</ul>\n<h2 id=\"笔试-3\"><a class=\"anchor\" href=\"#笔试-3\">#</a> 笔试</h2>\n<p>一共 30 道选择题（20 道单选，10 道多选），限时 60 分钟：</p>\n<ul>\n<li>数据结构与算法：图论（最短路径、最小生成树、有向图、邻接矩阵）、栈、动态规划的基本要素、贪心思想、回溯法</li>\n<li>机器学习相关：线性回归、生成模型、基于二次准则函数的 H-K 算法、感知器算法、统计模式识别分类问题、map-reduce 框架及相关算法、K - 均值算法、判别式模型、决策树的启发函数</li>\n<li>操作系统：内存管理、线程</li>\n<li>运筹优化相关：分支定界、TSP 问题的时间复杂度、路径规划算法、应用 Johnson 法则的流水作业调度所采用的算法、无约束优化问题的相关算法、PnP 问题的求解方法</li>\n<li>排列数与组合数</li>\n<li>编程语言：C++ 语句、类的静态成员、python 中的复数</li>\n</ul>\n<h2 id=\"一面-2\"><a class=\"anchor\" href=\"#一面-2\">#</a> 一面</h2>\n<p>自我介绍</p>\n<p>学习成绩</p>\n<p>英语六级成绩</p>\n<p>用的什么编程语言</p>\n<p>简述利用 matlab 实现的一个算法</p>\n<p>对汽车有没有什么了解</p>\n<p>建议：</p>\n<ul>\n<li>后续要加强对汽车相关知识的学习</li>\n<li>要进一步熟悉一下 matlab，尤其是 simulink</li>\n</ul>\n<p>面试一共 6 分钟（邮件里写的 20 分钟）</p>\n<h1 id=\"中兴算法工程师\"><a class=\"anchor\" href=\"#中兴算法工程师\">#</a> 中兴（算法工程师）</h1>\n<h2 id=\"测评北森系统-2\"><a class=\"anchor\" href=\"#测评北森系统-2\">#</a> 测评（北森系统）</h2>\n<p>行测：</p>\n<ul>\n<li>言语理解与表达，一共 10 题，限时 10 分钟</li>\n<li>图形推理，一共 10 题，限时 10 分钟</li>\n<li>图表分析，一共 10 题，限时 10 分钟</li>\n</ul>\n<p>性格测评，不限时：</p>\n<ul>\n<li>98 道选择题：每题需从三个选项中选出最符合、最不符合</li>\n<li>100 道单选题</li>\n</ul>\n<h2 id=\"面试\"><a class=\"anchor\" href=\"#面试\">#</a> 面试</h2>\n<p>安排了软件工程师的面试</p>\n<p>拒掉了面试</p>\n<h1 id=\"用友运筹优化算法工程师\"><a class=\"anchor\" href=\"#用友运筹优化算法工程师\">#</a> 用友（运筹优化算法工程师）</h1>\n<h2 id=\"测评-2\"><a class=\"anchor\" href=\"#测评-2\">#</a> 测评</h2>\n<p>行测：数量关系、演绎论证、图形推理、图表分析，一共 28 道选择题，限时 30 分钟</p>\n<p>性格测评：一共 88 题（每题需从三个选项中选出最符合、最不符合），限时 30 分钟</p>\n<h1 id=\"大疆决策与规划算法工程师\"><a class=\"anchor\" href=\"#大疆决策与规划算法工程师\">#</a> 大疆（决策与规划算法工程师）</h1>\n<h2 id=\"测评-3\"><a class=\"anchor\" href=\"#测评-3\">#</a> 测评</h2>\n<p>一共 80 道题，限时 80 分钟</p>\n<ul>\n<li>行测：数量关系，演绎论证，15 题左右</li>\n<li>性格测试</li>\n</ul>\n<h2 id=\"笔试-4\"><a class=\"anchor\" href=\"#笔试-4\">#</a> 笔试</h2>\n<p>一共 25 道不定项选择题，限时 60 分钟</p>\n<p>内容涉及以下方面：</p>\n<ul>\n<li>ROS</li>\n<li>git</li>\n<li>多项式曲线、B spline、羊角螺线</li>\n<li>Dijkstra、A*、RRT、RRT* 路径规划算法（特性比较）</li>\n<li>line search、无约束的路径规划、采用 邻接矩阵或邻接表 的 Dijkstra 算法的复杂度</li>\n<li>判断凸函数、判断凸约束</li>\n<li>多项式曲线刻画曲率能否为凸约束、庞特里亚金最大化原理、半正定优化是否为凸优化问题</li>\n<li>C++ 模板编程、返回值</li>\n<li>算法的时间复杂度</li>\n<li>链表操作的时间复杂度</li>\n<li>unordered_map 的底层实现以及相关特性</li>\n<li>SO ()、SE ()、四元数与自由度</li>\n<li>计算排列数、计算事件发生的概率、计算数学期望</li>\n<li>平面空间索引、K-D tree、R-tree、三维空间索引</li>\n</ul>\n<h1 id=\"杉数科技算法工程师-运筹优化方向\"><a class=\"anchor\" href=\"#杉数科技算法工程师-运筹优化方向\">#</a> 杉数科技（算法工程师 - 运筹优化方向）</h1>\n<h2 id=\"一面-3\"><a class=\"anchor\" href=\"#一面-3\">#</a> 一面</h2>\n<p>自我介绍</p>\n<p>讲解项目（大概聊了 20 分钟）</p>\n<p>KKT 条件</p>\n<ul>\n<li>KKT 条件是最优解的充分条件还是必要条件</li>\n<li>在什么情况下 KKT 能作为充分条件</li>\n<li>KKT 的具体内容</li>\n</ul>\n<p>从 branch-and-bound 、Benders 分解、Largrange 松弛、列生成 四个算法中选择一个算法，讲解其原理以及应用场景</p>\n<p>使用的编程语言，有没有使用 C++ 实现算法</p>\n<p>给两道场景题，要求建立数学模型（口述）：都是排产、排程相关的场景</p>\n<ul>\n<li>\n<p>第一道的大概内容：假设你是某饭店的老板，饭店里有一台冰箱可以存放盒饭（每一份盒饭可以保存两个小时），如果盒饭库存不够就需要现场准备。现场准备所需的成本与提前准备的成本不相等，并且，顾客的数量是随机的（有以往的顾客数量信息）。问：如果规划 冰箱存放的盒饭数量 以及 现场所需准备的盒饭数量，以使得总成本最小？</p>\n</li>\n<li>\n<p>第二道的大概内容：假设你是某电子工厂的老板，现要在一年内生产 A、B 两类产品各 5 千万个，若当天生产的是 A 产品，则可生产 a 个，若当天生产的是 B 产品，则可生产 b 个。假设：若当天生产 A 类产品且第二天生产 B 类产品，或者，当天生产 B 类产品且第二天生产 A 类产品，两种情况都会产生额外的成本。即，生产产品的类别的变化，会带来额外成本。问：如何确定每一天生产的产品类别，使得生产产品类别的变化次数最少？</p>\n</li>\n</ul>\n<p>面试官介绍业务（主要是与工厂的排班排程相关的实际问题），并且主要使用 python</p>\n<p>反问：</p>\n<ul>\n<li>会参与 COPT 求解器的研发吗？</li>\n<li>面试有多少轮（三轮）</li>\n</ul>\n<p>面试一共 50 分钟左右（邮件里写的是 60 分钟）</p>\n<p>面试官很友好，并且会及时提供引导。面试体验挺不错，虽然很多都不会 hh</p>\n<h2 id=\"笔试-5\"><a class=\"anchor\" href=\"#笔试-5\">#</a> 笔试</h2>\n<p>一共两道题，24 小时内做完</p>\n<ul>\n<li>\n<p>现有一家移动运营商（例如中国移动、中国电信）需要为一座城市建造基站，已知该城市终端用户的所在位置和所需的移动流量，可选的基站建造位置，以及不同类型基站的覆盖范围和最大流量。请帮助基站规划员决策需要布置的基站数量，所选的基站位置以及每小时的基站运行状态（无流量需求时基站可关闭，假设基站可随意开关且没有额外成本），使得该家公司的支出总成本最小，包括基站建造成本以及基站运营成本。</p>\n<ul>\n<li>假设每个时间段内的终端需求都需要被满足，建立数学规划模型，设计最优的基站建设及运营方案。可根据需要添加合理的前提假设。</li>\n<li>假设每个时间段内的终端需求不需要都被满足，但是未被满足的流量需求会产生额外成本，请修改模型并简述和模型 1 的差异。</li>\n<li>如果没有可选的基站位置，城市里的任何位置都可建造基站，请简述如何修改你的方案和模型。</li>\n<li>如果可选的基站点过多，请简述如何修改模型，使得在可接受的时间范围内求解模型。</li>\n<li>如果每个终端用户的流量需求不确定，请简述如何求解这个问题。</li>\n</ul>\n</li>\n<li>\n<p>某学生必须在 4 个不同系中选修 10 门课程，每个系至少选 1 门。这个学生将每个系选修课程数目与获得知识量按照 100 分衡量如表格所示。要争取获得的知识量达到最大。</p>\n<ul>\n<li>针对以上场景：\n<ul>\n<li>请使用动态规划求解该问题。（编程）</li>\n<li>请使用混合整数规划求解该问题。（调用任意求解器编程）</li>\n</ul>\n</li>\n<li>若 C 的选修课数量不得多于 D：\n<ul>\n<li>请使用动态规划求解该问题。（编程）</li>\n<li>请使用混合整数规划求解该问题。（调用任意求解器编程）</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<p>备注：优先使用 python</p>\n<h2 id=\"二面-2\"><a class=\"anchor\" href=\"#二面-2\">#</a> 二面</h2>\n<p>两个面试官，副总裁和业务总监</p>\n<p>首先进行自我介绍，讲一讲对杉数的认识，自己的优势</p>\n<p>自己对这一岗位的工作规划，可能遇到的问题以及解决方案</p>\n<p>介绍项目</p>\n<p>反问</p>\n<h1 id=\"顺丰科技运筹优化算法工程师\"><a class=\"anchor\" href=\"#顺丰科技运筹优化算法工程师\">#</a> 顺丰科技（运筹优化算法工程师）</h1>\n<h2 id=\"测评-4\"><a class=\"anchor\" href=\"#测评-4\">#</a> 测评</h2>\n<p>言语理解、性格测评、情景题</p>\n<h2 id=\"笔试-6\"><a class=\"anchor\" href=\"#笔试-6\">#</a> 笔试</h2>\n<p>120 分钟</p>\n<p>选择题：单选、多选共 34 道题，一共 70 分：主要考察运筹优化算法、概率论相关</p>\n<p>编程题：两道，ACM 模式，每题 15 分</p>\n<ul>\n<li>\n<p>幸运数：如果一个数在十进制表示下数字 5 出现了不少于 5 次，则这个数是一个幸运数。求：大于 N 的最小的幸运数</p>\n</li>\n<li>\n<p>猜排列游戏：小明有一个由 1 到 n 的整数组成的排列，让你来猜出这个排列是什么。每次可以猜测某个位置的数字，小明会告知你的猜想是 “大了”、“小了” 或者 “正确”。求：在最坏情况下，需要猜测几次，才能在排列的所有位置都得到小明的 “正确” 的回复。</p>\n</li>\n</ul>\n<h1 id=\"小米运筹强化学习算法工程师\"><a class=\"anchor\" href=\"#小米运筹强化学习算法工程师\">#</a> 小米（运筹 / 强化学习算法工程师）</h1>\n<h2 id=\"测评北森系统-3\"><a class=\"anchor\" href=\"#测评北森系统-3\">#</a> 测评（北森系统）</h2>\n<p>行测：</p>\n<ul>\n<li>言语理解与表达，一共 10 题，每题都有相应限时</li>\n<li>图形推理，一共 10 题，每题都有相应限时</li>\n<li>图表分析，一共 10 题，每题都有相应限时</li>\n</ul>\n<p>性格测评，不限时：</p>\n<ul>\n<li>98 道选择题：每题需从三个选项中选出最符合、最不符合</li>\n<li>100 道单选题</li>\n</ul>\n<p>性格测评的这两个板块直接复用了之前做过中兴的测评</p>\n<h2 id=\"笔试算法方向\"><a class=\"anchor\" href=\"#笔试算法方向\">#</a> 笔试（算法方向）</h2>\n<p>16 道单选题，每题 2 分，主要涉及以下方面的知识点：</p>\n<ul>\n<li>机器学习</li>\n<li>图像处理</li>\n<li>数字信号处理（滤波器、快速傅里叶变换）</li>\n<li>快速排序、链表操作</li>\n<li>概率论与数理统计</li>\n</ul>\n<p>17 道多选题，每题 2 分，涉及以下内容：</p>\n<ul>\n<li>栈操作</li>\n<li>动态规划代码</li>\n<li>向量范数</li>\n<li>快速傅里叶变换</li>\n<li>机器学习（监督学习、生成式模型）</li>\n<li>矩阵的秩</li>\n<li>图像处理过程中的噪声</li>\n<li>凸函数</li>\n</ul>\n<p>2 道编程题，每题 17 分，均为 ACM 模式：</p>\n<ul>\n<li>给定一个数组，每一次可以从数组的最左侧或者最右侧移除一个数，同时，令数字 x 减去移除的这一元素。问：至少需要多少次移除操作，才能使 x 变为 0 。如果无法使得 x 变为 0，则输出 -1\n<ul>\n<li>输入：一共三行，其中，第一行是一个用 [] 包围一个数字序列（数字与数字之间用逗号分隔），第二行是数字序列的长度，第三行是数字 x</li>\n<li>输出：一个整数，表示需要的移除次数（无法将 x 变为 0 时输出 -1 ）</li>\n</ul>\n</li>\n</ul>\n<ul>\n<li>给定两个序列，计算两个序列的卷积和互相关\n<ul>\n<li>输入：一共两行，分别为两个序列，其中，每一行的第一个数表示序列长度，紧接着一个逗号，然后是用空格分隔的序列</li>\n<li>输出：一共两行，分别为卷积和互相关的结果，其中，每一行的第一个数表示结果序列长度，紧接着一个逗号，然后是用空格分隔的结果序列</li>\n</ul>\n</li>\n</ul>\n<h1 id=\"美团运筹优化研发工程师\"><a class=\"anchor\" href=\"#美团运筹优化研发工程师\">#</a> 美团（运筹优化研发工程师）</h1>\n<h2 id=\"笔试-7\"><a class=\"anchor\" href=\"#笔试-7\">#</a> 笔试</h2>\n<p>四道编程题，每题 20 分：</p>\n<ul>\n<li>第一题：字符串匹配</li>\n<li>第二题：数组、哈希表</li>\n<li>第三题：字符串分割</li>\n<li>第四题：背包问题</li>\n</ul>\n<p>三道多项选择题：</p>\n<ul>\n<li>第一题，6 分：下列哪些属于分类任务常用损失函数：Softmax 损失、L2 损失、L1 损失、交叉熵损失</li>\n<li>第二题，6 分：目前对于最近邻分类的研究在于：探索更加合理的 K 值、寻求更接近于实际的距离函数、建立高效的索引、运用更加精确的概率估测方法以取代简单的投票机制</li>\n<li>第三题，8 分：当想创建新表的时候，hive 输入命令 create table if not exist，以下哪些情况会发生：表名存在时报错、表名不存在时不报错、表名不存在时报错、表名存在时不报错</li>\n</ul>\n<p>一共限时 120 分钟</p>\n<h2 id=\"一面-4\"><a class=\"anchor\" href=\"#一面-4\">#</a> 一面</h2>\n<p>面试官首先自我介绍，并介绍事业部的主要工作，介绍面试流程</p>\n<p>自我介绍</p>\n<p>有没有实习</p>\n<p>聊项目</p>\n<p>对遗传算法、禁忌搜索等算法有没有了解？</p>\n<p>介绍一下遗传算法</p>\n<p>如果用遗传算法来求解 TSP 问题要怎么求解？</p>\n<p>对禁忌搜索这些算法有没有什么了解？</p>\n<p>对机器学习是否有了解？</p>\n<p>有没有做相应的机器学习算法实践？</p>\n<p>主要用的是什么编程语言？做题用什么语言？</p>\n<p>手撕代码，核心代码模式（在牛客上进行的面试，面试官可以直接在系统上出题）</p>\n<ul>\n<li><a href=\"https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/\">力扣 121 ：买卖股票的最佳时机</a></li>\n<li><a href=\"https://leetcode.cn/problems/trapping-rain-water/\">力扣 42 ：接雨水</a></li>\n</ul>\n<p>反问：</p>\n<ul>\n<li>部门的主要业务</li>\n<li>工作内容</li>\n</ul>\n<p>面试一共 45 分钟，其中，25 分钟项目、10 分钟代码、5 分钟反问</p>\n<h1 id=\"字节跳动算法工程师-运筹优化\"><a class=\"anchor\" href=\"#字节跳动算法工程师-运筹优化\">#</a> 字节跳动（算法工程师 - 运筹优化）</h1>\n<h2 id=\"笔试-8\"><a class=\"anchor\" href=\"#笔试-8\">#</a> 笔试</h2>\n<p>120 分钟</p>\n<p>四道编程题，ACM 模式，分值分别为 20，25，25，30</p>\n<ul>\n<li>弹珠游戏（动态规划）</li>\n<li>三数和赛高数组</li>\n</ul>\n<h1 id=\"华为ai-工程师-决策推理方向\"><a class=\"anchor\" href=\"#华为ai-工程师-决策推理方向\">#</a> 华为（AI 工程师 - 决策推理方向）</h1>\n<h2 id=\"一次笔试\"><a class=\"anchor\" href=\"#一次笔试\">#</a> 一次笔试</h2>\n<p>一共三题，分值分别为 100、200、300，限时 120 分钟</p>\n<p>猪场防疫（第一题）：猪场现有 N 只猪，编号从 0 到 N - 1 （每只猪无论生死都有唯一的编号）。老李在每只猪生产的时候记录了生产的母猪和出生的小猪，格式为 x y1 y2 y3 ... ，其中，x 为母猪，y1、y2、y3... 为新生的小猪，以上编码均在 0 ~ N - 1 范围内，每只猪可以多次生产，每只小猪都只有一个猪妈妈。现需要检查任意两只猪是否有亲戚关系（两只猪具有相同的祖先），并计算出关系亲疏情况（关系距离，若相同编号则距离为 0）</p>\n<ul>\n<li>输入：\n<ul>\n<li>第一行输入总数 N</li>\n<li>第二行输入后续生产记录行数 M</li>\n<li>后续 M 行输入生产记录，以空格分隔</li>\n<li>最后一行输入待检查的两只猪的编号 m1 和 m2</li>\n</ul>\n</li>\n<li>输出：\n<ul>\n<li>一个整数，表示 m1 和 m2 之间的关系距离，无亲戚关系输出 -1</li>\n</ul>\n</li>\n</ul>\n<p>速战速决（第二题）：在一个 M 行 N 列的街区中，有一个士兵 S 和一个敌人 E ，标识 X 为无法通过的街区，标识 B 为可以通过的街区；士兵在一个单位时间内可以从一个街区移动到相邻的街区（每次只能水平或垂直方向移动一个街区）；士兵每次改变方向时，需要额外花费一个单位的时间（士兵第一次移动一个街区的时候，不用考虑其初始方向，即，只需要一个单位时间即可到达相邻街区）。计算士兵最少需要多少时间才能到达敌人所在的街区</p>\n<ul>\n<li>输入：\n<ul>\n<li>第一行两个数字，分别为街区的大小，M 和 N （1 &lt;= M, N &lt;= 1000，M 、N 不同时为 1）</li>\n<li>接下来 M 行，每行 N 个字母，字母 S 表示士兵所在街区，字母 E 表示敌人所在街区，字母 X 表示障碍，字母 B 表示可以经过的街区（只有一个 S，一个 E）</li>\n</ul>\n</li>\n<li>输出：\n<ul>\n<li>最少需要的时间，当士兵永远无法到达敌人所在街区时输出 -1</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"二次笔试时隔一个月\"><a class=\"anchor\" href=\"#二次笔试时隔一个月\">#</a> 二次笔试（时隔一个月）</h2>\n<ul>\n<li>\n<p>字符串压缩，例如，将 &quot;aaBcaBcaBcc&quot; 压缩成 &quot;a3 (aBc) c&quot;、将 &quot;aAABBAABB&quot; 压缩成 &quot;a2 (2 (A) 2 (B))&quot;</p>\n</li>\n<li>\n<p>三叉树中的最大路径和</p>\n</li>\n<li>\n<p>多进制计算器</p>\n</li>\n</ul>\n<h1 id=\"京东\"><a class=\"anchor\" href=\"#京东\">#</a> 京东</h1>\n<h2 id=\"笔试-9\"><a class=\"anchor\" href=\"#笔试-9\">#</a> 笔试</h2>\n<p>选择题，主要考察算法与数据结构、机器学习相关知识</p>\n<p>三道编程题：</p>\n<ul>\n<li>\n<p>定义一个字符串为 “好串” ：当且仅当相邻两个字母不相同。对于一个仅由 'r' 、'e'、'd' 三种字符组成的字符串，可以将相邻两个相同的字母同时删除，并在其位置生成任意一个字母（'r'、'e'、'd' 三种中的一种）。例如，对于字符串 &quot;dedd&quot;，可以选择将 &quot;dd&quot; 变成 &quot;r&quot;，字符串即变为 &quot;der&quot; 。现给定一个字符串，问：至少需要多少次操作才能将该字符串变成 “ 好串 ”</p>\n<ul>\n<li>输入描述：一个长度不超过 200000 的、仅由 'r' 、'e'、'd' 三种字符组成的字符串</li>\n<li>输出描述：一个整数，代表操作的最小次数</li>\n</ul>\n</li>\n<li>\n<p>对于一个长度为 n 的数组，现希望将一些数（不少于 2 个数）染红，满足任意两个染红的数之和都是偶数。问：一共有多少种不同的染色方案？答案对 10<sup>9</sup> + 7 取模。规定：对于两个方案，只要存在某个数的染色情况不同，则认为是两种不同的方案</p>\n<ul>\n<li>输入描述：第一行输入一个正整数 n，代表数组长度；第二行输入 n 个正整数 a<sub>i</sub> ，代表数组的元素</li>\n<li>数据范围：2 &lt;= n &lt;= 10<sup>5</sup>，1 &lt;= a<sub>i</sub> &lt;= 10<sup>9</sup></li>\n<li>输出描述：一共整数，代表不同的方案数</li>\n</ul>\n</li>\n</ul>\n<h1 id=\"百度\"><a class=\"anchor\" href=\"#百度\">#</a> 百度</h1>\n<h2 id=\"笔试-10\"><a class=\"anchor\" href=\"#笔试-10\">#</a> 笔试</h2>\n<p>15 道单选题，一共 45 分，涉及知识点：</p>\n<ul>\n<li>SQL</li>\n<li>快速排序</li>\n<li>二分查找</li>\n<li>栈</li>\n<li>堆串</li>\n<li>ssh 公钥命令</li>\n<li>内存分配与释放（最佳适配算法）</li>\n<li>linux 系统</li>\n<li>同步关系和互斥关系</li>\n</ul>\n<p>5 道不定项选择题，一共 15 分，涉及知识点：</p>\n<ul>\n<li>linux</li>\n<li>C++</li>\n</ul>\n<p>3 道编程题，分值分别为 10 分、15 分、15 分，均为 ACM 模式</p>\n<ul>\n<li>\n<p>给定字符串 s ，问：字符串 s 中含有多少个形如 baidu 的子串（即，子串长度为 5，第一、四个字母是辅音字母，第二、三、五个字母是元音字母，并且，子串没有重复字母）</p>\n</li>\n<li>\n<p>已知字符串 str 仅包含 '0' 和 '1' ，每一次可反转字符串 s 中的两个连续字符（例如，&quot;01&quot; 反转成 &quot;10&quot; ），问：是否可以在有限次数内将 str 变成所有字符均相同的字符串（即，所有字符均为 '1' ，或者，所有字符均为 '0' ）</p>\n<ul>\n<li>例如，&quot;101&quot; 可以通过 2 次操作变成 &quot;000&quot; ，输出 &quot;Yes&quot; ；&quot;11111&quot; 无需操作即满足条件，输出 &quot;Yes&quot; ；&quot;1011&quot; 无法变成所有字符均相同的字符串，输出 &quot;No&quot;</li>\n<li>注：输入含有多组样例，需针对每组样例进行判断并输出</li>\n</ul>\n</li>\n<li>\n<p>给定一个 m 行 n 列的方格，其中，每个小方格有 'r' 、'e' 、'd' 三种字符中的某一个字符。现从左上角出发，每次可以往四个方向（向上、向下、向左、向右）中的某个方向移动一步，但是，不能从字符 'r' 移到字符 'e' 、不能从字符 'e' 移到字符 'd' 、不能从字符 'd' 移到字符 'r' 。问：至少需要移动多少步才能到达右下角。如果无法到达右下角，则输出 -1</p>\n<ul>\n<li>采用深度优先搜索（回溯）会超时，只能通过 23.08% 的样例</li>\n<li>需要采用广度优先搜索（没来得及写）</li>\n</ul>\n</li>\n</ul>\n<p>笔试一共限时 120 分钟</p>\n<h1 id=\"招银网络科技\"><a class=\"anchor\" href=\"#招银网络科技\">#</a> 招银网络科技</h1>\n<h2 id=\"测评北森系统-4\"><a class=\"anchor\" href=\"#测评北森系统-4\">#</a> 测评（北森系统）</h2>\n<p>行测：</p>\n<ul>\n<li>言语理解与表达，一共 11 题，每题有相应限时</li>\n<li>图形推理，一共 11 题，每题有相应限时</li>\n<li>图表分析，一共 11 题，每题有相应限时</li>\n</ul>\n<p>性格测评，不限时：</p>\n<ul>\n<li>98 道选择题：每题需从三个选项中选出最符合、最不符合</li>\n<li>100 道单选题：需从 非常不符合、比较不符合、比较符合、非常符合 四个选项中选择一个</li>\n</ul>\n<h1 id=\"美的嵌入式软件\"><a class=\"anchor\" href=\"#美的嵌入式软件\">#</a> 美的（嵌入式软件）</h1>\n<h2 id=\"笔试-11\"><a class=\"anchor\" href=\"#笔试-11\">#</a> 笔试</h2>\n<p>10 道单选，每题 2 分，主要考察操作系统、计算机网络的相关知识</p>\n<p>5 道不定项选择题，每题 4 分（少选错选不得分），主要考察操作系统、计算机网络的相关知识</p>\n<p>3 道编程题，ACM 模式：</p>\n<ul>\n<li>给定一个字符串，删除其中连续的多余空格：15 分</li>\n<li>输入一个十六进制数，将其表述成 32 位二进制数然后反转，再将反转得到的二进制数转换成十六进制输出：20 分</li>\n<li>给一个数组和一个目标数，判断存在一个组合使得元素和为目标数：25 分</li>\n</ul>\n<h1 id=\"中信银行信用卡中心\"><a class=\"anchor\" href=\"#中信银行信用卡中心\">#</a> 中信银行信用卡中心</h1>\n<h2 id=\"测评tas测评系统\"><a class=\"anchor\" href=\"#测评tas测评系统\">#</a> 测评（TAS 测评系统）</h2>\n<p>Talent5 大五职业性格测评：共 138 题，不限时</p>\n<p>iLogic 言语推理测评：共 15 题，限时 20 分钟（每题有相应限时）</p>\n<p>iLogic 数字推理测评：共 15 题，限时 20 分钟（每题有相应限时）</p>\n<p>iLogic 逻辑推理测评：共 10 题，限时 17 分钟（每题有相应限时）</p>\n<p>iDriver 职业驱动力测评：共 112 题，不限时</p>\n<p>Menlth 心理状态扫描：共 50 题，不限时</p>\n<h2 id=\"笔试-12\"><a class=\"anchor\" href=\"#笔试-12\">#</a> 笔试</h2>\n<p>30 道单项选择题，每题 2 分，考察 Linux 系统、Java、计算机网络、MySQL、数据结构 相关知识</p>\n<p>3 道编程题，ACM 模式，一共 40 分</p>\n<ul>\n<li>字符串中出现次数不少于 2 次的字母</li>\n<li>给定字符串，将元音字母都变成小写，辅音字母都变成大写</li>\n<li>给定 n 行 n 列的矩阵，将矩阵水平方向和垂直方向各翻转一次</li>\n</ul>\n",
            "tags": []
        },
        {
            "id": "https://jiankychen.github.io/python-container.html",
            "url": "https://jiankychen.github.io/python-container.html",
            "title": "Python 数据容器",
            "date_published": "2022-12-01T11:21:27.000Z",
            "content_html": "<p>数据容器：一种可以容纳多份数据的数据类型，容纳的每一份数据称之为 1 个元素，其中，每一个元素可以是任意类型的数据，如字符串、数字、布尔等</p>\n<p>Python 数据容器可以分为 5 类：</p>\n<ul>\n<li>列表（list）</li>\n<li>元组（tuple）</li>\n<li>字符串（str）</li>\n<li>集合（set）</li>\n<li>字典（dict）</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:center\"></th>\n<th style=\"text-align:center\">列表</th>\n<th style=\"text-align:center\">元组</th>\n<th style=\"text-align:center\">字符串</th>\n<th style=\"text-align:center\">集合</th>\n<th style=\"text-align:center\">字典</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\">元素类型</td>\n<td style=\"text-align:center\">任意</td>\n<td style=\"text-align:center\">任意</td>\n<td style=\"text-align:center\">字符</td>\n<td style=\"text-align:center\">任意</td>\n<td style=\"text-align:center\">key-value (key: 除字典外任意类型，value: 任意类型)</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">下标索引</td>\n<td style=\"text-align:center\">支持</td>\n<td style=\"text-align:center\">支持</td>\n<td style=\"text-align:center\">支持</td>\n<td style=\"text-align:center\">不支持</td>\n<td style=\"text-align:center\">不支持</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">数据有序</td>\n<td style=\"text-align:center\">是</td>\n<td style=\"text-align:center\">是</td>\n<td style=\"text-align:center\">是</td>\n<td style=\"text-align:center\">否</td>\n<td style=\"text-align:center\">否</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">重复元素</td>\n<td style=\"text-align:center\">支持</td>\n<td style=\"text-align:center\">支持</td>\n<td style=\"text-align:center\">支持</td>\n<td style=\"text-align:center\">不支持</td>\n<td style=\"text-align:center\">不支持</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">可修改性</td>\n<td style=\"text-align:center\">是</td>\n<td style=\"text-align:center\">否</td>\n<td style=\"text-align:center\">是</td>\n<td style=\"text-align:center\">是</td>\n<td style=\"text-align:center\">是</td>\n</tr>\n</tbody>\n</table>\n<blockquote>\n<p>在 Python 中，有序是指其中的数据可以通过索引（即下标）进行访问</p>\n</blockquote>\n<h1 id=\"列表\"><a class=\"anchor\" href=\"#列表\">#</a> 列表</h1>\n<h2 id=\"列表的定义\"><a class=\"anchor\" href=\"#列表的定义\">#</a> 列表的定义</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 字面量</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">[</span>元素<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 元素<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 定义变量</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>变量名 <span class=\"token operator\">=</span>  <span class=\"token punctuation\">[</span>元素<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 元素<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\">#定义空列表</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token builtin\">list</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>列表可以同时存储不同的数据类型，并且，列表支持嵌套</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>my_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"iteration\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1234</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">True</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>nested_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">,</span> <span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>my_list<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>my_list<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>nested_list<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>nested_list<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"列表的方法\"><a class=\"anchor\" href=\"#列表的方法\">#</a> 列表的方法</h2>\n<h3 id=\"访问元素\"><a class=\"anchor\" href=\"#访问元素\">#</a> 访问元素</h3>\n<p>可以通过列表的下标索引 idx 获取对应位置的数据</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>value <span class=\"token operator\">=</span> list_name<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span></pre></td></tr></table></figure><p>其中，列表的下标索引可以分为两种：</p>\n<ul>\n<li>正向索引（从左往右）：从 0 开始，依次递增</li>\n<li>反向索引（从右往左）：从 -1 开始，依次递减</li>\n</ul>\n<blockquote>\n<p>要注意下标索引的取值范围，超出范围会报错</p>\n</blockquote>\n<h3 id=\"查找元素\"><a class=\"anchor\" href=\"#查找元素\">#</a> 查找元素</h3>\n<p>查找元素 element 在列表 list_name 中的下标（元素在列表中的第一个匹配位置），如果找不到则报错 ValueError</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>index<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"修改元素\"><a class=\"anchor\" href=\"#修改元素\">#</a> 修改元素</h3>\n<p>修改下标为 idx 的元素的值</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> value</pre></td></tr></table></figure><h3 id=\"插入元素\"><a class=\"anchor\" href=\"#插入元素\">#</a> 插入元素</h3>\n<p>在下标 idx 处插入元素 element</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>insert<span class=\"token punctuation\">(</span>idx<span class=\"token punctuation\">,</span> element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"追加元素\"><a class=\"anchor\" href=\"#追加元素\">#</a> 追加元素</h3>\n<p><strong>方式一</strong></p>\n<p>将元素 element 追加到列表 list_name 的尾部</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>name_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"it\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"its\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"itself\"</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>name_list<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span><span class=\"token string\">\"itheima\"</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p><strong>方式二</strong></p>\n<p>将其他数据容器的内容取出，依次追加到列表 list_name 的尾部</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>extend<span class=\"token punctuation\">(</span>Data<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>mylist <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">5</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>temp_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">6</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>mylist<span class=\"token punctuation\">.</span>extend<span class=\"token punctuation\">(</span>temp_list<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"删除指定位置元素\"><a class=\"anchor\" href=\"#删除指定位置元素\">#</a> 删除指定位置元素</h3>\n<p>删除下标 idx 处的元素</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">del</span> list_name<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>pop<span class=\"token punctuation\">(</span>idx<span class=\"token punctuation\">)</span>      <span class=\"token comment\"># 该方式可以获取返回值（被删除的元素）</span></pre></td></tr></table></figure><h3 id=\"删除指定元素\"><a class=\"anchor\" href=\"#删除指定元素\">#</a> 删除指定元素</h3>\n<p>删除指定元素值在列表中的第一个匹配项</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>remove<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span>   <span class=\"token comment\"># 删除元素 element 在列表中的第一个匹配项</span></pre></td></tr></table></figure><h3 id=\"清空列表\"><a class=\"anchor\" href=\"#清空列表\">#</a> 清空列表</h3>\n<p>清空列表内容</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>clear<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"统计指定元素数量\"><a class=\"anchor\" href=\"#统计指定元素数量\">#</a> 统计指定元素数量</h3>\n<p>统计元素 element 在列表 list_name 中的数量</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>list_name<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"其他\"><a class=\"anchor\" href=\"#其他\">#</a> 其他</h2>\n<h3 id=\"统计列表元素数量\"><a class=\"anchor\" href=\"#统计列表元素数量\">#</a> 统计列表元素数量</h3>\n<p>统计整个列表中的元素总数量</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>list_name<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"列表的-while-遍历\"><a class=\"anchor\" href=\"#列表的-while-遍历\">#</a> 列表的 while 遍历</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>idx <span class=\"token operator\">=</span> <span class=\"token number\">0</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">while</span> idx <span class=\"token operator\">&lt;</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>list_name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    statement</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    idx <span class=\"token operator\">+=</span> <span class=\"token number\">1</span></pre></td></tr></table></figure><h3 id=\"列表的-for-遍历\"><a class=\"anchor\" href=\"#列表的-for-遍历\">#</a> 列表的 for 遍历</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>list_name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h1 id=\"元组\"><a class=\"anchor\" href=\"#元组\">#</a> 元组</h1>\n<p>元组（tuple）：元组同列表一样，都是一种可以封装多个、不同类型的元素的容器；不同点在于，元素一旦定义完成，就不可以修改</p>\n<h2 id=\"元组的定义\"><a class=\"anchor\" href=\"#元组的定义\">#</a> 元组的定义</h2>\n<p>定义元组：使用小括号包围数据，其中，每个数据之间用逗号隔开（数据可以是不同的数据类型）</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 定义元组字面量</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">(</span>元素<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 元素<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 定义元组变量</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>元素<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 元素<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 定义空元组</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token builtin\">tuple</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意：如果元组只有一个数据，需要在这个数据后面添加逗号，否则不是元组类型</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>t4 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token string\">\"World\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>元组也支持嵌套</p>\n<p>注意：</p>\n<ul>\n<li>不可以修改元组的内容，否则会直接报错</li>\n<li>如果元组内嵌套了 list 列表，则可以修改 list 列表的内容（修改、增加、删除元素，反转等）</li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>mytuple <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"it\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"20221124\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>mytuple<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"python\"</span></pre></td></tr></table></figure><h2 id=\"元组的方法\"><a class=\"anchor\" href=\"#元组的方法\">#</a> 元组的方法</h2>\n<h3 id=\"访问元素-2\"><a class=\"anchor\" href=\"#访问元素-2\">#</a> 访问元素</h3>\n<p>元组支持下标索引</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>element <span class=\"token operator\">=</span> tuple_name<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span></pre></td></tr></table></figure><h3 id=\"查找元素-2\"><a class=\"anchor\" href=\"#查找元素-2\">#</a> 查找元素</h3>\n<p>查找指定元素的第一个匹配项</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>tuple_name<span class=\"token punctuation\">.</span>index<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"统计指定元素数量-2\"><a class=\"anchor\" href=\"#统计指定元素数量-2\">#</a> 统计指定元素数量</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>tuple_name<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"其他-2\"><a class=\"anchor\" href=\"#其他-2\">#</a> 其他</h2>\n<h3 id=\"统计元素数量\"><a class=\"anchor\" href=\"#统计元素数量\">#</a> 统计元素数量</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>tuple_name<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"元组的-while-遍历\"><a class=\"anchor\" href=\"#元组的-while-遍历\">#</a> 元组的 while 遍历</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>idx <span class=\"token operator\">=</span> <span class=\"token number\">0</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">while</span> idx <span class=\"token operator\">&lt;</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>tuple_name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    statement</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    idx <span class=\"token operator\">+=</span> <span class=\"token number\">1</span></pre></td></tr></table></figure><h3 id=\"元组的-for-遍历\"><a class=\"anchor\" href=\"#元组的-for-遍历\">#</a> 元组的 for 遍历</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> element <span class=\"token keyword\">in</span> tuple_name<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h1 id=\"字符串\"><a class=\"anchor\" href=\"#字符串\">#</a> 字符串</h1>\n<p>字符串（str）：字符串是字符的容器，一个字符串可以存放任意数量的字符</p>\n<p>字符串是一个 无法修改 的数据容器</p>\n<h2 id=\"字符串的定义\"><a class=\"anchor\" href=\"#字符串的定义\">#</a> 字符串的定义</h2>\n<p>使用一对双引号包围一系列字符</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name <span class=\"token operator\">=</span> <span class=\"token string\">\"Here is the content of string\"</span></pre></td></tr></table></figure><h2 id=\"字符串的方法\"><a class=\"anchor\" href=\"#字符串的方法\">#</a> 字符串的方法</h2>\n<h3 id=\"访问元素-3\"><a class=\"anchor\" href=\"#访问元素-3\">#</a> 访问元素</h3>\n<p>字符串支持下标索引</p>\n<ul>\n<li>从前往后索引：下标从 0 开始</li>\n<li>从后往前索引：下标从 -1 开始</li>\n</ul>\n<h3 id=\"查找子串\"><a class=\"anchor\" href=\"#查找子串\">#</a> 查找子串</h3>\n<p>查找子串 target_str 在字符串 str_name 中的下标索引值</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name<span class=\"token punctuation\">.</span>index<span class=\"token punctuation\">(</span>target_str<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"替换子串\"><a class=\"anchor\" href=\"#替换子串\">#</a> 替换子串</h3>\n<p>将字符串 str_name 内的 str1 全部替换为 str2</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name<span class=\"token punctuation\">.</span>replace<span class=\"token punctuation\">(</span>str1<span class=\"token punctuation\">,</span> str2<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意，此方法并不是修改字符串本身（字符串是无法修改的），而是得到了一个新的字符串</p>\n<h3 id=\"分割子串\"><a class=\"anchor\" href=\"#分割子串\">#</a> 分割子串</h3>\n<p>按照指定的分隔符字符串 separator，将字符串划分为多个子字符串并存入列表对象中</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name<span class=\"token punctuation\">.</span>split<span class=\"token punctuation\">(</span>separator<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>注意，此方法并不是修改字符串本身，而是得到了一个列表对象</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>my_str <span class=\"token operator\">=</span> <span class=\"token string\">\"hello python itheima and itcast\"</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>result <span class=\"token operator\">=</span> my_str<span class=\"token punctuation\">.</span>split<span class=\"token punctuation\">(</span><span class=\"token string\">\" \"</span><span class=\"token punctuation\">)</span>  <span class=\"token comment\"># 按照空格进行分割，得到一个列表</span></pre></td></tr></table></figure><h3 id=\"去除前后空格\"><a class=\"anchor\" href=\"#去除前后空格\">#</a> 去除前后空格</h3>\n<p>strip () 方法删除开头和结尾的空白字符</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name<span class=\"token punctuation\">.</span>strip<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>my_str <span class=\"token operator\">=</span> <span class=\"token string\">\"   itheima and itcast   \"</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>new_my_str <span class=\"token operator\">=</span> my_str<span class=\"token punctuation\">.</span>strip<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"去除前后指定字符串\"><a class=\"anchor\" href=\"#去除前后指定字符串\">#</a> 去除前后指定字符串</h3>\n<p>通过给 strip () 方法传入参数，可以删除字符串开头和结尾处的指定字符串</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name<span class=\"token punctuation\">.</span>strip<span class=\"token punctuation\">(</span>target_str<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>需要注意，删除操作是按照单个字符进行的</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>my_str <span class=\"token operator\">=</span> <span class=\"token string\">\"12itheima and itcast21\"</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>new_my_str <span class=\"token operator\">=</span> my_str<span class=\"token punctuation\">.</span>strip<span class=\"token punctuation\">(</span><span class=\"token string\">\"12\"</span><span class=\"token punctuation\">)</span>     <span class=\"token comment\"># 传入的是 \"12\"，此时，\"1\" 和 \"2\" 都会移除，即，按照单个字符移除</span></pre></td></tr></table></figure><h3 id=\"统计指定字符串数量\"><a class=\"anchor\" href=\"#统计指定字符串数量\">#</a> 统计指定字符串数量</h3>\n<p>统计字符串中某子串的出现次数</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>str_name<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">(</span>target_str<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>my_str <span class=\"token operator\">=</span> <span class=\"token string\">\"itheima and itcast\"</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>cnt <span class=\"token operator\">=</span> my_str<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">(</span><span class=\"token string\">'it'</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"其他-3\"><a class=\"anchor\" href=\"#其他-3\">#</a> 其他</h2>\n<h3 id=\"统计字符串长度\"><a class=\"anchor\" href=\"#统计字符串长度\">#</a> 统计字符串长度</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>str_name<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"字符串的-while-遍历\"><a class=\"anchor\" href=\"#字符串的-while-遍历\">#</a> 字符串的 while 遍历</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>idx <span class=\"token operator\">=</span> <span class=\"token number\">0</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">while</span> idx <span class=\"token operator\">&lt;</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>str_name<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    statement</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    idx <span class=\"token operator\">+=</span> <span class=\"token number\">1</span></pre></td></tr></table></figure><h3 id=\"字符串的-for-遍历\"><a class=\"anchor\" href=\"#字符串的-for-遍历\">#</a> 字符串的 for 遍历</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> element <span class=\"token keyword\">in</span> str_name<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h1 id=\"序列\"><a class=\"anchor\" href=\"#序列\">#</a> 序列</h1>\n<p>序列是指内容连续、有序，并且可使用下标索引的一类数据容器</p>\n<p>序列是字符串、元组、列表的统称</p>\n<p>序列支持切片，即：从序列的指定位置开始，依次取出元素，到指定位置结束，得到一个新序列（该操作不会影响原序列，而是生成了一个新的序列）</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>sequence<span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">:</span>end<span class=\"token punctuation\">:</span>step<span class=\"token punctuation\">]</span></pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li>起始下标 start 表示从何处开始，可以省略，省略时视为从头开始</li>\n<li>结束下标 end 表示何处结束（不截取结束下标对应元素），可以省略，省略时视为截取至序列末尾（截取最后一个元素）</li>\n<li>步长 step 表示依次取元素的间隔，步长可以为负数，表示反向取元素（注意，起始下标和结束下标也要反向标记）</li>\n</ul>\n<h1 id=\"集合\"><a class=\"anchor\" href=\"#集合\">#</a> 集合</h1>\n<p>集合（set）：不支持元素重复（自带去重功能），并且内容无序</p>\n<p>集合是无序的，不支持下标索引访问</p>\n<p>集合是可以修改的</p>\n<h2 id=\"集合的定义\"><a class=\"anchor\" href=\"#集合的定义\">#</a> 集合的定义</h2>\n<p>定义集合：使用大括号包围数据，其中，每个数据之间用逗号隔开</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 定义集合字面量</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span>元素<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 元素<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 定义集合变量</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>元素<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 元素<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 定义空集合</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token builtin\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"集合的方法\"><a class=\"anchor\" href=\"#集合的方法\">#</a> 集合的方法</h2>\n<h3 id=\"添加元素\"><a class=\"anchor\" href=\"#添加元素\">#</a> 添加元素</h3>\n<p>将指定元素添加到集合内</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>set_name<span class=\"token punctuation\">.</span>add<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"删除元素\"><a class=\"anchor\" href=\"#删除元素\">#</a> 删除元素</h3>\n<p>将指定元素从集合内移除</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>set_name<span class=\"token punctuation\">.</span>remove<span class=\"token punctuation\">(</span>element<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"随机取出元素\"><a class=\"anchor\" href=\"#随机取出元素\">#</a> 随机取出元素</h3>\n<p>从集合中随机取出一个元素（集合本身被修改，元素被移除）</p>\n<p>该操作可以具有返回值</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>element <span class=\"token operator\">=</span> set_name<span class=\"token punctuation\">.</span>pop<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"清空集合\"><a class=\"anchor\" href=\"#清空集合\">#</a> 清空集合</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>set_name<span class=\"token punctuation\">.</span>clear<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"取两集合的差集\"><a class=\"anchor\" href=\"#取两集合的差集\">#</a> 取两集合的差集</h3>\n<p>取出集合 1 与集合 2 的差集：元素在集合 1 中、但不在集合 2 中</p>\n<p>该操作得到一个新集合，集合 1 和集合 2 保持不变</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>new_set <span class=\"token operator\">=</span> set1<span class=\"token punctuation\">.</span>difference<span class=\"token punctuation\">(</span>set2<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"消除两集合的差集\"><a class=\"anchor\" href=\"#消除两集合的差集\">#</a> 消除两集合的差集</h3>\n<p>消除集合 1 与集合 2 的差集：对比集合 1 和集合 2，在集合 1 内，删除与集合 2 相同的元素</p>\n<p>该操作修改了集合 2，集合 2 保持不变</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>set1<span class=\"token punctuation\">.</span>difference_update<span class=\"token punctuation\">(</span>set2<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"合并两集合\"><a class=\"anchor\" href=\"#合并两集合\">#</a> 合并两集合</h3>\n<p>合并 2 个集合：将集合 1 与集合 2 组成新集合</p>\n<p>该操作得到一个新集合，集合 1 与集合 2 保持不变</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>new_set <span class=\"token operator\">=</span> set1<span class=\"token punctuation\">.</span>union<span class=\"token punctuation\">(</span>set2<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"其他-4\"><a class=\"anchor\" href=\"#其他-4\">#</a> 其他</h2>\n<h3 id=\"统计集合元素数量\"><a class=\"anchor\" href=\"#统计集合元素数量\">#</a> 统计集合元素数量</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>set_name<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"集合的遍历\"><a class=\"anchor\" href=\"#集合的遍历\">#</a> 集合的遍历</h3>\n<p>集合不支持下标索引，不能使用 while 循环遍历</p>\n<p>集合可以使用 for 循环遍历</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> element <span class=\"token keyword\">in</span> set_name</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h1 id=\"字典\"><a class=\"anchor\" href=\"#字典\">#</a> 字典</h1>\n<p>字典（dict）：存储键值对（即，key-value 对），可以提供基于 key 检索 value 的场景实现</p>\n<p>字典不支持重复的 key ，重复添加等同于覆盖原有数据</p>\n<h2 id=\"字典的定义\"><a class=\"anchor\" href=\"#字典的定义\">#</a> 字典的定义</h2>\n<p>使用大括号 {} 包围元素，其中，每一个元素都是一个键值对（key: value），元素之间用逗号隔开</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 定义字典字面量</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token punctuation\">&#123;</span>key<span class=\"token punctuation\">:</span> value<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">:</span> value<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 定义字典变量</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span>key<span class=\"token punctuation\">:</span> value<span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">:</span> value<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 定义空字典</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>变量名称 <span class=\"token operator\">=</span> <span class=\"token builtin\">dict</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>字典的 key 和 value 可以是任意数据类型（key 不可为字典）</p>\n<p>因此可以将 字典 2 作为 字典 1 的 value ，实现字典的嵌套</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>score_dict <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token string\">\"小红\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"语文\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">77</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"数学\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">66</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"英语\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">33</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token string\">\"小明\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"语文\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">88</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"数学\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">86</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"英语\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">55</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token string\">\"小花\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"语文\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">99</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"数学\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">96</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"英语\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">66</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"score_dict 的内容为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span>score_dict<span class=\"token punctuation\">&#125;</span></span><span class=\"token string\">，类型为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>score_dict<span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"小红的语文成绩为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span>score_dict<span class=\"token punctuation\">[</span><span class=\"token string\">'小红'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'语文'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"小明的数学成绩为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span>score_dict<span class=\"token punctuation\">[</span><span class=\"token string\">'小明'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'数学'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"小花的英语成绩为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span>score_dict<span class=\"token punctuation\">[</span><span class=\"token string\">'小花'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'英语'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"字典的方法\"><a class=\"anchor\" href=\"#字典的方法\">#</a> 字典的方法</h2>\n<h3 id=\"访问元素-4\"><a class=\"anchor\" href=\"#访问元素-4\">#</a> 访问元素</h3>\n<p>字典同集合一样，不支持下标索引。但是，字典可以通过 key 来获取对应的 value</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>value <span class=\"token operator\">=</span> dict_name<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span></pre></td></tr></table></figure><h3 id=\"添加更新元素\"><a class=\"anchor\" href=\"#添加更新元素\">#</a> 添加 / 更新元素</h3>\n<p>新增元素 / 更新元素：如果 key 不存在，则新增元素；如果 key 存在，则更新元素（更新 value 值）</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>dict_name<span class=\"token punctuation\">[</span>key<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> value</pre></td></tr></table></figure><h3 id=\"删除元素-2\"><a class=\"anchor\" href=\"#删除元素-2\">#</a> 删除元素</h3>\n<p>将 key 所在键值对从字典中删除</p>\n<p>该操作具有返回值，可以获取 key 所对应的 value</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>value <span class=\"token operator\">=</span> dict_name<span class=\"token punctuation\">.</span>pop<span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"清空字典\"><a class=\"anchor\" href=\"#清空字典\">#</a> 清空字典</h3>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>dict_name<span class=\"token punctuation\">.</span>clear<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"获取-key-列表\"><a class=\"anchor\" href=\"#获取-key-列表\">#</a> 获取 key 列表</h3>\n<p>获取全部的 key</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>keys <span class=\"token operator\">=</span> dict_name<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>my_dict <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"b\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"c\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"d\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>keys <span class=\"token operator\">=</span> my_dict<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"通过 keys 方法获取全部的 key ，结果为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span>keys<span class=\"token punctuation\">&#125;</span></span><span class=\"token string\"> ，其数据类型为：</span><span class=\"token interpolation\"><span class=\"token punctuation\">&#123;</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>keys<span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#125;</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"其他-5\"><a class=\"anchor\" href=\"#其他-5\">#</a> 其他</h2>\n<h3 id=\"统计元素数量-2\"><a class=\"anchor\" href=\"#统计元素数量-2\">#</a> 统计元素数量</h3>\n<p>统计字典的元素数量（一个键值对视为一个元素）</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>dict_name<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"字典的遍历\"><a class=\"anchor\" href=\"#字典的遍历\">#</a> 字典的遍历</h3>\n<p>方式 1：获取全部的 key ，从而实现遍历</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>keys <span class=\"token operator\">=</span> dict_name<span class=\"token punctuation\">.</span>keys<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">for</span> key <span class=\"token keyword\">in</span> keys<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    statement</pre></td></tr></table></figure><p>方式 2：直接对字典进行 for 循环遍历，每次循环都是直接得到 key</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> key <span class=\"token keyword\">in</span> dict_name<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h1 id=\"数据容器的通用操作\"><a class=\"anchor\" href=\"#数据容器的通用操作\">#</a> 数据容器的通用操作</h1>\n<h2 id=\"统计元素数量-3\"><a class=\"anchor\" href=\"#统计元素数量-3\">#</a> 统计元素数量</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"获取最大元素\"><a class=\"anchor\" href=\"#获取最大元素\">#</a> 获取最大元素</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">max</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"获取最小元素\"><a class=\"anchor\" href=\"#获取最小元素\">#</a> 获取最小元素</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">min</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"类型转换\"><a class=\"anchor\" href=\"#类型转换\">#</a> 类型转换</h2>\n<h3 id=\"转为列表\"><a class=\"anchor\" href=\"#转为列表\">#</a> 转为列表</h3>\n<p>将给定容器转换为列表</p>\n<ul>\n<li>若原容器为字符串，则将字符串中的每个字符分别作为列表的一个元素</li>\n<li>若原容器为字典，则将字典的每个 key 分别作为列表的一个元素（value 被舍弃）</li>\n</ul>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">list</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"转为元组\"><a class=\"anchor\" href=\"#转为元组\">#</a> 转为元组</h3>\n<p>将给定容器转换为元组</p>\n<ul>\n<li>若原容器为字符串，则将字符串中的每个字符分别作为元组的一个元素</li>\n<li>若原容器为字典，则将字典的每个 key 分别作为元组的一个元素（value 被舍弃）</li>\n</ul>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">tuple</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h3 id=\"转为字符串\"><a class=\"anchor\" href=\"#转为字符串\">#</a> 转为字符串</h3>\n<p>将给定容器转换为字符串：整个容器（包括容器的组成括号）均被转换为字符串</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>mylist <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>mytuple <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>myset <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>mydict <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"a\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"b\"</span><span class=\"token punctuation\">:</span> <span class=\"token number\">2</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>str1 <span class=\"token operator\">=</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>mylist<span class=\"token punctuation\">)</span>      <span class=\"token comment\"># '[1, 2, 3, 4]'</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>str2 <span class=\"token operator\">=</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>mytuple<span class=\"token punctuation\">)</span>     <span class=\"token comment\"># '(1, 2, 3, 4, 5)'</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>str3 <span class=\"token operator\">=</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>myset<span class=\"token punctuation\">)</span>       <span class=\"token comment\"># '&#123;2, 3, 4, 5&#125;'</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>str4 <span class=\"token operator\">=</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>mydict<span class=\"token punctuation\">)</span>      <span class=\"token comment\"># \"&#123;'a': 1, 'b': 2&#125;\"</span></pre></td></tr></table></figure><h3 id=\"转为集合\"><a class=\"anchor\" href=\"#转为集合\">#</a> 转为集合</h3>\n<p>将给定容器转换为集合</p>\n<ul>\n<li>若原容器为字典，则将字典的每个 key 分别作为集合的一个元素（value 被舍弃）</li>\n</ul>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">set</span><span class=\"token punctuation\">(</span>数据容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><blockquote>\n<p>转换为集合后，原容器的数据有序性将不再保持</p>\n</blockquote>\n<h2 id=\"排序\"><a class=\"anchor\" href=\"#排序\">#</a> 排序</h2>\n<p>将给定容器进行排序：</p>\n<ul>\n<li>排序的结果为列表对象（即，将给定容器的内容进行排序，并将结果放入列表中）</li>\n</ul>\n<p>按升序排序（默认按照升序排序）：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">sorted</span><span class=\"token punctuation\">(</span>容器<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>按降序排序：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin\">sorted</span><span class=\"token punctuation\">(</span>容器<span class=\"token punctuation\">,</span> reverse<span class=\"token operator\">=</span><span class=\"token boolean\">True</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>参考：</p>\n<ul>\n<li><a href=\"https://www.bilibili.com/video/BV1qW4y1a7fU/\">黑马程序员</a></li>\n<li><a href=\"https://www.w3school.com.cn/python/index.asp\">W3school</a></li>\n<li><a href=\"https://www.runoob.com/python3/python3-tutorial.html\">菜鸟教程</a></li>\n</ul>\n",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/python-basics.html",
            "url": "https://jiankychen.github.io/python-basics.html",
            "title": "Python 基本语法",
            "date_published": "2022-11-30T08:09:05.000Z",
            "content_html": "<h1 id=\"条件语句\"><a class=\"anchor\" href=\"#条件语句\">#</a> 条件语句</h1>\n<h2 id=\"if\"><a class=\"anchor\" href=\"#if\">#</a> if</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">if</span> condition<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h2 id=\"if-else\"><a class=\"anchor\" href=\"#if-else\">#</a> if - else</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">if</span> condition<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement1</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    statement2</pre></td></tr></table></figure><h2 id=\"if-eles-if-else\"><a class=\"anchor\" href=\"#if-eles-if-else\">#</a> if - eles if - else</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">if</span> condition1<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement1</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">elif</span> condition2<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    statement2</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    statement3</pre></td></tr></table></figure><h1 id=\"循环语句\"><a class=\"anchor\" href=\"#循环语句\">#</a> 循环语句</h1>\n<h2 id=\"while\"><a class=\"anchor\" href=\"#while\">#</a> while</h2>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">while</span> condition<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h2 id=\"for\"><a class=\"anchor\" href=\"#for\">#</a> for</h2>\n<p>for 循环无法定义循环条件，只能从 序列 中取出数据处理</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> sequence<span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr></table></figure><h2 id=\"range\"><a class=\"anchor\" href=\"#range\">#</a> range</h2>\n<p>range 语句：产生一个序列</p>\n<ul>\n<li><code>range(num)</code> : 从 0 开始、到 num 结束（不包含 num 本身）</li>\n<li><code>range(num1, num2)</code> : 从 num1 开始、到 num2 结束（不包含 num2 本身）</li>\n<li><code>range(num1, num2, step)</code> : 从 num1 开始、到 num2 结束（不包含 num2 本身），步长为 step</li>\n</ul>\n<h2 id=\"continue\"><a class=\"anchor\" href=\"#continue\">#</a> continue</h2>\n<p>continue: 中断本次循环，直接进入下一次循环</p>\n<p>continue 可用于 while 和 for 循环</p>\n<h2 id=\"break\"><a class=\"anchor\" href=\"#break\">#</a> break</h2>\n<p>break: 直接结束循环</p>\n<p>break 可用于 while 和 for 循环</p>\n<h1 id=\"函数\"><a class=\"anchor\" href=\"#函数\">#</a> 函数</h1>\n<p>函数的定义：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span>parameters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    statement</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">return</span> results</pre></td></tr></table></figure><p><strong>函数必须先定义后使用</strong></p>\n<h2 id=\"函数的返回值\"><a class=\"anchor\" href=\"#函数的返回值\">#</a> 函数的返回值</h2>\n<p>如果函数没有 return 语句，将默认返回 None</p>\n<blockquote>\n<p>None 可用于声明无初始内容的变量，并且，None 可用于 if 判断</p>\n</blockquote>\n<p>如果函数有多个返回值，则将多个返回值（用逗号分隔）同时放在一个 return 语句中</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">div</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    quotient <span class=\"token operator\">=</span> x <span class=\"token operator\">//</span> y</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    remainder <span class=\"token operator\">=</span> x <span class=\"token operator\">%</span> y</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">return</span> quotient<span class=\"token punctuation\">,</span> remainder</pre></td></tr></table></figure><h2 id=\"传参方式\"><a class=\"anchor\" href=\"#传参方式\">#</a> 传参方式</h2>\n<h3 id=\"位置参数\"><a class=\"anchor\" href=\"#位置参数\">#</a> 位置参数</h3>\n<p>调用函数时根据函数定义的参数位置来传递参数</p>\n<p>注意：实参的顺序及个数必须与形参列表保持一致</p>\n<h3 id=\"关键字参数\"><a class=\"anchor\" href=\"#关键字参数\">#</a> 关键字参数</h3>\n<p>函数调用时通过 “key=value” 形式传递参数</p>\n<p>可以让函数更见清晰，同时也消除了参数的顺序需求（关键字参数之间不存在先后顺序）</p>\n<p>注意：在调用函数时，如果混用位置参数与关键字参数，必须将位置参数放在关键字参数的前面</p>\n<h3 id=\"缺省参数默认参数\"><a class=\"anchor\" href=\"#缺省参数默认参数\">#</a> 缺省参数（默认参数）</h3>\n<p>定义函数时，如果为参数提供默认值，则在调用函数时可以不传递该默认参数的值</p>\n<p>在调用函数时，如果为缺省参数传递值则修改默认参数值，否则，使用默认值</p>\n<p>注意：无论是定义函数或者调用函数，所有位置参数都必须出现在默认参数之前</p>\n<h3 id=\"不定长参数可变参数\"><a class=\"anchor\" href=\"#不定长参数可变参数\">#</a> 不定长参数（可变参数）</h3>\n<p>不定长参数用于不确定实参数量（不传参也可以）的场景</p>\n<p>不定长参数的类型：</p>\n<ul>\n<li>位置传递</li>\n<li>关键字传递</li>\n</ul>\n<h4 id=\"位置不定长\"><a class=\"anchor\" href=\"#位置不定长\">#</a> 位置不定长</h4>\n<p>位置不定长传递以 * 号标记一个形式参数，以元组的形式接收传入的实参，形式参数一般命名为 args</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">user_info</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>args<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>args<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># ('TOM',)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>user_info<span class=\"token punctuation\">(</span><span class=\"token string\">'TOM'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\"># ('TOM', 18)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>user_info<span class=\"token punctuation\">(</span><span class=\"token string\">'TOM'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">18</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h4 id=\"关键字不定长\"><a class=\"anchor\" href=\"#关键字不定长\">#</a> 关键字不定长</h4>\n<p>关键字不定长传递以 ** 号标记一个形式参数，以字典的形式接收传入的实参，形式参数一般命名为 kwargs</p>\n<p>传递的所有实参均为 &quot;key=value&quot; 形式</p>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">user_info</span><span class=\"token punctuation\">(</span><span class=\"token operator\">**</span>kwargs<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>kwargs<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># ('name': 'TOM', 'age': 18, 'id': 198)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>user_info<span class=\"token punctuation\">(</span>name<span class=\"token operator\">=</span><span class=\"token string\">'TOM'</span><span class=\"token punctuation\">,</span> age<span class=\"token operator\">=</span><span class=\"token number\">18</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">id</span><span class=\"token operator\">=</span><span class=\"token number\">198</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"函数作为参数传递\"><a class=\"anchor\" href=\"#函数作为参数传递\">#</a> 函数作为参数传递</h2>\n<p>函数本身是可以作为参数传入到另一个函数中使用的</p>\n<p>将函数作为参数的作用：传入的是计算逻辑，而不是计算数据</p>\n<h2 id=\"lambda-匿名函数\"><a class=\"anchor\" href=\"#lambda-匿名函数\">#</a> lambda 匿名函数</h2>\n<p>函数的两种定义方式：</p>\n<ul>\n<li><code>def</code>  关键字可以定义带有名称的函数，该函数可以重复使用</li>\n<li><code>lambda</code>  关键字可以定义匿名函数（无名称），该函数只可临时使用一次</li>\n</ul>\n<p>匿名函数的定义：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">lambda</span> 传入参数<span class=\"token punctuation\">:</span> 函数体</pre></td></tr></table></figure><p>其中：</p>\n<ul>\n<li><code>lambda</code>  是关键字，表示定义匿名函数</li>\n<li>传入参数表示匿名函数的形式参数（可以传入多个参数）</li>\n<li>函数体只能写一行，无法写多行代码</li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight python\"><figcaption data-lang=\"python\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># compute 函数作为参数传入 test_func 函数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">test_func</span><span class=\"token punctuation\">(</span>compute<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    result <span class=\"token operator\">=</span> compute<span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">def</span> <span class=\"token function\">compute</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">return</span> x <span class=\"token operator\">+</span> y</pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\"># 通过 def 定义 compute 函数并传入</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>test_func<span class=\"token punctuation\">(</span>compute<span class=\"token punctuation\">)</span>  <span class=\"token comment\"># 结果：3</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token comment\"># 通过 lambda 关键字定义匿名函数并传入</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>test_func<span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">:</span> x <span class=\"token operator\">+</span> y<span class=\"token punctuation\">)</span>   <span class=\"token comment\"># 结果：3</span></pre></td></tr></table></figure><h1 id=\"局部变量与全局变量\"><a class=\"anchor\" href=\"#局部变量与全局变量\">#</a> 局部变量与全局变量</h1>\n<p>局部变量：定义在函数体内部的变量，只在函数体内部生效</p>\n<p>全局变量：在函数体内、外都能生效的变量</p>\n<p>在函数内无法修改全局变量</p>\n<blockquote>\n<p>如果尝试在函数内部修改全局变量，实际上是定义了一个与全局变量同名的局部变量</p>\n</blockquote>\n<p>使用 global 关键字，可以在函数内部声明变量为全局变量</p>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://www.bilibili.com/video/BV1qW4y1a7fU/\">黑马程序员</a></li>\n<li><a href=\"https://www.w3school.com.cn/python/index.asp\">W3school</a></li>\n<li><a href=\"https://www.runoob.com/python3/python3-tutorial.html\">菜鸟教程</a></li>\n</ul>\n",
            "tags": [
                "Python"
            ]
        },
        {
            "id": "https://jiankychen.github.io/leetcode-analog.html",
            "url": "https://jiankychen.github.io/leetcode-analog.html",
            "title": "LeetCode - 模拟专题",
            "date_published": "2022-10-28T12:35:22.000Z",
            "content_html": "<h1 id=\"leetcode-463-岛屿的周长\"><a class=\"anchor\" href=\"#leetcode-463-岛屿的周长\">#</a> LeetCode 463. 岛屿的周长</h1>\n<p><a href=\"https://leetcode.cn/problems/island-perimeter/\">LeetCode 463. Island Perimeter</a></p>\n<p>给定一个  <code>row x col</code>  的二维网格地图  <code>grid</code>  ，其中： <code>grid[i][j] = 1</code>  表示陆地， <code>grid[i][j] = 0</code>  表示水域</p>\n<p>网格中的格子 <strong>水平</strong> 和 <strong>垂直</strong> 方向相连（对角线方向不相连）。整个网格被水完全包围，但其中恰好有一个岛屿（或者说，一个或多个表示陆地的格子相连组成的岛屿）</p>\n<p>岛屿中没有 “湖”（“湖” 是指水域在岛屿内部且不和岛屿周围的水相连）。格子是边长为 1 的正方形。网格为长方形，且宽度和高度均不超过 100 。计算这个岛屿的周长</p>\n<p><strong>示例 1：</strong></p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode463_Example1.png\" alt=\"\" /></p>\n<pre><code>输入：grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]\n输出：16\n解释：它的周长是上面图片中的 16 个黄色的边\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：grid = [[1]]\n输出：4\n</code></pre>\n<p><strong>示例 3：</strong></p>\n<pre><code>输入：grid = [[1,0]]\n输出：4\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><code>row == grid.length</code></li>\n<li><code>col == grid[i].length</code></li>\n<li><code>1 &lt;= row, col &lt;= 100</code></li>\n<li><code>grid[i][j]</code>  为  <code>0</code>  或  <code>1</code></li>\n</ul>\n<h2 id=\"method-1-模拟\"><a class=\"anchor\" href=\"#method-1-模拟\">#</a> Method 1: 模拟</h2>\n<h2 id=\"算法思路\"><a class=\"anchor\" href=\"#算法思路\">#</a> 算法思路</h2>\n<p>对于一个岛屿格子的每条边：如果这条边为网格的边界，或者这条边是岛屿与水域的分界线，则需将这条边计入岛屿的周长</p>\n<p>因此，可以遍历每个岛屿格子，看其四个方向的边是否为网格边界或水域分界线，如果是，则计入岛屿周长</p>\n<h2 id=\"代码实现\"><a class=\"anchor\" href=\"#代码实现\">#</a> 代码实现</h2>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">islandPerimeter</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> m <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> dir <span class=\"token operator\">=</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">!</span><span class=\"token operator\">--</span>swig￼<span class=\"token number\">0</span><span class=\"token operator\">--</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> res <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> m<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> k <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> k <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>k<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>                <span class=\"token keyword\">int</span> x <span class=\"token operator\">=</span> i <span class=\"token operator\">+</span> dir<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>                <span class=\"token keyword\">int</span> y <span class=\"token operator\">=</span> j <span class=\"token operator\">+</span> dir<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">==</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span> <span class=\"token operator\">||</span> x <span class=\"token operator\">==</span> m <span class=\"token operator\">||</span> y <span class=\"token operator\">==</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span> <span class=\"token operator\">||</span> y <span class=\"token operator\">==</span> n<span class=\"token punctuation\">)</span> <span class=\"token operator\">++</span>res<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 网格边界</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>                <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>y<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">++</span>res<span class=\"token punctuation\">;</span>                   <span class=\"token comment\">// 水域分界线</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"复杂度分析\"><a class=\"anchor\" href=\"#复杂度分析\">#</a> 复杂度分析</h2>\n<p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>，其中，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 分别为网格的行数和列数</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></p>\n<h2 id=\"method-2-深度优先搜索\"><a class=\"anchor\" href=\"#method-2-深度优先搜索\">#</a> Method 2: 深度优先搜索</h2>\n<h2 id=\"算法思路-2\"><a class=\"anchor\" href=\"#算法思路-2\">#</a> 算法思路</h2>\n<p>可以将方法一改成深度优先搜索遍历的方式（该方式可以拓展至多个岛屿情形）</p>\n<p>其中，为避免岛屿格子被重复遍历，需要将已经遍历过的岛屿格子标记。特别地，可以将已经遍历过的岛屿格子的值置为 -1 （不能置为 0，因为置 0 会形成新的 “水域边界线”，进而导致结果出错）</p>\n<h2 id=\"代码实现-2\"><a class=\"anchor\" href=\"#代码实现-2\">#</a> 代码实现</h2>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> dir <span class=\"token operator\">=</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">!</span><span class=\"token operator\">--</span>swig￼<span class=\"token number\">1</span><span class=\"token operator\">--</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">dfs</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> x<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> y<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> m <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>x <span class=\"token operator\">==</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span> <span class=\"token operator\">||</span> x <span class=\"token operator\">==</span> m <span class=\"token operator\">||</span> y <span class=\"token operator\">==</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span> <span class=\"token operator\">||</span> y <span class=\"token operator\">==</span> n<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>y<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>y<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    grid<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>y<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">int</span> count <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> k <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> k <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>k<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">int</span> newx <span class=\"token operator\">=</span> x <span class=\"token operator\">+</span> dir<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">int</span> newy <span class=\"token operator\">=</span> y <span class=\"token operator\">+</span> dir<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        count <span class=\"token operator\">+=</span> <span class=\"token function\">dfs</span><span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">,</span> newx<span class=\"token punctuation\">,</span> newy<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">return</span> count<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">islandPerimeter</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">int</span> m <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">int</span> ans <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> m<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>                ans <span class=\"token operator\">+=</span> <span class=\"token function\">dfs</span><span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">,</span> j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token keyword\">return</span> ans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"复杂度分析-2\"><a class=\"anchor\" href=\"#复杂度分析-2\">#</a> 复杂度分析</h2>\n<p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>，其中，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 分别为网格的行数和列数</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>参考：<a href=\"https://leetcode.cn/problems/island-perimeter/solution/dao-yu-de-zhou-chang-by-leetcode-solution/\">力扣官方题解</a></p>\n<h1 id=\"leetcode-48-旋转图像\"><a class=\"anchor\" href=\"#leetcode-48-旋转图像\">#</a> LeetCode 48. 旋转图像</h1>\n<p><a href=\"https://leetcode.cn/problems/rotate-image/\">48. Rotate Image</a></p>\n<p>给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。</p>\n<p>你必须在 原地 旋转图像，这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。</p>\n<p><strong>示例 1：</strong></p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode48_Example1.jpg\" alt=\"\" /></p>\n<pre><code>输入：matrix = [[1,2,3],[4,5,6],[7,8,9]]\n输出：[[7,4,1],[8,5,2],[9,6,3]]\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode48_Example2.jpg\" alt=\"\" /></p>\n<pre><code>输入：matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]\n输出：[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><code>n == matrix.length == matrix[i].length</code></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>n</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>20</mn></mrow><annotation encoding=\"application/x-tex\">\\le 20</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">20</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>−</mo><mn>1000</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">-1000 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">−</span><span class=\"mord\">1000</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>matrix[i][j]</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>1000</mn></mrow><annotation encoding=\"application/x-tex\">\\le 1000</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1000</span></span></span></span></li>\n</ul>\n<h2 id=\"method-1-原地旋转\"><a class=\"anchor\" href=\"#method-1-原地旋转\">#</a> Method 1: 原地旋转</h2>\n<p>经过观察，可以发现：</p>\n<ul>\n<li>\n<p>原矩阵中的位置 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span></span></span></span> ，旋转后的目标位置为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[j][n - i - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span></p>\n</li>\n<li>\n<p>原矩阵中的位置 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[j][n - i - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span> ，旋转后的目标位置为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[n - i - 1][n - j - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span></p>\n</li>\n<li>\n<p>原矩阵中的位置 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[n - i - 1][n - j - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span> ，旋转后的目标位置为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[n - j - 1][i]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span></span></span></span></p>\n</li>\n<li>\n<p>原矩阵中的位置 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[n - j - 1][i]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span></span></span></span> ，旋转后的目标位置为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span></span></span></span></p>\n</li>\n</ul>\n<p>即，对于 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span></span></span></span> 、<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[j][n - i - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span> 、<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[n - i - 1][n - j - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span> 、<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[n - j - 1][i]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span></span></span></span> 而言，每一项旋转后的位置就是下一项所在的位置</p>\n<p>因此，可以引入一个临时变量  <code>tmp</code>  ，完成这四项的原地交换</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> tmp <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>matrix<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>matrix<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> tmp<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>那么，我们应该枚举哪些 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi></mrow><annotation encoding=\"application/x-tex\">i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>j</mi></mrow><annotation encoding=\"application/x-tex\">j</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span></span></span></span> 呢？</p>\n<p>每一次可以交换四个位置的元素：</p>\n<ul>\n<li>\n<p>当 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 为偶数时，此时需要枚举 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup><mi mathvariant=\"normal\">/</mi><mn>4</mn><mo>=</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mi mathvariant=\"normal\">/</mi><mn>2</mn><mo stretchy=\"false\">)</mo><mo>×</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mi mathvariant=\"normal\">/</mi><mn>2</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">n^2 / 4 = (n / 2) \\times (n / 2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mord\">/4</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mord\">/2</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mord\">/2</span><span class=\"mclose\">)</span></span></span></span> 个位置。因此，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi></mrow><annotation encoding=\"application/x-tex\">i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>j</mi></mrow><annotation encoding=\"application/x-tex\">j</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span></span></span></span> 分别遍历 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mi mathvariant=\"normal\">/</mi><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">n / 2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mord\">/2</span></span></span></span> 个位置，以 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>4</mn><mo>×</mo><mn>4</mn></mrow><annotation encoding=\"application/x-tex\">4 \\times 4</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">4</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">4</span></span></span></span> 矩阵为例</p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode48_pic1.png\" alt=\"\" height=\"150px\" /></p>\n</li>\n<li>\n<p>当 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 为奇数时，由于中心位置始终不变，需要枚举 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>4</mn><mo>=</mo><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>2</mn><mo stretchy=\"false\">)</mo><mo>×</mo><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>2</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">(n^2 - 1) / 4 = ((n - 1) / 2) \\times ((n + 1) / 2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/4</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">((</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/2</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">((</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/2</span><span class=\"mclose\">)</span></span></span></span> 个位置。因此，i 遍历 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">(n - 1) / 2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/2</span></span></span></span> 个位置、j 遍历 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">(n + 1) / 2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/2</span></span></span></span> 个位置，以 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>5</mn><mo>×</mo><mn>5</mn></mrow><annotation encoding=\"application/x-tex\">5 \\times 5</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em;\"></span><span class=\"mord\">5</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">5</span></span></span></span> 矩阵为例</p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode48_pic2.png\" alt=\"\" height=\"150px\" /></p>\n</li>\n</ul>\n<p>因此，无论 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 是奇数还是偶数，均可按照 “ <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>i</mi></mrow><annotation encoding=\"application/x-tex\">i</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em;\"></span><span class=\"mord mathnormal\">i</span></span></span></span> 遍历 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mi mathvariant=\"normal\">/</mi><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">n / 2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mord\">/2</span></span></span></span> 个位置、<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>j</mi></mrow><annotation encoding=\"application/x-tex\">j</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.854em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span></span></span></span> 遍历 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mi mathvariant=\"normal\">/</mi><mn>2</mn></mrow><annotation encoding=\"application/x-tex\">(n + 1) / 2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mord\">/2</span></span></span></span> 个位置 ” 来处理，即， <code>i</code>  遍历  <code>[0, n / 2)</code>  ， <code>j</code>  遍历  <code>[0, (n + 1) / 2)</code></p>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">rotate</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> matrix<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> <span class=\"token punctuation\">(</span>n <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> j<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>            <span class=\"token keyword\">int</span> tmp <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> tmp<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></p>\n<h2 id=\"method-2-翻转\"><a class=\"anchor\" href=\"#method-2-翻转\">#</a> Method 2: 翻转</h2>\n<p>算法思路：</p>\n<p>首先进行上下翻转，然后进行对角线翻转（即，转置）</p>\n<p>理论推导：</p>\n<p>对于上下翻转：只需要枚举矩阵上半部分的元素，并将其与下半部分对应位置的元素进行交换，即</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo>⟷</mo><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j] \\longleftrightarrow matrix[n - i - 1][j]\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟷</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span></span></span></span></span></p>\n<p>对于对角线翻转：只需要枚举对角线左侧的元素，并将其与右侧对应位置的元素进行交换，即</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo>⟷</mo><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j] \\longleftrightarrow matrix[j][i]\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟷</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span></span></span></span></span></p>\n<p>联立以上两式可得</p>\n<p><span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo>⟶</mo><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo>⟶</mo><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j] \\longrightarrow matrix[n - i - 1][j] \\longrightarrow matrix[j][n - i - 1]\n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟶</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">⟶</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span></span></p>\n<p>即，实现了将 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>i</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[i][j]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">i</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span></span></span></span> 旋转 90 度、放到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mi>a</mi><mi>t</mi><mi>r</mi><mi>i</mi><mi>x</mi><mo stretchy=\"false\">[</mo><mi>j</mi><mo stretchy=\"false\">]</mo><mo stretchy=\"false\">[</mo><mi>n</mi><mo>−</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">matrix[j][n - i - 1]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">ma</span><span class=\"mord mathnormal\">t</span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">r</span><span class=\"mord mathnormal\">i</span><span class=\"mord mathnormal\">x</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\" style=\"margin-right:0.05724em;\">j</span><span class=\"mclose\">]</span><span class=\"mopen\">[</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7429em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">]</span></span></span></span> 位置</p>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">rotate</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> matrix<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> matrix<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 上下翻转</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> j<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>            <span class=\"token function\">swap</span><span class=\"token punctuation\">(</span>matrix<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>     <span class=\"token comment\">// 对角线翻转</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> i<span class=\"token punctuation\">;</span> j<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            <span class=\"token function\">swap</span><span class=\"token punctuation\">(</span>matrix<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> matrix<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>参考：<a href=\"https://leetcode.cn/problems/rotate-image/solution/xuan-zhuan-tu-xiang-by-leetcode-solution-vu3m/\">leetcode-solution</a></p>\n<h1 id=\"leetcode-59-螺旋矩阵-ii\"><a class=\"anchor\" href=\"#leetcode-59-螺旋矩阵-ii\">#</a> LeetCode 59. 螺旋矩阵 II</h1>\n<p><a href=\"https://leetcode-cn.com/problems/spiral-matrix-ii/\">LeetCode 59. Spiral Matrix II</a></p>\n<p>给你一个正整数 n ，生成一个包含 1 到 n2 所有元素，且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。</p>\n<p><strong>示例 1：</strong></p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode59_1.jpg\" alt=\"\" /></p>\n<pre><code>输入：n = 3\n输出：[[1,2,3],[8,9,4],[7,6,5]]\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：n = 1\n输出：[[1]]\n</code></pre>\n<p></p>\n<p><strong>提示：</strong></p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>n</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>20</mn></mrow><annotation encoding=\"application/x-tex\">\\le 20</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">20</span></span></span></span></li>\n</ul>\n<h2 id=\"method-模拟\"><a class=\"anchor\" href=\"#method-模拟\">#</a> Method: 模拟</h2>\n<p>思路：<strong>模拟</strong> 顺时针画矩阵的过程，即</p>\n<ul>\n<li>\n<p>填充上行从左到右</p>\n</li>\n<li>\n<p>填充右列从上到下</p>\n</li>\n<li>\n<p>填充下行从右到左</p>\n</li>\n<li>\n<p>填充左列从下到上</p>\n</li>\n</ul>\n<p>由外向内一圈一圈这么画下去</p>\n<p>注意：每画一条边都要坚持一致的 <strong>左闭右开</strong> ，或者 <strong>左开又闭</strong> 的原则，这样这一圈才能按照统一的规则画下来</p>\n<blockquote>\n<p>坚持 <strong>循环不变量</strong> 原则</p>\n</blockquote>\n<p>下图以左闭右开原则为例：每一种颜色，代表一条边，注意每一个拐角处的处理规则，拐角处让给新的一条边来继续画（即，每条边都遵循左闭右开原则）</p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode59_2.png\" alt=\"\" /></p>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> <span class=\"token function\">generateMatrix</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> <span class=\"token function\">matrix</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> <span class=\"token generic-function\"><span class=\"token function\">vector</span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>                        <span class=\"token comment\">// 填充的数字</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>   <span class=\"token comment\">// 每次循环填充一圈</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token keyword\">int</span> start <span class=\"token operator\">=</span> i<span class=\"token punctuation\">;</span>                  <span class=\"token comment\">// 填充的起点</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">int</span> len <span class=\"token operator\">=</span> n <span class=\"token operator\">-</span> i <span class=\"token operator\">*</span> <span class=\"token number\">2</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 每个方向的填充长度</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> len<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 上面一行，从左往右填充</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>start <span class=\"token operator\">+</span> j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> num<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> len<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 右边一列，从上往下填充</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>start <span class=\"token operator\">+</span> j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>start <span class=\"token operator\">+</span> len<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> num<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> len<span class=\"token punctuation\">;</span> j <span class=\"token operator\">>=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">--</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 下面一行，从右往左填充</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>start <span class=\"token operator\">+</span> len<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>start <span class=\"token operator\">+</span> j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> num<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> len<span class=\"token punctuation\">;</span> j <span class=\"token operator\">>=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">--</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 左边一列，从下往上填充</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            matrix<span class=\"token punctuation\">[</span>start <span class=\"token operator\">+</span> j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> num<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>n <span class=\"token operator\">%</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> matrix<span class=\"token punctuation\">[</span>n <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>n <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> n <span class=\"token operator\">*</span> n<span class=\"token punctuation\">;</span> <span class=\"token comment\">//n 为奇数，数组最中间的位置需要单独处理</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">return</span> matrix<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span>，需要填充 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding=\"application/x-tex\">n^2</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8141em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span> 个元素</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></p>\n<p>参考：<a href=\"https://www.programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html#%E6%80%9D%E8%B7%AF\">代码随想录：螺旋矩阵 II</a></p>\n<h1 id=\"leetcode-621-任务调度器\"><a class=\"anchor\" href=\"#leetcode-621-任务调度器\">#</a> LeetCode 621. 任务调度器</h1>\n<p><a href=\"https://leetcode.cn/problems/task-scheduler/\">621. Task Scheduler</a></p>\n<p>给你一个用字符数组  <code>tasks</code>  表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行，并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间，CPU 可以完成一个任务，或者处于待命状态。</p>\n<p>然而，两个 <strong>相同种类</strong> 的任务之间必须有长度为整数  <code>n</code>  的冷却时间，因此至少有连续  <code>n</code>  个单位时间内 CPU 在执行不同的任务，或者在待命状态。</p>\n<p>你需要计算 <strong>完成所有任务所需要的最短时间</strong> 。</p>\n<p><strong>示例 1：</strong></p>\n<pre><code>输入：tasks = [&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;B&quot;,&quot;B&quot;,&quot;B&quot;], n = 2\n输出：8\n解释：\nA -&gt; B -&gt; idle -&gt; A -&gt; B -&gt; idle -&gt; A -&gt; B\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：tasks = [&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;B&quot;,&quot;B&quot;,&quot;B&quot;], n = 0\n输出：6\n解释：在这种情况下，任何大小为 6 的排列都可以满足要求，因为 n = 0\n[&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;B&quot;,&quot;B&quot;,&quot;B&quot;]\n[&quot;A&quot;,&quot;B&quot;,&quot;A&quot;,&quot;B&quot;,&quot;A&quot;,&quot;B&quot;]\n[&quot;B&quot;,&quot;B&quot;,&quot;B&quot;,&quot;A&quot;,&quot;A&quot;,&quot;A&quot;]\n...\n诸如此类\n</code></pre>\n<p><strong>示例 3：</strong></p>\n<pre><code>输入：tasks = [&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;,&quot;F&quot;,&quot;G&quot;], n = 2\n输出：16\n解释：一种可能的解决方案：\nA -&gt; B -&gt; C -&gt; A -&gt; D -&gt; E -&gt; A -&gt; F -&gt; G -&gt; A -&gt; (待命) -&gt; (待命) -&gt; A -&gt; (待命) -&gt; (待命) -&gt; A\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>task.length</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding=\"application/x-tex\">\\le 10^4</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8141em;\"></span><span class=\"mord\">1</span><span class=\"mord\"><span class=\"mord\">0</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">4</span></span></span></span></span></span></span></span></span></span></span></li>\n<li><code>tasks[i]</code>  是大写英文字母</li>\n<li><code>n</code>  的取值范围为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">[</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>100</mn><mo stretchy=\"false\">]</mo></mrow><annotation encoding=\"application/x-tex\">[0, 100]</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">[</span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\">100</span><span class=\"mclose\">]</span></span></span></span></li>\n</ul>\n<h2 id=\"method-桶思想\"><a class=\"anchor\" href=\"#method-桶思想\">#</a> Method: 桶思想</h2>\n<h2 id=\"算法思路-3\"><a class=\"anchor\" href=\"#算法思路-3\">#</a> 算法思路</h2>\n<p>使用一个宽为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">n + 1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">1</span></span></span></span> 的矩阵来展示任务执行方案，其中，任务按照逐行遍历的顺序执行，空白格子对应 CPU 的待命状态</p>\n<p>于是，可以将具有最大数量的任务排布在矩阵的第一列，将其余任务依次排布成列。由于冷却时间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span>，上述排列方案可以保证满足题目要求，并且总时间最小</p>\n<ul>\n<li>\n<p>情况一：冷却时间长、任务种类和数量很少，假设所有任务种类中的最大数量为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mtext>maxn</mtext></mrow><annotation encoding=\"application/x-tex\">\\textrm{maxn}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord text\"><span class=\"mord textrm\">maxn</span></span></span></span></span>（即，矩阵的行数），具有最大数量的任务的种类数为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mtext>cnt</mtext></mrow><annotation encoding=\"application/x-tex\">\\textrm{cnt}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6151em;\"></span><span class=\"mord text\"><span class=\"mord textrm\">cnt</span></span></span></span></span>（即，矩阵最后一行的任务数量），则执行任务所需的时间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo stretchy=\"false\">(</mo><mtext>maxn</mtext><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>×</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mtext>cnt</mtext></mrow><annotation encoding=\"application/x-tex\">(\\textrm{maxn} - 1) \\times (n + 1) + \\textrm{cnt}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord text\"><span class=\"mord textrm\">maxn</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6151em;\"></span><span class=\"mord text\"><span class=\"mord textrm\">cnt</span></span></span></span></span></p>\n<ul>\n<li>示例 1： <img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode621_Example1.png\" alt=\"\" /></li>\n<li>示例 3： <img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode621_Example3.png\" alt=\"\" /></li>\n</ul>\n</li>\n<li>\n<p>情况二：冷却时间短、任务种类或数量很多，可以拓展矩阵的列数，并将任务排布在拓展的列中。此时，每个任务之间都不存在待命时间，因此，执行任务所需的时间就是任务的数量，即 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∣</mi><mtext>tasks</mtext><mi mathvariant=\"normal\">∣</mi></mrow><annotation encoding=\"application/x-tex\">\\vert \\textrm{tasks} \\vert</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣</span><span class=\"mord text\"><span class=\"mord textrm\">tasks</span></span><span class=\"mord\">∣</span></span></span></span></p>\n<ul>\n<li><img loading=\"lazy\" data-src=\"LeetCode-%E6%A8%A1%E6%8B%9F%E4%B8%93%E9%A2%98/LeetCode621_%E7%A4%BA%E4%BE%8B.png\" alt=\"\" /></li>\n</ul>\n</li>\n</ul>\n<p>因此，需要的最少时间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>max</mi><mo>⁡</mo><mrow><mo stretchy=\"false\">(</mo><mi mathvariant=\"normal\">∣</mi><mtext>tasks</mtext><mi mathvariant=\"normal\">∣</mi><mo separator=\"true\">,</mo><mo stretchy=\"false\">(</mo><mtext>maxn</mtext><mo>−</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>×</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy=\"false\">)</mo><mo>+</mo><mtext>cnt</mtext><mo stretchy=\"false\">)</mo></mrow></mrow><annotation encoding=\"application/x-tex\">\\max{(\\vert \\textrm{tasks} \\vert, (\\textrm{maxn} - 1) \\times (n + 1) + \\textrm{cnt})}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mop\">max</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mopen\">(</span><span class=\"mord\">∣</span><span class=\"mord text\"><span class=\"mord textrm\">tasks</span></span><span class=\"mord\">∣</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mopen\">(</span><span class=\"mord text\"><span class=\"mord textrm\">maxn</span></span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord\">1</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mord text\"><span class=\"mord textrm\">cnt</span></span><span class=\"mclose\">)</span></span></span></span></span></p>\n<p>具体可参考 <a href=\"https://leetcode.cn/problems/task-scheduler/solution/tong-zi-by-popopop/\">popopop</a></p>\n<h2 id=\"代码实现-3\"><a class=\"anchor\" href=\"#代码实现-3\">#</a> 代码实现</h2>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">leastInterval</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">char</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> tasks<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">rec</span><span class=\"token punctuation\">(</span><span class=\"token number\">26</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> c <span class=\"token operator\">:</span> tasks<span class=\"token punctuation\">)</span> <span class=\"token comment\">// 记录每种任务的数量</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token operator\">++</span>rec<span class=\"token punctuation\">[</span>c <span class=\"token operator\">-</span> <span class=\"token char\">'A'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> maxn <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 任务的最大数量</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">int</span> cnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>         <span class=\"token comment\">// 具有最大数量的任务种类数</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> num <span class=\"token operator\">:</span> rec<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>num <span class=\"token operator\">></span> maxn<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            maxn <span class=\"token operator\">=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            cnt <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>num <span class=\"token operator\">==</span> maxn<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token operator\">++</span>cnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token function\">max</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span>tasks<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>maxn <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span>n <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> cnt<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"复杂度分析-3\"><a class=\"anchor\" href=\"#复杂度分析-3\">#</a> 复杂度分析</h2>\n<p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi mathvariant=\"normal\">∣</mi><mi mathvariant=\"normal\">Σ</mi><mi mathvariant=\"normal\">∣</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + \\vert \\Sigma \\vert)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣Σ∣</span><span class=\"mclose\">)</span></span></span></span>，其中，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 为数组 tasks 的长度，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">∣</mi><mi mathvariant=\"normal\">Σ</mi><mi mathvariant=\"normal\">∣</mi></mrow><annotation encoding=\"application/x-tex\">\\vert \\Sigma \\vert</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord\">∣Σ∣</span></span></span></span> 为数组 tasks 中可能出现的任务种类数</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi mathvariant=\"normal\">∣</mi><mi mathvariant=\"normal\">Σ</mi><mi mathvariant=\"normal\">∣</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(\\vert \\Sigma \\vert)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">∣Σ∣</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://leetcode.cn/problems/task-scheduler/solution/tong-zi-by-popopop/\">popopop</a></li>\n<li><a href=\"https://leetcode.cn/problems/task-scheduler/solution/ren-wu-diao-du-qi-by-leetcode-solution-ur9w/\">leetcode-solution</a></li>\n</ul>\n",
            "tags": [
                "Coding",
                "模拟"
            ]
        },
        {
            "id": "https://jiankychen.github.io/cpp-classes.html",
            "url": "https://jiankychen.github.io/cpp-classes.html",
            "title": "C++ 类",
            "date_published": "2022-10-25T14:11:12.000Z",
            "content_html": "<h1 id=\"定义抽象数据类型\"><a class=\"anchor\" href=\"#定义抽象数据类型\">#</a> 定义抽象数据类型</h1>\n<p>类的基本思想是<strong>数据抽象</strong>（data abstraction）和<strong>封装</strong>（encapsulation）</p>\n<p>数据抽象是一种依赖于<strong>接口</strong>（interface）和<strong>实现</strong>（implementation）分离的编程（以及设计）技术</p>\n<ul>\n<li>类的接口：包括用户所能执行的操作</li>\n<li>类的实现：包括类的数据成员、负责接口实现的函数体以及定义类所需的各种私有函数</li>\n</ul>\n<p>封装实现了类的接口和实现的分离。封装后的类隐藏了它的实现细节，也就是说，类的用户只能使用接口而无法访问实现部分</p>\n<p>类要想实现数据抽象和封装，需要首先定义一个<strong>抽象数据类型</strong>（abstract data type）</p>\n<ul>\n<li>在抽象数据类型中，由类的设计者负责考虑类的实现过程</li>\n<li>使用该类的程序员则只需要抽象地思考类型做了什么，而无须了解类型的工作细节</li>\n</ul>\n<p>本节将以 Sales_data 类为例，介绍类的定义与使用</p>\n<h2 id=\"设计-sales_data-类\"><a class=\"anchor\" href=\"#设计-sales_data-类\">#</a> 设计 Sales_data 类</h2>\n<p>我们希望 Sales_item 类有一个名为 isbn 的成员函数（member function），并且具有一些等效于 + 、= 、+= 、&lt;&lt;和&gt;&gt; 运算符的函数</p>\n<p>于是，Sales_data 的接口应该包含以下操作：</p>\n<ul>\n<li>一个 isbn 成员函数，用于返回对象的 ISBN 编号</li>\n<li>一个 combine 成员函数，用于将一个 Sales_data 对象加到另一个对象上（等效于 += 运算符）</li>\n<li>一个名为 add 的普通函数，执行两个 Sales_data 对象的加法（等效于 + 运算符）</li>\n<li>一个名为 read 的普通函数，将数据从 istream 读入到 Sales_data 对象中（等效于 &gt;&gt; 运算符）</li>\n<li>一个名为 print 的函数，将 Sales_data 对象的值输出到 ostream （等效于 &lt;&lt; 运算符）</li>\n</ul>\n<p>定义 Sales_data 类如下所示：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">Sales_data</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 数据成员</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string bookNo<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> units_sold <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">double</span> revenue <span class=\"token operator\">=</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 成员函数：关于 Sales_data 对象的操作</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> bookNo<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    Sales_data<span class=\"token operator\">&amp;</span> <span class=\"token function\">combine</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">double</span> <span class=\"token function\">avg_price</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token comment\">// 非成员的普通函数</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>Sales_data <span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>ostream <span class=\"token operator\">&amp;</span><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>ostream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>istream <span class=\"token operator\">&amp;</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>其中，Sales_data 类的数据成员包括：bookNo 、units_sold 、revenue ，分别表示书本的 ISBN 编号、销量、总销售额；Sales_data 类的成员函数包括 isbn 和 combine ；add、read 和 print 则是普通函数，并未作为 Sales_data 类的成员</p>\n<p>Sales_data 类的使用示例：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Sales_data total<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">,</span> total<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>  <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    Sales_data trans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">,</span> trans<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>total<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> trans<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>            total<span class=\"token punctuation\">.</span><span class=\"token function\">combine</span><span class=\"token punctuation\">(</span>trans<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token function\">print</span><span class=\"token punctuation\">(</span>cout<span class=\"token punctuation\">,</span> total<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            total <span class=\"token operator\">=</span> trans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span>cout<span class=\"token punctuation\">,</span> total<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    cerr <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"No data?!\"</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"定义成员函数\"><a class=\"anchor\" href=\"#定义成员函数\">#</a> 定义成员函数</h3>\n<p><strong>成员函数的声明必须在类的内部，它的定义既可以在类的内部也可以在类的外部</strong></p>\n<p>例如，上述的 isbn 函数定义在 Sales_data 类的内部，combine 和 avg_price 定义在类的外部</p>\n<p>和其他函数一样，类的成员函数也由函数类型、函数名、形参列表和函数体组成。以 isbn 函数为例，isbn 函数用于返回 Sales_data 对象的 bookNo 数据成员，其定义为</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> bookNo<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>然而，isbn 函数是如何获得 bookNo 成员所依赖的对象的呢？</p>\n<h4 id=\"this\"><a class=\"anchor\" href=\"#this\">#</a> this</h4>\n<p>不妨先观察 isbn 成员函数的调用：使用点运算符访问 trans 对象的 isbn 成员，由此来调用该函数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Sales_data trans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>trans<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p><strong>成员函数通过一个名为 <strong> <code>this</code> </strong> 的隐式参数来访问调用它的那个对象</strong>。具体来说，当我们调用一个成员函数时，请求该函数的对象地址 将会被用于初始化  <code>this</code></p>\n<p>例如，如果调用  <code>trans.isbn()</code>  ，编译器将会把 trans 的地址传递给 isbn 函数的隐式形参  <code>this</code>  。可以等价地认为，编译器将  <code>trans.isbn()</code>  这一调用重写成了如下形式：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 伪代码，用于说明调用成员函数的实际执行过程</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token class-name\">Sales_data</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>trans<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>其中，调用 Sales_data 的 isbn 成员时传入了 trans 的地址</p>\n<p>在成员函数内部，可以直接使用调用该函数的对象的成员，而无须通过成员访问运算符来做到这一点，因为  <code>this</code>  所指的就是当前对象。<strong>任何对类成员的直接访问都被看作  <code>this</code>  的隐式引用</strong>，也就是说，当 isbn 使用 bookNo 时，它隐式地使用  <code>this</code>  指向的成员，就像我们书写了 this-&gt;bookNo 一样</p>\n<p>this 形参是隐式定义的。任何自定义名为 this 的参数或变量都是非法的</p>\n<p>我们可以在成员函数体内部使用 this （尽管没有必要）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token operator\">-></span>bookNo<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>需要注意，<strong> <code>this</code>  是一个常量指针</strong>，不允许改变  <code>this</code>  中保存的地址</p>\n<h4 id=\"const-成员函数\"><a class=\"anchor\" href=\"#const-成员函数\">#</a> const 成员函数</h4>\n<p>isbn 函数的另一个关键之处：参数列表后的  <code>const</code>  关键字，用于修改隐式  <code>this</code>  指针的类型</p>\n<p>默认情况下， <code>this</code>  的类型是指向类类型非常量版本的常量指针。例如，在 Sales_data 的成员函数中，this 的类型是 Sales_data *const</p>\n<p>尽管  <code>this</code>  是隐式的，也依然需要遵循初始化规则，这意味着：（在默认情况下）我们不能把  <code>this</code>  绑定到一个常量对象上，即，我们不能在一个常量对象上调用普通的成员函数（不加  <code>const</code>  的成员函数）</p>\n<p>于是，我们不禁会想到：如果想要在常量对象上调用普通成员函数，就应该将  <code>this</code>  声明成指向常量的指针（即，const Sales_data *const ）。然而， <code>this</code>  是隐式的，并不会出现在参数列表中。那我们应该在哪里将  <code>this</code>  声明成指向常量的指针呢？</p>\n<p>C++ 语言的做法是：允许把  <code>const</code>  关键字放在成员函数的参数列表之后，此时，紧跟在参数列表后面的  <code>const</code>  表示  <code>this</code>  是一个指向常量的指针</p>\n<p>像这样使用  <code>const</code>  的成员函数被称作 <strong>常量成员函数</strong>（const member function）</p>\n<p>因为  <code>this</code>  是指向常量的指针，常量成员函数不能改变调用它的对象的内容</p>\n<p><strong>常量对象，以及常量对象的引用或指针都只能调用常量成员函数</strong></p>\n<h4 id=\"类作用域和成员函数\"><a class=\"anchor\" href=\"#类作用域和成员函数\">#</a> 类作用域和成员函数</h4>\n<p>类本身就是一个作用域，类成员函数的定义嵌套在类的作用域之内</p>\n<p>在上例中，isbn 中用到的名字 bookNo 是定义在 Sales_data 内的数据成员，并且，即使 bookNo 定义在 isbn 之后，isbn 也还是能够使用 bookNo</p>\n<p>这是因为，编译器分两步处理类：首先编译成员的声明，然后才编译成员函数体（如果有的话）</p>\n<p>因此，<strong>成员函数体可以随意使用类中的其他成员，无须在意这些成员出现的次序</strong></p>\n<h4 id=\"在类的外部定义\"><a class=\"anchor\" href=\"#在类的外部定义\">#</a> 在类的外部定义</h4>\n<p>当我们在类的外部定义成员函数时，成员函数的定义必须与它的声明匹配</p>\n<ul>\n<li>返回类型、参数列表和函数名都得与类内部的声明保持一致</li>\n<li>如果成员被声明成常量成员函数，那么它的定义也必须在参数列表后明确指定  <code>const</code>  属性</li>\n</ul>\n<p>并且，类外部定义的成员名字必须包含它所属的类名</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">double</span> <span class=\"token class-name\">Sales_data</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">avg_price</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>units_sold<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span> revenue<span class=\"token operator\">/</span>units_sold<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">else</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>其中，函数名 Sales_data::avg_price 使用作用域运算符来说明 avg_price 函数被声明在类 Sales_data 的作用域内。因此，当 avg_price 使用 revenue 和 units_sold 时，它实际上是使用了 Sales_data 的成员</p>\n<h4 id=\"定义一个返回-this-对象的函数\"><a class=\"anchor\" href=\"#定义一个返回-this-对象的函数\">#</a> 定义一个返回 this 对象的函数</h4>\n<p>函数 combine 的设计初衷类似于复合赋值运算符 += 。调用该函数的对象代表的是赋值运算符左侧的运算对象，右侧运算对象则通过显式的实参被传入函数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Sales_data<span class=\"token operator\">&amp;</span> <span class=\"token class-name\">Sales_data</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">combine</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data <span class=\"token operator\">&amp;</span>rhs<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    units_sold <span class=\"token operator\">+=</span> rhs<span class=\"token punctuation\">.</span>units_sold<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 把 rhs 的成员加到 this 对象的成员上</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    revenue <span class=\"token operator\">+=</span> rhs<span class=\"token punctuation\">.</span>revenue<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token operator\">*</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>                 <span class=\"token comment\">// 返回调用该函数的对象</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>当我们的程序调用如下函数时，</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>total<span class=\"token punctuation\">.</span><span class=\"token function\">combine</span><span class=\"token punctuation\">(</span>trans<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>             <span class=\"token comment\">// 更新变量 total 的值</span></pre></td></tr></table></figure><p>total 的地址被绑定到隐式的 this 参数上，而 rhs 绑定到了 trans 上</p>\n<p>因此，当 combine 执行下面的语句时，</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>units_sold <span class=\"token operator\">+=</span> rhs<span class=\"token punctuation\">.</span>units_sold<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>等效于 total.units_sold += trans.unit_sold</p>\n<p>一般来说，当我们定义的函数类似于某个内置运算符时，应该令该函数的行为尽量模仿这个运算符</p>\n<ul>\n<li>内置的赋值运算符把它的左侧运算对象当成左值返回</li>\n<li>为了与它保持一致，combine 函数必须返回引用类型。因为此时的左侧运算对象是一个 Sales_data 的对象，所以返回类型应该是 Sales_data&amp;</li>\n</ul>\n<p>如前所述，我们无须使用隐式的  <code>this</code>  指针访问函数调用者的某个具体成员，但是，我们需要使用  <code>this</code>  来把调用函数的对象当成一个整体访问。因此，需要使用</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">return</span> <span class=\"token operator\">*</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回调用该函数的对象</span></pre></td></tr></table></figure><p>以获得执行该函数的对象，其中，解引用  <code>this</code>  指针就是得到了 total 的地址</p>\n<h3 id=\"定义类相关的非成员函数\"><a class=\"anchor\" href=\"#定义类相关的非成员函数\">#</a> 定义类相关的非成员函数</h3>\n<p><strong>作为接口组成部分的非成员函数，它们的定义和声明都在类的外部</strong>，例如 add、read 和 print 等</p>\n<blockquote>\n<p>一般来说，如果非成员函数是类接口的组成部分，则这些函数的声明应该与类在同一个头文件内。在这种方式下，用户使用接口的任何部分都只需要引入一个文件</p>\n</blockquote>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 定义 read 函数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>istream <span class=\"token operator\">&amp;</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>istream <span class=\"token operator\">&amp;</span>is<span class=\"token punctuation\">,</span> Sales_data <span class=\"token operator\">&amp;</span>item<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">double</span> price <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    is <span class=\"token operator\">>></span> item<span class=\"token punctuation\">.</span>bookNo <span class=\"token operator\">>></span> item<span class=\"token punctuation\">.</span>units_sold <span class=\"token operator\">>></span> price<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    item<span class=\"token punctuation\">.</span>revenue <span class=\"token operator\">=</span> price <span class=\"token operator\">*</span> item<span class=\"token punctuation\">.</span>units_sold<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">return</span> is<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\">// 定义 print 函数</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>ostream <span class=\"token operator\">&amp;</span><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>ostream <span class=\"token operator\">&amp;</span>os<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data <span class=\"token operator\">&amp;</span>item<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    os <span class=\"token operator\">&lt;&lt;</span> item<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span> <span class=\"token operator\">&lt;&lt;</span> item<span class=\"token punctuation\">.</span>units_sold <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>       <span class=\"token operator\">&lt;&lt;</span> item<span class=\"token punctuation\">.</span>revenue <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span> <span class=\"token operator\">&lt;&lt;</span> item<span class=\"token punctuation\">.</span><span class=\"token function\">avg_price</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">return</span> os<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token comment\">// 定义 add 函数</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>Sales_data <span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data <span class=\"token operator\">&amp;</span>lhs<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data <span class=\"token operator\">&amp;</span>rhs<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    Sales_data sum <span class=\"token operator\">=</span> lhs<span class=\"token punctuation\">;</span>  <span class=\"token comment\">// copy data members from lhs into sum</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    sum<span class=\"token punctuation\">.</span><span class=\"token function\">combine</span><span class=\"token punctuation\">(</span>rhs<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">// add data members from rhs into sum</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">return</span> sum<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>read 函数从给定流中将数据读到给定的对象里，print 函数则负责将给定对象的内容打印到给定的流中。其中，read 和 print 分别接受一个各自 IO 类型的引用作为其参数，这是因为 IO 类属于不能被拷贝的类型，因此我们只能通过引用来传递它们。而且，因为读取和写入的操作会改变流的内容，两个函数接受的都是普通引用，而非对常量的引用</p>\n<h2 id=\"构造函数\"><a class=\"anchor\" href=\"#构造函数\">#</a> 构造函数</h2>\n<p>每个类都分别定义了它的对象被初始化的方式</p>\n<p>类通过一个或几个特殊的成员函数来控制其对象的初始化过程，这些函数叫做 <strong>构造函数</strong>（constructor）</p>\n<ul>\n<li>\n<p><strong>构造函数的名字和类名相同</strong></p>\n</li>\n<li>\n<p>类似于其他函数，构造函数有一个参数列表（可能为空）和一个函数体（可能为空）</p>\n</li>\n<li>\n<p><strong>构造函数没有返回类型</strong></p>\n</li>\n</ul>\n<p>构造函数的任务是初始化类对象的数据成员。无论何时，只要类的对象被创建，就会执行构造函数</p>\n<p>类可以包含多个构造函数，但是，不同的构造函数之间必须在参数数量或参数类型上有所区别（类似于函数重载）</p>\n<p>不同于其他成员函数，构造函数不能被声明成  <code>const</code>  。当我们创建类的一个  <code>const</code>  对象时，直到构造函数完成初始化过程，对象才能真正取得其 “常量” 属性。因此，构造函数在构造  <code>const</code>  对象的过程中可以向其写值</p>\n<h3 id=\"合成的默认构造函数\"><a class=\"anchor\" href=\"#合成的默认构造函数\">#</a> 合成的默认构造函数</h3>\n<p>我们的 Sales_data 类并没有定义任何构造函数，但是之前使用了 Sales_data 对象的程序仍然可以正确编译和运行，因此可以说明，Sales_data 对象执行了默认初始化</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Sales_data total<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 没有为 total 提供初始值，执行默认初始化</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Sales_data trans<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 没有为 trans 提供初始值，执行默认初始化</span></pre></td></tr></table></figure><p>类通过一个特殊的构造函数来控制默认初始化过程，这个函数叫做 <strong>默认构造函数</strong>（default constructor）</p>\n<ul>\n<li>\n<p>默认构造函数无须任何实参</p>\n</li>\n<li>\n<p>如果我们的类没有显式地定义构造函数，编译器将会为我们隐式地定义一个默认构造函数</p>\n</li>\n</ul>\n<p>编译器自动生成的构造函数被称为<strong>合成的默认构造函数</strong>（synthesized default constructor）</p>\n<p>对于大多数类来说，合成的默认构造函数将按照如下规则初始化类的数据成员：</p>\n<ul>\n<li>如果存在类内的初始值，用类内初始值来初始化成员</li>\n<li>否则，默认初始化该成员</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">Sales_data</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string bookNo<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> units_sold <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">double</span> revenue <span class=\"token operator\">=</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>例如，对上面的类而言，因为 Sales_data 为 units_sold 和 revenue 提供了初始值，所以合成的默认构造函数将使用这些值来初始化对应的成员，而 bookNo 并未提供初始值，所以合成的默认构造函数把 bookNo 默认初始化成一个空字符串</p>\n<p>然而，合成的默认构造函数只适合非常简单的类，比如现在定义的这个 Sales_data 版本</p>\n<p>通常来说，<strong>一个类必须定义它自己的默认构造函数，而不能仅依赖于合成的默认构造函数</strong> 。这是因为：</p>\n<ul>\n<li>\n<p>只有当类没有声明任何构造函数时，编译器才会自动地生成默认构造函数。一旦我们定义了一些其他的构造函数，类将没有默认构造函数（除非我们自己定义一个默认构造函数）</p>\n</li>\n<li>\n<p>对于某些类来说，合成的默认构造函数可能执行错误的操作。如果类包含有内置类型或者复合类型的成员，则只有当这些成员全都被赋予了类内的初始值时，这个类才适合于使用合成的默认构造函数</p>\n</li>\n<li>\n<p>有的时候编译器不能为某些类合成默认的构造函数。例如，如果类中包含一个其他类类型的成员且这个成员的类型没有默认构造函数，那么编译器将无法初始化该成员。此外，还有其他一些情况也会导致编译器无法生成一个正确的默认构造函数，我们将在以后讨论</p>\n</li>\n</ul>\n<h3 id=\"定义构造函数\"><a class=\"anchor\" href=\"#定义构造函数\">#</a> 定义构造函数</h3>\n<p>对于我们的 Sales_data 类来说，我们可根据实际需要而定义不同的构造函数，例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">Sales_data</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 数据成员及成员函数</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string bookNo<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> units_sold <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">double</span> revenue <span class=\"token operator\">=</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> bookNo<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    Sales_data<span class=\"token operator\">&amp;</span> <span class=\"token function\">combine</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">double</span> <span class=\"token function\">avg_price</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token comment\">// 构造函数</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">default</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">,</span> <span class=\"token keyword\">unsigned</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">double</span> p<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>               <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">units_sold</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">revenue</span><span class=\"token punctuation\">(</span>p<span class=\"token operator\">*</span>n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h4 id=\"default\"><a class=\"anchor\" href=\"#default\">#</a> = default</h4>\n<p>在 C++ 11 标准中，如果我们需要默认的行为，可以通过在参数列表后面写上  <code>= default</code>  来要求编译器生成默认构造函数，其作用完全等同于之前使用的合成默认构造函数</p>\n<p>其中， <code>= default</code>  既可以与声明一起出现在类的内部，也可以作为定义出现在类的外部</p>\n<ul>\n<li>如果  <code>= default</code>  在类的内部，则默认构造函数是内联的</li>\n<li>如果它在类的外部，则该成员默认情况下不是内联的</li>\n</ul>\n<blockquote>\n<p>If the  <code>= default</code>  appears inside the class body, the default constructor will be inlined; if it appears on the definition outside the class, the member will not be inlined by default.</p>\n</blockquote>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">default</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>需注意， <code>= default</code>  生成的默认构造函数之所以对 Sales_data 类有效，是因为我们已经为内置类型的数据成员提供初始值。如果编译器不支持类内初始值，默认构造函数就应该使用构造函数初始值列表来初始化类的每个成员</p>\n<h4 id=\"构造函数初始值列表\"><a class=\"anchor\" href=\"#构造函数初始值列表\">#</a> 构造函数初始值列表</h4>\n<p>对于以下两个构造函数，其定义中出现了新的部分，即，冒号 以及 冒号与花括号之间的代码。我们把新出现的部分称为 <strong>构造函数初始值列表</strong>（constructor initialize list）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">,</span> <span class=\"token keyword\">unsigned</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">double</span> p<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>           <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">units_sold</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">revenue</span><span class=\"token punctuation\">(</span>p<span class=\"token operator\">*</span>n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>构造函数初始值列表负责为新创建对象的一个或几个数据成员赋初值</p>\n<p>构造函数初始值列表的组成：</p>\n<ul>\n<li>成员名字</li>\n<li>成员名字后面的、括号（或者花括号）括起来的成员初始值</li>\n<li>不同成员之间的逗号分隔符</li>\n</ul>\n<p>以  <code>Sales_data(const std::string &amp;s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) &#123; &#125;</code>  为例，该函数使用  <code>s</code>  和  <code>n</code>  来分别初始化成员 bookNo 和 units_sold ，并用  <code>p</code>  与  <code>n</code>  的乘积来初始化 revenue</p>\n<p><code>Sales_data(const std::string &amp;s): bookNo(s) &#123; &#125;</code>  ，其只使用  <code>s</code>  来显式初始化 bookNo 。对于 units_sold 和 revenue 这两个成员而言，将利用类内初始值进行隐式初始化（类似于合成默认构造函数的方式）。因此，该构造函数等价于</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>           <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">units_sold</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">revenue</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>当某个数据成员被构造函数初始值列表忽略时，它将以与合成默认构造函数相同的方式隐式初始化</p>\n</blockquote>\n<p>通常情况下，构造函数使用类内初始值不失为一种好的选择，因为只要这样的初始值存在我们就能确保为成员赋予了一个正确的值。不过，如果你的编译器不支持类内初始值，则所有构造函数都应该显式地初始化每个内置类型的成员</p>\n<p>另外，我们需要注意， <code>Sales_data(const std::string &amp;s): bookNo(s) &#123; &#125;</code>  中的  <code>&#123; &#125;</code>  实际是构造函数的函数体。因为我们定义这些构造函数的目的是为数据成员赋初值，其并不需要通过函数体实现，所以将函数体定义成空的</p>\n<h4 id=\"在类的外部定义构造函数\"><a class=\"anchor\" href=\"#在类的外部定义构造函数\">#</a> 在类的外部定义构造函数</h4>\n<p>与其他几个构造函数不同，以  <code>istream</code>  对象为参数的构造函数  <code>Sales_data(std::istream &amp;)</code>  需要执行一些实际的操作，在它的函数体内调用了 read 函数来给数据成员赋以初值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token class-name\">Sales_data</span><span class=\"token double-colon punctuation\">::</span><span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream <span class=\"token operator\">&amp;</span>is<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token function\">read</span><span class=\"token punctuation\">(</span>is<span class=\"token punctuation\">,</span> <span class=\"token operator\">*</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 从 is 中读取一条信息然后存入 this 对象中</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>和其他成员函数一样，<strong>当我们在类的外部定义构造函数时，必须指明该构造函数是哪个类的成员</strong></p>\n<p>因此， <code>Sales_data::Sales_data</code>  指出，我们定义了 Sales_data 类的成员 Sales_data 。因为该成员的名字和类名相同，所以它是一个构造函数（构造函数没有返回类型）</p>\n<p>由于  <code>Sales_data(std::istream &amp;)</code>  函数定义了函数体，在执行该构造函数时，对象的成员是可以被初始化的（尽管这个构造函数初始值列表是空的）</p>\n<h2 id=\"拷贝-赋值和析构\"><a class=\"anchor\" href=\"#拷贝-赋值和析构\">#</a> 拷贝、赋值和析构</h2>\n<p>除了定义类的对象如何初始化之外，类还需要控制拷贝、赋值和销毁对象时发生的行为</p>\n<p>如果我们不主动定义这些操作，编译器将替我们合成它们。一般来说，编译器生成的版本将对对象的每个成员执行拷贝、赋值和销毁操作</p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>total <span class=\"token operator\">=</span> trans<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>实际上等价于</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// Sales_data 的默认赋值操作等价于</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>total<span class=\"token punctuation\">.</span>bookNo <span class=\"token operator\">=</span> trans<span class=\"token punctuation\">.</span>bookNo<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>total<span class=\"token punctuation\">.</span>units_sold <span class=\"token operator\">=</span> trans<span class=\"token punctuation\">.</span>units_sold<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>total<span class=\"token punctuation\">.</span>revenue <span class=\"token operator\">=</span> trans<span class=\"token punctuation\">.</span>revenue<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>尽管编译器能替我们合成拷贝、赋值和销毁的操作，但是必须要清楚的一点是，对于某些类来说合成的版本无法正常工作。特别是，当类需要分配类对象之外的资源时，合成的版本常常会失效。例如，管理动态内存的类通常不能依赖于上述操作的合成版本</p>\n<ul>\n<li>很多需要动态内存的类能够并且应该使用 vector 对象或者 string 对象来管理必要的存储空间</li>\n<li>如果类包含 vector 或者 string 成员，则其拷贝、赋值和销毁的合成版本能够正常工作</li>\n</ul>\n<h1 id=\"访问控制与封装\"><a class=\"anchor\" href=\"#访问控制与封装\">#</a> 访问控制与封装</h1>\n<p>在 C++ 语言中，我们使用 <strong>访问说明符</strong>（access specifiers）加强类的封装性：</p>\n<ul>\n<li>\n<p>定义在 <strong> <code>public</code> </strong> 说明符之后的成员可以在整个程序内被访问。 <code>public</code>  成员定义类的接口</p>\n</li>\n<li>\n<p>定义在 <strong> <code>private</code> </strong> 说明符之后的成员可以被类的成员函数访问，但是不能被使用该类的代码访问。 <code>private</code>  封装（即，隐藏）类的实现细节</p>\n</li>\n</ul>\n<p>一个类可以包含 0 个或多个访问说明符，而且，某个访问说明符可以出现多次</p>\n<p>每个访问说明符指定了接下来的成员的访问级别，其有效范围直到出现下一个访问说明符或者到达类的结尾处为止</p>\n<p>再一次定义 Sales_data 类，其新形式如下所示：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Sales_data</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">public</span><span class=\"token operator\">:</span>            <span class=\"token comment\">// 添加了访问说明符</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">default</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">,</span> <span class=\"token keyword\">unsigned</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">double</span> p<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>               <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">units_sold</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">revenue</span><span class=\"token punctuation\">(</span>p<span class=\"token operator\">*</span>n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> bookNo<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    Sales_data <span class=\"token operator\">&amp;</span><span class=\"token function\">combine</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">private</span><span class=\"token operator\">:</span>            <span class=\"token comment\">// 添加了访问说明符</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">double</span> <span class=\"token function\">avg_price</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> units_sold <span class=\"token operator\">?</span> revenue<span class=\"token operator\">/</span>units_sold <span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string bookNo<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> units_sold <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">double</span> revenue <span class=\"token operator\">=</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>作为接口的一部分，构造函数和部分成员函数（即 isbn 和 combine ）紧跟在  <code>public</code>  说明符之后；而数据成员和作为实现部分的函数则跟在  <code>private</code>  说明符后面</p>\n<p>在上面的定义中我们还做了一个微妙的变化，我们使用了  <code>class</code>  关键字而非  <code>struct</code>  开始类的定义。这种变化仅仅是形式上有所不同，实际上我们可以使用这两个关键字中的任何一个定义类。唯一的一点区别是，<strong> <code>struct</code>  和  <code>class</code>  的默认访问权限不太一样</strong></p>\n<p><strong>类可以在它的第一个访问说明符之前定义成员，这种成员的访问权限依赖于类定义的方式</strong></p>\n<ul>\n<li>\n<p>如果我们使用  <code>struct</code>  关键字，则定义在第一个访问说明符之前的成员是  <code>public</code>  的</p>\n</li>\n<li>\n<p>如果我们使用  <code>class</code>  关键字，则这些成员是  <code>private</code>  的</p>\n</li>\n</ul>\n<p>出于统一编程风格的考虑，<strong>如果我们希望定义的类的所有成员是  <code>public</code>  的，使用  <code>struct</code>  ；反之，如果希望成员是  <code>private</code>  的，使用  <code>class</code> </strong></p>\n<h2 id=\"友元\"><a class=\"anchor\" href=\"#友元\">#</a> 友元</h2>\n<p>类可以将其他类或者函数声明成为它的 <strong>友元</strong>（friend），从而允许其他类或者函数访问它的非公有成员</p>\n<p><strong>如果类想把一个函数作为它的友元，需要增加一条以  <code>friend</code>  关键字开始的函数声明语句</strong></p>\n<p>例如，此前 <strong>定义抽象数据类型</strong> 时的 read、print 和 add 函数并不是类的成员，但却需要访问 Sales_data 类中  <code>private</code>  的数据成员，因此，我们需要将 read、print 和 add 函数作为 Sales_data 类的友元</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">class</span> <span class=\"token class-name\">Sales_data</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 为 Sales_data 的非成员函数所做的友元声明</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">friend</span> Sales_data <span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">friend</span> std<span class=\"token double-colon punctuation\">::</span>istream <span class=\"token operator\">&amp;</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">friend</span> std<span class=\"token double-colon punctuation\">::</span>ostream <span class=\"token operator\">&amp;</span><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>ostream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 其他成员及访问说明符与之前一致</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">public</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">default</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">,</span> <span class=\"token keyword\">unsigned</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">double</span> p<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">units_sold</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">revenue</span><span class=\"token punctuation\">(</span>p<span class=\"token operator\">*</span>n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token function\">bookNo</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token function\">Sales_data</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">const</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> bookNo<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    Sales_data <span class=\"token operator\">&amp;</span><span class=\"token function\">combine</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">private</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    std<span class=\"token double-colon punctuation\">::</span>string bookNo<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">unsigned</span> units_sold <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">double</span> revenue <span class=\"token operator\">=</span> <span class=\"token number\">0.0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token comment\">// Sales_data 接口的非成员组成部分的声明</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>Sales_data <span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>istream <span class=\"token operator\">&amp;</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>istream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>ostream <span class=\"token operator\">&amp;</span><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>ostream<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> Sales_data<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>友元声明只能出现在类定义的内部，但是在类内出现的具体位置不限。友元不是类的成员也不受它所在区域访问控制级别的约束</p>\n<blockquote>\n<p>一般来说，最好在类定义开始或结束前的位置集中声明友元</p>\n</blockquote>\n<h3 id=\"友元的声明\"><a class=\"anchor\" href=\"#友元的声明\">#</a> 友元的声明</h3>\n<p>友元的声明仅仅指定了访问的权限，而非一个通常意义上的函数声明</p>\n<p>如果我们希望类的用户能够调用某个友元函数，那么我们就必须在友元声明之外再专门对函数进行一次声明</p>\n<p>为了使友元对类的用户可见，我们通常把友元的声明与类本身放置在同一个头文件中（类的外部）</p>\n<p>因此，我们的 Sales_data 头文件应该为 read 、print 和 add 提供独立的声明（除了类内部的友元声明之外）</p>\n<blockquote>\n<p>许多编译器并未强制限定友元函数必须在使用之前在类的外部声明</p>\n</blockquote>\n<p>一些编译器允许在尚无友元函数的初始声明的情况下就调用它，不过最好还是提供一个独立的函数声明</p>\n<h2 id=\"封装\"><a class=\"anchor\" href=\"#封装\">#</a> 封装</h2>\n<p>封装有两个重要的优点：</p>\n<ul>\n<li>确保用户代码不会无意间破坏封装对象的状态</li>\n<li>被封装的类的具体实现细节可以随时改变，而无须调整用户级别的代码</li>\n</ul>\n<p>一旦把数据成员定义成  <code>private</code>  的，类的作者就可以比较自由地修改数据了</p>\n<ul>\n<li>当实现部分改变时，我们只需要检查类的代码本身以确认这次改变有什么影响。换句话说，只要类的接口不变，用户代码就无须改变</li>\n<li>如果数据是  <code>public</code>  的，所有使用了原来数据成员的代码都可能失效，这时我们必须定位并重写所有依赖于老版本实现的代码，之后才能重新使用该程序</li>\n</ul>\n<p>把数据成员的访问权限设成  <code>private</code>  还有另外一个好处：防止由于用户的原因造成数据被破坏。如果我们发现有程序缺陷破坏了对象的状态，则可以在有限的范围内定位缺陷</p>\n<blockquote>\n<p>尽管当类的定义发生改变时无须更改用户代码，但是使用了该类的源文件必须重新编译</p>\n</blockquote>\n<p>参考：C++ Primer 中文版（第 5 版）</p>\n",
            "tags": [
                "C++"
            ]
        },
        {
            "id": "https://jiankychen.github.io/shoka-opt.html",
            "url": "https://jiankychen.github.io/shoka-opt.html",
            "title": "shoka 主题的若干改动",
            "date_published": "2022-10-19T14:49:50.000Z",
            "content_html": "<p>相关文章推荐：</p>\n<ul>\n<li><a href=\"https://www.reversesacle.com/Supplement-for-shoka-theme/\">shoka 主题功能介绍补充点</a></li>\n<li><a href=\"https://www.lavenderdh.cn/categories/SHOKA/\">shoka 主题进阶玩法</a></li>\n</ul>\n<h1 id=\"修改主页标签名\"><a class=\"anchor\" href=\"#修改主页标签名\">#</a> 修改主页标签名</h1>\n<p>打开  <code>themes\\shoka\\languages</code>  路径下的  <code>zh-CN.yml</code>  文件，找到  <code>favicon</code>  板块，修改  <code>show</code>  和  <code>hide</code></p>\n<figure class=\"highlight yml\"><figcaption data-lang=\"YAML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token key atrule\">favicon</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token key atrule\">show</span><span class=\"token punctuation\">:</span> Jiankychen</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token key atrule\">hide</span><span class=\"token punctuation\">:</span> Jiankychen</pre></td></tr></table></figure><blockquote>\n<p>本博客根目录 _config.yml 中的语言设置为  <code>language: zh-CN</code>  ，所以这里是修改  <code>zh-CN.yml</code>  文件。若根目录 _config.yml 中的语言设置为  <code>language: en</code>  ，则应修改  <code>en.yml</code>  文件</p>\n</blockquote>\n<h1 id=\"修改加载动画\"><a class=\"anchor\" href=\"#修改加载动画\">#</a> 修改加载动画</h1>\n<p><strong>实现步骤：</strong></p>\n<ul>\n<li>\n<p>打开  <code>themes\\shoka\\source\\css\\_common\\components\\third-party</code>  路径下的  <code>loading.styl</code>  文件，将第 9 行（  <code>$bgColor = var(--grey-1)</code>  ）及以后的内容全部删除，新增以下内容：</p>\n<figure class=\"highlight stylus\"><figcaption data-lang=\"stylus\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>+<span class=\"token func\"><span class=\"token function\">mobile</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>+<span class=\"token func\"><span class=\"token function\">tablet</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">30</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span> <span class=\"token number\">30</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token selector\">.container <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span> <span class=\"token number\">100</span><span class=\"token unit\">vh</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">100</span><span class=\"token unit\">vw</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">font-family</span><span class=\"token punctuation\">:</span> Helvetica<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token selector\">.loader <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">250</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">bottom</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">left</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">right</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">margin</span><span class=\"token punctuation\">:</span> auto<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token selector\">.loader--dot <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-name</span><span class=\"token punctuation\">:</span> loader<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-timing-function</span><span class=\"token punctuation\">:</span> ease-<span class=\"token operator\">in</span>-out<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-duration</span><span class=\"token punctuation\">:</span> <span class=\"token number\">3</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-iteration-count</span><span class=\"token punctuation\">:</span> infinite<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">height</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span><span class=\"token unit\">px</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">border-radius</span><span class=\"token punctuation\">:</span> <span class=\"token number\">100</span><span class=\"token unit\">%</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token color\">black</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">border</span><span class=\"token punctuation\">:</span> <span class=\"token number\">2</span><span class=\"token unit\">px</span> solid <span class=\"token color\">white</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre></pre></td></tr><tr><td data-num=\"40\"></td><td><pre><span class=\"token selector\">.loader--dot:first-child <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token hexcode\">#8cc759</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-delay</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0.5</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre></pre></td></tr><tr><td data-num=\"45\"></td><td><pre><span class=\"token selector\">.loader--dot:nth-child(2) <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token hexcode\">#8c6daf</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-delay</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0.4</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre></pre></td></tr><tr><td data-num=\"50\"></td><td><pre><span class=\"token selector\">.loader--dot:nth-child(3) <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token hexcode\">#ef5d74</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-delay</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0.3</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre></pre></td></tr><tr><td data-num=\"55\"></td><td><pre><span class=\"token selector\">.loader--dot:nth-child(4) <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token hexcode\">#f9a74b</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"57\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-delay</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0.2</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"59\"></td><td><pre></pre></td></tr><tr><td data-num=\"60\"></td><td><pre><span class=\"token selector\">.loader--dot:nth-child(5) <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"61\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token hexcode\">#60beeb</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"62\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-delay</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0.1</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"63\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"64\"></td><td><pre></pre></td></tr><tr><td data-num=\"65\"></td><td><pre><span class=\"token selector\">.loader--dot:nth-child(6) <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"66\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token hexcode\">#fbef5a</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"67\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-delay</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"68\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"69\"></td><td><pre></pre></td></tr><tr><td data-num=\"70\"></td><td><pre><span class=\"token selector\">.loader--text <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"71\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">position</span><span class=\"token punctuation\">:</span> absolute<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"72\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token unit\">%</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"73\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">left</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"74\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">right</span><span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"75\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">4</span><span class=\"token unit\">rem</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"76\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">margin</span><span class=\"token punctuation\">:</span> auto<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"77\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"78\"></td><td><pre></pre></td></tr><tr><td data-num=\"79\"></td><td><pre><span class=\"token selector\">.loader--text:after <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"80\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Loading\"</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"81\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">font-weight</span><span class=\"token punctuation\">:</span> bold<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"82\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-name</span><span class=\"token punctuation\">:</span> loading-text<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"83\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-duration</span><span class=\"token punctuation\">:</span> <span class=\"token number\">2.5</span><span class=\"token unit\">s</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"84\"></td><td><pre>  <span class=\"token property-declaration\"><span class=\"token property\">animation-iteration-count</span><span class=\"token punctuation\">:</span> infinite<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"85\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"86\"></td><td><pre></pre></td></tr><tr><td data-num=\"87\"></td><td><pre></pre></td></tr><tr><td data-num=\"88\"></td><td><pre><span class=\"token atrule-declaration\"><span class=\"token atrule\">@keyframes</span> loader <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"89\"></td><td><pre>  <span class=\"token selector\">15% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"90\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token func\"><span class=\"token function\">translateX</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span></span></pre></td></tr><tr><td data-num=\"91\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"92\"></td><td><pre>  <span class=\"token selector\">45% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"93\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token func\"><span class=\"token function\">translateX</span><span class=\"token punctuation\">(</span><span class=\"token number\">230</span><span class=\"token unit\">px</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span></span></pre></td></tr><tr><td data-num=\"94\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"95\"></td><td><pre>  <span class=\"token selector\">65% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"96\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token func\"><span class=\"token function\">translateX</span><span class=\"token punctuation\">(</span><span class=\"token number\">230</span><span class=\"token unit\">px</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span></span></pre></td></tr><tr><td data-num=\"97\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"98\"></td><td><pre>  <span class=\"token selector\">95% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"99\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">transform</span><span class=\"token punctuation\">:</span> <span class=\"token func\"><span class=\"token function\">translateX</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span></span></pre></td></tr><tr><td data-num=\"100\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"101\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"102\"></td><td><pre></pre></td></tr><tr><td data-num=\"103\"></td><td><pre><span class=\"token atrule-declaration\"><span class=\"token atrule\">@keyframes</span> loading-text <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"104\"></td><td><pre>  <span class=\"token selector\">0% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"105\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Loading\"</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"106\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"107\"></td><td><pre>  <span class=\"token selector\">25% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"108\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Loading.\"</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"109\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"110\"></td><td><pre>  <span class=\"token selector\">50% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"111\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Loading..\"</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"112\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"113\"></td><td><pre>  <span class=\"token selector\">75% <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"114\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">content</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Loading...\"</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"115\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"116\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></li>\n<li>\n<p>打开  <code>themes\\shoka\\layout\\_partials</code>  路径下的  <code>layout.njk</code>  文件，将第 14 行（即   <code>&lt;div class=&quot;cat&quot;&gt;</code>  ）至第 29 行（即  <code>&lt;/div&gt;</code>  ）之间的内容（包括第 14 行和第 29 行）替换为</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>container<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--dot<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--dot<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--dot<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--dot<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--dot<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--dot<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">'</span>loader--text<span class=\"token punctuation\">'</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure></li>\n<li>\n<p>为适配移动端显示，需修改  <code>themes\\shoka\\source\\css\\_common\\outline</code>  路径下的  <code>outline.styl</code>  文件：将</p>\n<figure class=\"highlight stylus\"><figcaption data-lang=\"stylus\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token selector\">.cat <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token property-declaration\"><span class=\"token property\">margin-top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">10</span><span class=\"token unit\">rem</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>替换为</p>\n<figure class=\"highlight stylus\"><figcaption data-lang=\"stylus\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token selector\">.loader <span class=\"token punctuation\">&#123;</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>      <span class=\"token property-declaration\"><span class=\"token property\">margin-top</span><span class=\"token punctuation\">:</span> <span class=\"token number\">15</span><span class=\"token unit\">rem</span><span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>      <span class=\"token property-declaration\"><span class=\"token property\">justify-content</span><span class=\"token punctuation\">:</span> center<span class=\"token punctuation\">;</span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></li>\n</ul>\n<p>效果预览：</p>\n<p>\n<p class=\"codepen\" data-height=\"300\" data-default-tab=\"html,result\" data-slug-hash=\"rNvXjjd\" data-user=\"jiankychen\" style=\"height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\">\n  <span>See the Pen <a href=\"https://codepen.io/jiankychen/pen/rNvXjjd\">\n  Untitled</a> by Jiankychen (<a href=\"https://codepen.io/jiankychen\">@jiankychen</a>)\n  on <a href=\"https://codepen.io\">CodePen</a>.</span>\n</p>\n<script async src=\"https://cpwebassets.codepen.io/assets/embed/ei.js\"></script>\n</p>\n<p>加载动画列表：</p>\n<ul>\n<li><a href=\"https://codepen.io/search/pens?q=loader\">codepen</a></li>\n<li><a href=\"https://uiverse.io/loaders\">uiverse</a></li>\n</ul>\n<blockquote>\n<p>本加载动画源自于 <a href=\"https://codepen.io/AsLittleDesign/pen/ZbVVwa\">Dave McCarthy</a></p>\n</blockquote>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://www.reversesacle.com/Supplement-for-shoka-theme/\">替换加载动画</a></li>\n<li><a href=\"https://www.lavenderdh.cn/posts/608012233/\">修改加载动画</a></li>\n</ul>\n<h1 id=\"使用外链头像\"><a class=\"anchor\" href=\"#使用外链头像\">#</a> 使用外链头像</h1>\n<p>在采用 Jsdelivr 静态缓存的情况下，由于某种未知原因，博客侧边栏的头像经常无法显示，现考虑使用外部链接的图片作为头像</p>\n<p>实现步骤：</p>\n<ul>\n<li>\n<p>打开  <code>themes\\shoka\\layout\\_partials\\post</code>  路径下的  <code>post.njk</code>  文件，将</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span> <span class=\"token attr-name\">hidden</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemscope</span> <span class=\"token attr-name\">itemtype</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>http://schema.org/Person<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; url_for(theme.statics + theme.images + '/' + theme.sidebar.avatar) &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; author &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; subtitle &#125;&#125;, &#123;&#123; description &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>span</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure><p>替换为</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span> <span class=\"token attr-name\">hidden</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemscope</span> <span class=\"token attr-name\">itemtype</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>http://schema.org/Person<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  &#123;%- if 'http' in theme.sidebar.avatar %&#125;</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; url_for(theme.sidebar.avatar) &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  &#123;%- else %&#125;</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; url_for(theme.statics + theme.images + '/' + theme.sidebar.avatar) &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>  &#123;%- endif %&#125;</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; author &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; subtitle &#125;&#125;, &#123;&#123; description &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>span</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure></li>\n<li>\n<p>打开  <code>themes\\shoka\\layout\\_partials\\sidebar</code>  路径下的  <code>overview.njk</code>  文件，将</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemscope</span> <span class=\"token attr-name\">itemtype</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>http://schema.org/Person<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; author &#125;&#125;<span class=\"token punctuation\">\"</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>      <span class=\"token attr-name\">data-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; url_for(theme.statics + theme.images + '/'+ theme.sidebar.avatar) &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>&#123;&#123; author &#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>&#123;&#123; description &#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure><p>替换为</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemscope</span> <span class=\"token attr-name\">itemtype</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>http://schema.org/Person<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>image<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; author &#125;&#125;<span class=\"token punctuation\">\"</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token attr-name\">&#123;%-</span> <span class=\"token attr-name\">if</span> <span class=\"token attr-name\">'http'</span> <span class=\"token attr-name\">in</span> <span class=\"token attr-name\">theme.sidebar.avatar</span> <span class=\"token attr-name\">%&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>      <span class=\"token attr-name\">data-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; url_for(theme.sidebar.avatar) &#125;&#125;<span class=\"token punctuation\">\"</span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token attr-name\">&#123;%-</span> <span class=\"token attr-name\">else</span> <span class=\"token attr-name\">%&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>      <span class=\"token attr-name\">data-src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; url_for(theme.statics + theme.images + '/'+ theme.sidebar.avatar) &#125;&#125;<span class=\"token punctuation\">\"</span></span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token attr-name\">&#123;%-</span> <span class=\"token attr-name\">endif</span> <span class=\"token attr-name\">%&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>  <span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>&#123;&#123; author &#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>&#123;&#123; description &#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure></li>\n<li>\n<p>打开主题 _config.yml 文件，找到  <code>sidebar</code>  板块，将  <code>avatar</code>  值设为外部链接，例如</p>\n<figure class=\"highlight yml\"><figcaption data-lang=\"YAML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token key atrule\">avatar</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//s2.loli.net/2023/01/01/hnmYMxBAwF9QelU.jpg</pre></td></tr></table></figure></li>\n</ul>\n<h1 id=\"去除首页-subtitle-两侧的-号\"><a class=\"anchor\" href=\"#去除首页-subtitle-两侧的-号\">#</a> 去除首页 subtitle 两侧的 = 号</h1>\n<p>首页 subtitle 两侧会显示出一个 = 号，这里考虑将其去除</p>\n<p><strong>实现方式：</strong></p>\n<p>打开  <code>themes\\shoka\\layout\\_partials</code>  路径下的  <code>layout.njk</code>  文件，将第 42 行（  <code>&lt;p class=&quot;meta&quot; itemprop=&quot;description&quot;&gt;= &#123;&#123; subtitle &#125;&#125; =&lt;/p&gt;</code>  ）替换为</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>meta<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>&#123;&#123; subtitle &#125;&#125;<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure><p><strong>效果对比：</strong></p>\n<ul>\n<li>\n<p>去除前<br />\n<img loading=\"lazy\" data-src=\"T4-shoka%E4%B8%BB%E9%A2%98%E7%9A%84%E8%8B%A5%E5%B9%B2%E6%94%B9%E5%8A%A8/before.png\" alt=\"\" height=\"150px\" /></p>\n</li>\n<li>\n<p>去除后<br />\n<img loading=\"lazy\" data-src=\"T4-shoka%E4%B8%BB%E9%A2%98%E7%9A%84%E8%8B%A5%E5%B9%B2%E6%94%B9%E5%8A%A8/after.png\" alt=\"\" height=\"150px\" /></p>\n</li>\n</ul>\n<p>也可以将 = 号替换成其他字符或图标，例如：</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>meta<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">itemprop</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>description<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>~<span class=\"token strike\"><span class=\"token punctuation\">~~</span><span class=\"token content\"> &#123;&#123; subtitle &#125;&#125; </span><span class=\"token punctuation\">~~</span></span>~<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure><p><strong>效果：</strong></p>\n<p><img loading=\"lazy\" data-src=\"T4-shoka%E4%B8%BB%E9%A2%98%E7%9A%84%E8%8B%A5%E5%B9%B2%E6%94%B9%E5%8A%A8/replace.png\" alt=\"\" height=\"150px\" /></p>\n<h1 id=\"添加页脚站点运行时长\"><a class=\"anchor\" href=\"#添加页脚站点运行时长\">#</a> 添加页脚：站点运行时长</h1>\n<p><strong>实现步骤：</strong></p>\n<ul>\n<li>\n<p>打开  <code>themes\\shoka\\languages</code>  路径下的  <code>zh-CN.yml</code>  文件，找到  <code>footer</code>  板块，添加以下内容：</p>\n<figure class=\"highlight yml\"><figcaption data-lang=\"YAML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token key atrule\">timing</span><span class=\"token punctuation\">:</span> 本站已运行</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token key atrule\">days</span><span class=\"token punctuation\">:</span> 天</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token key atrule\">hours</span><span class=\"token punctuation\">:</span> 时</pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token key atrule\">minutes</span><span class=\"token punctuation\">:</span> 分</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token key atrule\">seconds</span><span class=\"token punctuation\">:</span> 秒</pre></td></tr></table></figure></li>\n<li>\n<p>打开  <code>themes\\shoka\\layout\\_partials</code>  路径下的  <code>footer.njk</code>  文件，在  <code>&lt;/div&gt;</code>  与  <code>&#123;%- if theme.footer.count %&#125;</code>  之间插入以下内容：</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>timing<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>RunTime<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>span</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span><span class=\"token punctuation\">></span></span><span class=\"token script\"><span class=\"token language-javascript\"></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">var</span> BootDate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"2021/10/24 23:00:00\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#123;</span># 站点起始时间 #<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">function</span> <span class=\"token function\">ShowRunTime</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">id</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>      <span class=\"token keyword\">var</span> NowDate <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>      <span class=\"token keyword\">var</span> RunDateM <span class=\"token operator\">=</span> <span class=\"token function\">parseInt</span><span class=\"token punctuation\">(</span>NowDate <span class=\"token operator\">-</span> BootDate<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>      <span class=\"token keyword\">var</span> RunDays <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>RunDateM<span class=\"token operator\">/</span><span class=\"token punctuation\">(</span><span class=\"token number\">24</span><span class=\"token operator\">*</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>      <span class=\"token keyword\">var</span> RunHours <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>RunDateM<span class=\"token operator\">%</span><span class=\"token punctuation\">(</span><span class=\"token number\">24</span><span class=\"token operator\">*</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token operator\">/</span><span class=\"token punctuation\">(</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>      <span class=\"token keyword\">var</span> RunMinutes <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>RunDateM<span class=\"token operator\">%</span><span class=\"token punctuation\">(</span><span class=\"token number\">24</span><span class=\"token operator\">*</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token operator\">%</span><span class=\"token punctuation\">(</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token operator\">/</span><span class=\"token punctuation\">(</span><span class=\"token number\">60</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>      <span class=\"token keyword\">var</span> RunSeconds <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">round</span><span class=\"token punctuation\">(</span>RunDateM<span class=\"token operator\">%</span><span class=\"token punctuation\">(</span><span class=\"token number\">24</span><span class=\"token operator\">*</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token operator\">%</span><span class=\"token punctuation\">(</span><span class=\"token number\">3600</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token operator\">%</span><span class=\"token punctuation\">(</span><span class=\"token number\">60</span><span class=\"token operator\">*</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token operator\">/</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>      <span class=\"token keyword\">var</span> RunTime <span class=\"token operator\">=</span> RunDays <span class=\"token operator\">+</span> <span class=\"token string\">\" &#123;&#123; __('footer.days') &#125;&#125; \"</span> <span class=\"token operator\">+</span> RunHours <span class=\"token operator\">+</span> <span class=\"token string\">\" &#123;&#123; __('footer.hours') &#125;&#125; \"</span> <span class=\"token operator\">+</span> RunMinutes <span class=\"token operator\">+</span> <span class=\"token string\">\" &#123;&#123; __('footer.minutes') &#125;&#125; \"</span> <span class=\"token operator\">+</span> RunSeconds <span class=\"token operator\">+</span> <span class=\"token string\">\" &#123;&#123; __('footer.seconds') &#125;&#125;\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>      document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>innerHTML <span class=\"token operator\">=</span> <span class=\"token string\">\"&#123;&#123; __('footer.timing') &#125;&#125; \"</span> <span class=\"token operator\">+</span> RunTime<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token function\">setInterval</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"ShowRunTime('RunTime')\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>  </span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr></table></figure></li>\n</ul>\n<p><strong>效果：</strong></p>\n<p><img loading=\"lazy\" data-src=\"T4-shoka%E4%B8%BB%E9%A2%98%E7%9A%84%E8%8B%A5%E5%B9%B2%E6%94%B9%E5%8A%A8/runtime.png\" alt=\"\" /></p>\n<h1 id=\"添加页脚站点访问量\"><a class=\"anchor\" href=\"#添加页脚站点访问量\">#</a> 添加页脚：站点访问量</h1>\n<p>可以通过 busuanzi 将 站点 / 某个页面的访客数量 添加到 页脚</p>\n<p><strong>实现步骤：</strong></p>\n<ul>\n<li>\n<p>打开  <code>themes\\shoka\\languages</code>  路径下的  <code>zh-CN.yml</code>  文件，找到  <code>footer</code>  板块，添加以下内容</p>\n<figure class=\"highlight yml\"><figcaption data-lang=\"YAML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token key atrule\">views</span><span class=\"token punctuation\">:</span> 次</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token key atrule\">visitors</span><span class=\"token punctuation\">:</span> 人</pre></td></tr></table></figure></li>\n<li>\n<p>打开  <code>themes\\shoka\\layout\\_partials</code>  路径下的  <code>footer.njk</code>  文件，将  <code>&#123;%- if theme.footer.count %&#125;</code>  至  <code>&#123;%- endif %&#125;</code>  之间的内容替换为</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>&#123;%- if theme.footer.count %&#125;</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">async</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://cdn.jsdelivr.net/gh/jiankychen/jiankychen.github.io@master/js/busuanzi.pure.min.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>count<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>span</span> <span class=\"token attr-name\">title</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>&#123;&#123; __('symbols_count_time.count_total') &#125;&#125;<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token code keyword\">      &lt;span class=\"post-meta-item-icon\"></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        &lt;i class=\"ic i-file\" aria-hidden=\"true\">&lt;/i></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>      &lt;/span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>      &lt;span class=\"text\">&#123;&#123; symbolsCountTotal(site) &#125;&#125; &#123;&#123;__('symbols_count_time.word')&#125;&#125;&lt;/span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    &lt;/span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    &lt;span class=\"post-meta-divider\">|&lt;/span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    &lt;span title=\"&#123;&#123; __('footer.total_visitors') &#125;&#125;\"></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>      &lt;span class=\"post-meta-item-icon\"></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        &lt;i class=\"ic i-person\" aria-hidden=\"true\">&lt;/i></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>      &lt;/span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>      &lt;span class=\"views\"></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>      &lt;span id=\"busuanzi_value_site_uv\">&lt;/span> &#123;&#123; __('footer.visitors') &#125;&#125;</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>      &lt;/span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    &lt;/span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    &lt;span class=\"post-meta-divider\">|&lt;/span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    &lt;span title=\"&#123;&#123; __('footer.total_views') &#125;&#125;\"></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>      &lt;span class=\"post-meta-item-icon\"></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        &lt;i class=\"ic i-eye\" aria-hidden=\"true\">&lt;/i></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>      &lt;/span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>      &lt;span class=\"visitors\"></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        &lt;span id=\"busuanzi_value_site_pv\">&lt;/span> &#123;&#123; __('footer.views') &#125;&#125;</pre></td></tr><tr><td data-num=\"26\"></td><td><pre>      &lt;/span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    &lt;/span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    &lt;span class=\"post-meta-divider\">|&lt;/span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    &lt;span title=\"&#123;&#123; __('symbols_count_time.time_total') &#125;&#125;\"></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>      &lt;span class=\"post-meta-item-icon\"></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        &lt;i class=\"ic i-clock\" aria-hidden=\"true\">&lt;/i></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>      &lt;/span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>      &lt;span class=\"text\">&#123;&#123; symbolsTimeTotal(site, config.symbols_count_time.awl, config.symbols_count_time.wpm, __('symbols_count_time.time_minutes')) &#125;&#125;&lt;/span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>    &lt;/span></span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>&#123;%- endif %&#125;</pre></td></tr></table></figure></li>\n</ul>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://www.reversesacle.com/Computer-science/Shoka-Theme/Another/\">添加网站浏览量统计功能</a></li>\n<li><a href=\"http://ibruce.info/2015/04/04/busuanzi/\">busuanzi 使用教程</a></li>\n</ul>\n<h1 id=\"新增页面访问统计与文章统计\"><a class=\"anchor\" href=\"#新增页面访问统计与文章统计\">#</a> 新增页面：访问统计与文章统计</h1>\n<h2 id=\"添加访问统计页面\"><a class=\"anchor\" href=\"#添加访问统计页面\">#</a> 添加访问统计页面</h2>\n<p>按照 <a href=\"https://www.lavenderdh.cn/\">Lavender</a> 的文章 <a href=\"https://www.lavenderdh.cn/posts/1409583388/\">Shoka 主题：新增博客访问统计页面</a> 做相应配置</p>\n<p>其中，百度商业账号和百度账号的调用方法存在差异，普通用户按照 <a href=\"https://tongji.baidu.com/api/manual/Chapter2/openapi.html\">百度账号接口说明</a> 进行操作，以获取 API Key、Secret Key、Refresh Token、Acess_Token、Site_ID 等信息</p>\n<p>一旦 Acess_Token 过期，可根据以下请求更换新的 Acess_Token 和 Refresh_Token ：</p>\n<pre><code>http://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&amp;refresh_token=&#123;REFRESH_TOKEN&#125;&amp;client_id=&#123;CLIENT_ID&#125;&amp;client_secret=&#123;CLIENT_SECRET&#125;\n</code></pre>\n<p>其中：</p>\n<ul>\n<li>\n<p>{REFRESH_TOKEN} 填写 Refresh Token</p>\n</li>\n<li>\n<p>{CLIENT_ID} 填写 API Key</p>\n</li>\n<li>\n<p>{CLIENT_SECRET} 填写 Secret Key</p>\n</li>\n</ul>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://www.lavenderdh.cn/posts/1409583388/\">Shoka 主题：新增博客访问统计页面</a></li>\n<li><a href=\"https://blog.eurkon.com/post/61763977.html\">Hexo 博客实时访问统计图</a></li>\n</ul>\n<h2 id=\"添加文章统计功能\"><a class=\"anchor\" href=\"#添加文章统计功能\">#</a> 添加文章统计功能</h2>\n<p>具体可参考 <a href=\"https://www.lavenderdh.cn/posts/3265173701/\">Shoka 主题：新增文章统计页面</a>、<a href=\"https://blog.eurkon.com/post/1213ef82.html\">Hexo 博客文章统计图</a></p>\n<h1 id=\"主题-vendors-链接替换-拆分-jsdelivr\"><a class=\"anchor\" href=\"#主题-vendors-链接替换-拆分-jsdelivr\">#</a> 主题 vendors 链接替换 - 拆分 Jsdelivr</h1>\n<p>参考：<a href=\"https://www.reversesacle.com/Supplement-for-shoka-theme/\">Hexo-Shoka 主题功能介绍补充点：主题插件链接替换思路与案例</a></p>\n<blockquote>\n<p>另一种方案：<a href=\"https://www.kaitaku.xyz/webbuild/shokajsdelivr/\">shoka 主题速度优化 - 拆分 jsdelivr</a></p>\n</blockquote>\n<h2 id=\"修改主题配置文件\"><a class=\"anchor\" href=\"#修改主题配置文件\">#</a> 修改主题配置文件</h2>\n<p>打开主题配置文件  <code>_config.shoka.yml</code>  ，找到文件最后的  <code>vendors</code>  板块，将其注释，并在其下方新增以下内容</p>\n<figure class=\"highlight yml\"><figcaption data-lang=\"YAML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token key atrule\">vendors</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token key atrule\">css</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token key atrule\">katex</span><span class=\"token punctuation\">:</span> unpkg.com/katex@0.12.0/dist/katex.min.css</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token key atrule\">comment</span><span class=\"token punctuation\">:</span> css/comment.css</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token key atrule\">fancybox</span><span class=\"token punctuation\">:</span> unpkg.com/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token key atrule\">justifiedGallery</span><span class=\"token punctuation\">:</span> unpkg.com/justifiedGallery@3.8.1/dist/css/justifiedGallery.min.css</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>  <span class=\"token key atrule\">js</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token key atrule\">pace</span><span class=\"token punctuation\">:</span> unpkg.com/pace<span class=\"token punctuation\">-</span>js@1.0.2/pace.min.js</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token key atrule\">pjax</span><span class=\"token punctuation\">:</span> unpkg.com/pjax@0.2.8/pjax.min.js</pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token key atrule\">fetch</span><span class=\"token punctuation\">:</span> unpkg.com/whatwg<span class=\"token punctuation\">-</span>fetch@3.4.0/dist/fetch.umd.js</pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token key atrule\">anime</span><span class=\"token punctuation\">:</span> unpkg.com/animejs@3.2.0/lib/anime.min.js</pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token key atrule\">algolia</span><span class=\"token punctuation\">:</span> unpkg.com/algoliasearch@4/dist/algoliasearch<span class=\"token punctuation\">-</span>lite.umd.js</pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token key atrule\">instantsearch</span><span class=\"token punctuation\">:</span> unpkg.com/instantsearch.js@4/dist/instantsearch.production.min.js</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token key atrule\">lazyload</span><span class=\"token punctuation\">:</span> unpkg.com/lozad@1/dist/lozad.min.js</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token key atrule\">quicklink</span><span class=\"token punctuation\">:</span> unpkg.com/quicklink@2/dist/quicklink.umd.js</pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token key atrule\">jquery</span><span class=\"token punctuation\">:</span> unpkg.com/jquery@3.5.1/dist/jquery.min.js</pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token key atrule\">fancybox</span><span class=\"token punctuation\">:</span> unpkg.com/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js</pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token key atrule\">justifiedGallery</span><span class=\"token punctuation\">:</span> unpkg.com/justifiedGallery@3.8.1/dist/js/jquery.justifiedGallery.min.js</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token key atrule\">valine</span><span class=\"token punctuation\">:</span> js/MiniValine.min.js</pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token key atrule\">copy_tex</span><span class=\"token punctuation\">:</span> unpkg.com/katex@0.12.0/dist/contrib/copy<span class=\"token punctuation\">-</span>tex.min.js</pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token key atrule\">chart</span><span class=\"token punctuation\">:</span> unpkg.com/frappe<span class=\"token punctuation\">-</span>charts@1.5.0/dist/frappe<span class=\"token punctuation\">-</span>charts.min.iife.js</pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token key atrule\">echarts</span><span class=\"token punctuation\">:</span> unpkg.com/echarts@5.2.2/dist/echarts.min.js</pre></td></tr></table></figure><p>与原始版本相比，有以下改动：</p>\n<ul>\n<li>除了  <code>comment</code>  和  <code>valine</code>  依然使用本地文件外，其余  <code>vendors</code>  元素的链接前缀均修改为 <a href=\"http://unpkg.com\">unpkg.com</a></li>\n<li><code>fancybox</code>  元素被拆分成  <code>fancybox</code>  和  <code>justifiedGallery</code></li>\n<li>新增个人所需的  <code>echarts</code>  （用于实现博客统计页面中的图表）</li>\n</ul>\n<h2 id=\"修改-utilsjs\"><a class=\"anchor\" href=\"#修改-utilsjs\">#</a> 修改 utils.js</h2>\n<p>打开  <code>themes\\shoka\\source\\js\\_app\\utils.js</code>  ，找到  <code>const assetUrl = function (asset, type) &#123;&#125;</code> （文件第 25~39 行左右），将其替换为</p>\n<figure class=\"highlight js\"><figcaption data-lang=\"JavaScript\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">assetUrl</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">asset<span class=\"token punctuation\">,</span> type</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token keyword\">var</span> str <span class=\"token operator\">=</span> <span class=\"token constant\">CONFIG</span><span class=\"token punctuation\">[</span>asset<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>type<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span><span class=\"token string\">'unpkg.com'</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>      <span class=\"token keyword\">return</span> <span class=\"token string\">\"https://\"</span> <span class=\"token operator\">+</span> str<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">.</span><span class=\"token function\">indexOf</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http'</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>      <span class=\"token keyword\">return</span> str<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">return</span> statics <span class=\"token operator\">+</span> str<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"修改-assetjs\"><a class=\"anchor\" href=\"#修改-assetjs\">#</a> 修改 asset.js</h2>\n<p>打开  <code>themes\\shoka\\scripts\\helpers\\asset.js</code>  ，找到  <code>hexo.extend.helper.register('_vendor_js', () =&gt; &#123;&#125;)</code>  （第 41~63 行左右），将其替换为</p>\n<figure class=\"highlight js\"><figcaption data-lang=\"JavaScript\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>hexo<span class=\"token punctuation\">.</span>extend<span class=\"token punctuation\">.</span>helper<span class=\"token punctuation\">.</span><span class=\"token function\">register</span><span class=\"token punctuation\">(</span><span class=\"token string\">'_vendor_js'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token keyword\">const</span> config <span class=\"token operator\">=</span> hexo<span class=\"token punctuation\">.</span>theme<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>config<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">''</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  <span class=\"token comment\">//Get a font list from config</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>  <span class=\"token keyword\">let</span> vendorJs <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'pace'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'pjax'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'fetch'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'anime'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'algolia'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'instantsearch'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'lazyload'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'quicklink'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">item</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>config<span class=\"token punctuation\">[</span>item<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>      <span class=\"token keyword\">return</span> config<span class=\"token punctuation\">[</span>item<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token string\">''</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>  </pre></td></tr><tr><td data-num=\"12\"></td><td><pre>  <span class=\"token keyword\">return</span> vendorJs<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">url</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">&#123;</span> </pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>item <span class=\"token operator\">!==</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>      <span class=\"token keyword\">return</span> <span class=\"token function\">htmlTag</span><span class=\"token punctuation\">(</span><span class=\"token string\">'script'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token literal-property property\">src</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">https://</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">$&#123;</span>url<span class=\"token interpolation-punctuation punctuation\">&#125;</span></span><span class=\"token template-punctuation string\">`</span></span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span> <span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h2 id=\"修改-scriptjs\"><a class=\"anchor\" href=\"#修改-scriptjs\">#</a> 修改 script.js</h2>\n<p>打开  <code>themes\\shoka\\scripts\\generaters\\script.js</code>  ，找到 js 和 css 索引代码（第 23~38 行左右），将其替换为</p>\n<figure class=\"highlight js\"><figcaption data-lang=\"JavaScript\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token literal-property property\">js</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token literal-property property\">valine</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>valine<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  <span class=\"token literal-property property\">chart</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>chart<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>  <span class=\"token literal-property property\">copy_tex</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>copy_tex<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>  <span class=\"token literal-property property\">jquery</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>jquery<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>  <span class=\"token literal-property property\">fancybox</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>fancybox<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>  <span class=\"token literal-property property\">justifiedGallery</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>justifiedGallery<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>  <span class=\"token literal-property property\">echarts</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>js<span class=\"token punctuation\">.</span>echarts</pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token literal-property property\">css</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>  <span class=\"token literal-property property\">valine</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>css <span class=\"token operator\">+</span> <span class=\"token string\">\"/comment.css\"</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>  <span class=\"token literal-property property\">katex</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>css<span class=\"token punctuation\">.</span>katex<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>  <span class=\"token literal-property property\">mermaid</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>css <span class=\"token operator\">+</span> <span class=\"token string\">\"/mermaid.css\"</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>  <span class=\"token literal-property property\">fancybox</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>css<span class=\"token punctuation\">.</span>fancybox<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>  <span class=\"token literal-property property\">justifiedGallery</span><span class=\"token operator\">:</span> theme<span class=\"token punctuation\">.</span>vendors<span class=\"token punctuation\">.</span>css<span class=\"token punctuation\">.</span>justifiedGallery</pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token comment\">// ...</span></pre></td></tr></table></figure><h2 id=\"修改-pagejs\"><a class=\"anchor\" href=\"#修改-pagejs\">#</a> 修改 page.js</h2>\n<p>打开  <code>themes\\shoka\\source\\js\\_app\\page.js</code>  ，找到  <code>const postFancybox = function(p) &#123;&#125;</code>  中的  <code>vendorCss</code>  和  <code>vendorJs</code>  （第 72~79 行左右），将其替换为</p>\n<figure class=\"highlight js\"><figcaption data-lang=\"JavaScript\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">postFancybox</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">p</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>  <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>p <span class=\"token operator\">+</span> <span class=\"token string\">' .md img'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token function\">vendorCss</span><span class=\"token punctuation\">(</span><span class=\"token string\">'justifiedGallery'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token function\">vendorJs</span><span class=\"token punctuation\">(</span><span class=\"token string\">'justifiedGallery'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token function\">vendorCss</span><span class=\"token punctuation\">(</span><span class=\"token string\">'fancybox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token function\">vendorJs</span><span class=\"token punctuation\">(</span><span class=\"token string\">'jquery'</span><span class=\"token punctuation\">,</span><span class=\"token string\">'fancybox'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>      <span class=\"token comment\">// ...</span></pre></td></tr></table></figure><h1 id=\"tab-标签卡的红色线条\"><a class=\"anchor\" href=\"#tab-标签卡的红色线条\">#</a> tab 标签卡的红色线条</h1>\n<p>tab 标签卡中的标签名称下方没有显示红色线条</p>\n<p>为显示下画线，可按以下步骤修改：</p>\n<ul>\n<li>\n<p>打开  <code>shoka\\source\\css\\_common\\components\\tags\\tabs.styl</code></p>\n</li>\n<li>\n<p>删掉第 6 行的  <code>overflow: hidden;</code></p>\n</li>\n</ul>\n<p>效果：</p>\n<div class=\"tab\" data-id=\"TabBlock\" data-title=\"标签卡 1\">\n<p>修改前：</p>\n<figure class=\"highlight css\"><figcaption data-lang=\"CSS\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token selector\">.nav</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> hidden<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> .0625rem solid <span class=\"token function\">var</span><span class=\"token punctuation\">(</span>--grey-1-a7<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 2.6875rem<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    // ...</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></div>\n<div class=\"tab\" data-id=\"TabBlock\" data-title=\"标签卡 2\">\n<p>修改后：</p>\n<figure class=\"highlight css\"><figcaption data-lang=\"CSS\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token selector\">.nav</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token property\">border-bottom</span><span class=\"token punctuation\">:</span> .0625rem solid <span class=\"token function\">var</span><span class=\"token punctuation\">(</span>--grey-1-a7<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 2.6875rem<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    // ...</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>  <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></div>\n<h1 id=\"调整代码块的高度\"><a class=\"anchor\" href=\"#调整代码块的高度\">#</a> 调整代码块的高度</h1>\n<p>修改代码块折叠的阈值为 10 （即，超过 10 行代码即进行折叠），并将代码块（不包括 figcaption）的高度调整为 200px</p>\n<ul>\n<li>\n<p>打开  <code>themes\\shoka\\source\\js\\_app\\page.js</code></p>\n</li>\n<li>\n<p>将  <code>code_container &amp;&amp; code_container.find(&quot;tr&quot;).length &gt; 15</code>  中的 15 替换为 10</p>\n</li>\n<li>\n<p>将  <code>code_container.style.maxHeight = &quot;300px&quot;;</code>  中的 &quot;300px&quot; 替换为 &quot;200px&quot;</p>\n</li>\n</ul>\n",
            "tags": [
                "Tutorial",
                "Hexo"
            ]
        },
        {
            "id": "https://jiankychen.github.io/Dijkstra.html",
            "url": "https://jiankychen.github.io/Dijkstra.html",
            "title": "Dijkstra",
            "date_published": "2022-10-14T03:28:41.000Z",
            "content_html": "<p>Dijkstra 算法是典型最短路算法，用于计算一个节点到其他所有节点的最短路径</p>\n<p>定义：</p>\n<ul>\n<li>代价：<strong>F(n) = g(n)</strong></li>\n<li>g (n) ：从起点到节点 n 的代价（距离）</li>\n<li>open list ：存放 当前可到达、且未确定最小代价路径的节点</li>\n<li>closed list ：存放 已经找到最小代价路径的节点</li>\n</ul>\n<p>流程：</p>\n<ul>\n<li>从起点开始逐步扩展，每一步为一个节点找到代价最小的路径，即：\n<ul>\n<li>从 open list 选择代价最小的节点，将其收录到 closed list</li>\n<li>遍历新收录节点的所有可访问邻节点，更新代价</li>\n</ul>\n</li>\n</ul>\n<p>最优性证明（为什么被收录的节点已经找到代价最小的路径？）：反证法</p>\n<p>特性：</p>\n<ul>\n<li>完备性：如果在起始点和目标点之间有路径解存在，就一定可以得到解；如果得不到解，就一定说明没有解存在</li>\n<li>最优性：对于某个评价指标（一般为路径的长度），规划得到的路径是最优的</li>\n</ul>\n<p>算法：</p>\n<pre><code>将起点放入 open list\n\n执行循环：\n\n- 如果 open list 为空：搜索失败，结束\n- 取 open list 中代价（即，g(n)）最小的节点（记作 Node1），将其放入 closed list\n- 如果节点 Node1 为终点：找到目标路径，结束\n- 遍历节点 Node1 的（不在 closed list 中的）邻接节点\n    - 记当前遍历的邻接节点为 Node2\n    - 如果节点 Node2 在 open list 中：更新节点 Node2 的代价\n    - 如果节点 Node2 在 open list 中：计算节点 Node2 的代价，并将其加入 open list\n\n待循环结束，即得到从起点到终点的代价最小路径\n</code></pre>\n<h1 id=\"朴素-dijkstra\"><a class=\"anchor\" href=\"#朴素-dijkstra\">#</a> 朴素 Dijkstra</h1>\n<h2 id=\"邻接矩阵法\"><a class=\"anchor\" href=\"#邻接矩阵法\">#</a> 邻接矩阵法</h2>\n<p>采用邻接矩阵 edges 存储边的有关信息，其中，edges [i][j] 表示 i 到 j 的代价，若 edges [i][j] == INT_MAX ，则表示不存在由节点 i 指向节点 j 的边</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/*</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>@param:</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    edges: 邻接矩阵</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    n: 节点数</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    start: 起始点</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>@return: </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    起始点到其他点的最小代价</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>*/</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dijkstra</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> edges<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> start<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dist</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> INT_MAX<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">//dist [i] 表示 start 到 i 的最小代价</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    dist<span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>                  <span class=\"token comment\">//start 到自身的代价为 0</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">closedlist</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">//closedlist [i] 表示 i 是否在 closed list 中</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>     <span class=\"token comment\">// 从起点开始逐步扩展，每一步为一个节点找到代价最小的路径</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">int</span> idx <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>                  <span class=\"token comment\">// 不在 closed list 中的、代价最小的节点</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>closedlist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> dist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;=</span> dist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>                idx <span class=\"token operator\">=</span> j<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        closedlist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>          <span class=\"token comment\">// 将代价最小的节点 idx 添加到 closed list</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 更新 idx 邻居节点的代价</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>closedlist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> edges<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;</span> INT_MAX<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>                dist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">min</span><span class=\"token punctuation\">(</span>dist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> dist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> edges<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token keyword\">return</span> dist<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"邻接表法\"><a class=\"anchor\" href=\"#邻接表法\">#</a> 邻接表法</h2>\n<p>采用 <a href=\"https://jiankychen.github.io/posts/ee040603\">链式前向星</a>（用数组模拟实现的链表，也就是静态链表）作为邻接表</p>\n<p>结构体数组 edges 存储所有边：edges [i] 表示第 i 条边</p>\n<ul>\n<li>edges [i].to 表示第 i 条边的终点</li>\n<li>edges [i].next 表示与第 i 条边同起点的下一条边的编号</li>\n<li>edges [i].w 表示第 i 条边的权值</li>\n</ul>\n<p>数组 head 存储顶点的第一条边：head [i] 表示以 i 为起点的第一条边（编号最大的边）的编号</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/*</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>@param:</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    edges: 静态链表</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    head: 节点数组</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    n: 节点数</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    start: 起始点</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>@return: </pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    起始点到其他点的最小代价</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>*/</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dijkstra</span><span class=\"token punctuation\">(</span>Edge<span class=\"token operator\">&amp;</span> edges<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> head<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> start<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dist</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> INT_MAX<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    dist<span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">closedlist</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">int</span> idx <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>closedlist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">&amp;&amp;</span> dist<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;=</span> dist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>                idx <span class=\"token operator\">=</span> j<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        closedlist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> head<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">!=</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">=</span> edges<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>next<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 遍历链式前向星</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            dist<span class=\"token punctuation\">[</span>edges<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">min</span><span class=\"token punctuation\">(</span>dist<span class=\"token punctuation\">[</span>edges<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> dist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> edges<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>w<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token keyword\">return</span> dist<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"堆优化-dijkstra\"><a class=\"anchor\" href=\"#堆优化-dijkstra\">#</a> 堆优化 Dijkstra</h1>\n<p>可以使用堆（优先级队列）来查找 open list 中的代价最小的节点 idx</p>\n<p>定义一个小顶堆：由于  <code>pair&lt;typeA, typeB&gt;</code>  排序时会默认按照  <code>typeA</code>  排序，应将起点到节点的代价作为  <code>typeA</code>  、将节点的编号作为  <code>typeB</code>  ，以便每次可以从堆中取出代价最小的节点</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">typedef</span> pair<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token operator\">></span> pii<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 分别存储代价和节点编号</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>priority_queue<span class=\"token operator\">&lt;</span>pii<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span>pii<span class=\"token operator\">></span><span class=\"token punctuation\">,</span> greater<span class=\"token operator\">&lt;</span>pii<span class=\"token operator\">>></span> pq<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 小顶堆</span></pre></td></tr></table></figure><blockquote>\n<p><code>priority_queue</code>  位于  <code>&lt;queue&gt;</code>  头文件， <code>pair</code>  位于  <code>&lt;utility&gt;</code>  头文件</p>\n</blockquote>\n<h2 id=\"邻接矩阵法-2\"><a class=\"anchor\" href=\"#邻接矩阵法-2\">#</a> 邻接矩阵法</h2>\n<p>当探索到一个代价最小的节点 idx 时，会遍历 idx 的邻居节点 i ，如果 dist [idx] + edges [idx][i] &lt; dist [i] ，则需更新节点 i 的代价为 dist [idx] + edges [idx][i]</p>\n<p dist[idx]=\"\" +=\"\" edges[idx][i],=\"\" i=\"\">注意，即便堆中可能已经有 {xx, i} 存在，但由于无法对堆进行寻址访问，故而无法直接将堆中已有的 {xx, i} 更新为</p>\n<p>因此，我们采用的策略是：</p>\n<ul>\n<li>更新 dist [i] 为 dist [idx] + edges [idx][i]</li>\n<li>将 {dist [i], i} 添加到堆（此时，{dist [i], i} 与 {xx, i} 都存在于堆中，但由于 dist [i] &lt; xx ，{dist [i], i} 优先级高于 {xx, i}，因此该操作也等效于更新了堆中的 {xx, i} ）</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/*</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>@param:</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    edges: 邻接矩阵</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    n: 节点数</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    start: 起始点</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>@return: </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    起始点到其他点的最小代价</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>*/</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">Dijkstra</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> edges<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> start<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dist</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> INT_MAX<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">typedef</span> pair<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token operator\">></span> pii<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    priority_queue<span class=\"token operator\">&lt;</span>pii<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span>pii<span class=\"token operator\">></span><span class=\"token punctuation\">,</span> greater<span class=\"token operator\">&lt;</span>pii<span class=\"token operator\">>></span> pq<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    dist<span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    pq<span class=\"token punctuation\">.</span><span class=\"token function\">emplace</span><span class=\"token punctuation\">(</span><span class=\"token function\">make_pair</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> start<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>pq<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">int</span> idx <span class=\"token operator\">=</span> pq<span class=\"token punctuation\">.</span><span class=\"token function\">top</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>second<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        pq<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>edges<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;</span> INT_MAX<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>                <span class=\"token keyword\">int</span> cost <span class=\"token operator\">=</span> dist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> edges<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cost <span class=\"token operator\">&lt;</span> dist<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>                    dist<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> cost<span class=\"token punctuation\">;</span>                 <span class=\"token comment\">// 实时维护 dist 数组，记录当前搜索到的节点 i 的最小代价</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>                    pq<span class=\"token punctuation\">.</span><span class=\"token function\">emplace</span><span class=\"token punctuation\">(</span><span class=\"token function\">make_pair</span><span class=\"token punctuation\">(</span>cost<span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 可能已经有 &#123;val, i&#125; 在堆中了，但是 val 必然大于 cost</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token keyword\">return</span> dist<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"邻接表法-2\"><a class=\"anchor\" href=\"#邻接表法-2\">#</a> 邻接表法</h2>\n<p>堆优化也可以采用链式前向星结构</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">/*</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>@param:</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    edges: 静态链表</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    head: 节点数组</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    n: 节点数</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    start: 起始点</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>@return: </pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    起始点到其他点的最小代价</pre></td></tr><tr><td data-num=\"9\"></td><td><pre>*/</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dijkstra</span><span class=\"token punctuation\">(</span>Edge<span class=\"token operator\">&amp;</span> edges<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> head<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> start<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">dist</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> INT_MAX<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token keyword\">typedef</span> pair<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token operator\">></span> pii<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    priority_queue<span class=\"token operator\">&lt;</span>pii<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span>pii<span class=\"token operator\">></span><span class=\"token punctuation\">,</span> greater<span class=\"token operator\">&lt;</span>pii<span class=\"token operator\">>></span> pq<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    dist<span class=\"token punctuation\">[</span>start<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    pq<span class=\"token punctuation\">.</span><span class=\"token function\">emplace</span><span class=\"token punctuation\">(</span><span class=\"token function\">make_pair</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> start<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>pq<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token keyword\">int</span> idx <span class=\"token operator\">=</span> pq<span class=\"token punctuation\">.</span><span class=\"token function\">top</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>second<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        pq<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> head<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">!=</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">=</span> edges<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>next<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token keyword\">int</span> cost <span class=\"token operator\">=</span> dist<span class=\"token punctuation\">[</span>idx<span class=\"token punctuation\">]</span> <span class=\"token operator\">+</span> edges<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>w<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cost <span class=\"token operator\">&lt;</span> dist<span class=\"token punctuation\">[</span>edges<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>                dist<span class=\"token punctuation\">[</span>edges<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> cost<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>                pq<span class=\"token punctuation\">.</span><span class=\"token function\">emplace</span><span class=\"token punctuation\">(</span><span class=\"token function\">make_pair</span><span class=\"token punctuation\">(</span>cost<span class=\"token punctuation\">,</span> edges<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token keyword\">return</span> dist<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"复杂度分析\"><a class=\"anchor\" href=\"#复杂度分析\">#</a> 复杂度分析</h1>\n<p>设图中的节点数为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> ，边数为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span> ，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi><mo>≤</mo><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">n \\le m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span></p>\n<p>时间复杂度：</p>\n<ul>\n<li>朴素 Dijkstra 算法：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n<li>堆优化的 Dijkstra 算法：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>m</mi><mo stretchy=\"false\">)</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O((n + m) \\log{n})</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">((</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span></span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n<p>空间复杂度：</p>\n<ul>\n<li>邻接矩阵法：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n^2)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0641em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\"><span class=\"mord mathnormal\">n</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span><span class=\"mclose\">)</span></span></span></span></li>\n<li>邻接表法：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n<p>堆优化的时间复杂度优于朴素算法</p>\n<p>邻接表法的空间复杂度优于邻接矩阵法</p>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/129373740\">最短路径问题 — Dijkstra 算法最详解</a></li>\n<li><a href=\"https://zhuanlan.zhihu.com/p/454373256\">Dijkstra 算法（附案例详解）</a></li>\n<li><a href=\"https://blog.csdn.net/u011956367/article/details/121222139\">Dijkstra 算法的 C++ 实现</a></li>\n<li><a href=\"https://blog.csdn.net/michealoven/article/details/114040136\">Dijkstra 算法时间复杂度分析</a></li>\n</ul>\n",
            "tags": [
                "Data Structure",
                "图"
            ]
        },
        {
            "id": "https://jiankychen.github.io/cpp-functions.html",
            "url": "https://jiankychen.github.io/cpp-functions.html",
            "title": "C++ 函数",
            "date_published": "2022-09-20T08:40:31.000Z",
            "content_html": "<h1 id=\"函数基础\"><a class=\"anchor\" href=\"#函数基础\">#</a> 函数基础</h1>\n<p>典型的函数（function）定义包括以下部分：</p>\n<ul>\n<li>返回类型（return type）</li>\n<li>函数名字</li>\n<li>由 0 个或多个形参（parameter）组成的列表，其中，形参以逗号隔开，形参的列表位于一对圆括号之内</li>\n<li>函数体</li>\n</ul>\n<p>例如：定义一个函数用于求数 n 的阶乘，其中，返回类型为 int 型，函数名字为 fact，形参为 int n，函数体为一对花括号 {} 内的语句</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">fact</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> ret <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>n <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        ret <span class=\"token operator\">*=</span> n<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">return</span> ret<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"调用函数\"><a class=\"anchor\" href=\"#调用函数\">#</a> 调用函数</h2>\n<p>通过 <strong>调用运算符</strong>（call operator）来执行函数</p>\n<ul>\n<li>调用运算符的形式是一对圆括号，它作用于一个表达式，该表达式是函数或者指向函数的指针；圆括号之内是一个用逗号隔开的实参（argument）列表，我们用实参初始化函数的形参</li>\n<li>调用表达式的类型就是函数的返回类型</li>\n</ul>\n<p>函数的调用完成两项工作：</p>\n<ul>\n<li>（隐式地）定义并用实参初始化函数对应的形参</li>\n<li>将控制权转移给被调用函数</li>\n</ul>\n<p>此时，主调函数（calling function）的执行被暂时中断，被调函数（called function）开始执行</p>\n<p>当遇到一条 return 语句时，函数结束执行过程</p>\n<p>return 语句也完成两项工作：</p>\n<ul>\n<li>返回 return 语句中的值（如果有的话）</li>\n<li>将控制权从被调函数转移回主调函数</li>\n</ul>\n<h2 id=\"形参和实参\"><a class=\"anchor\" href=\"#形参和实参\">#</a> 形参和实参</h2>\n<p>实参是形参的初始值。第一个实参初始化第一个形参，第二个实参初始化第二个形参，以此类推</p>\n<blockquote>\n<p>尽管实参与形参存在对应关系，但是并没有规定实参的求值顺序。编译器能以任意可行的顺序对实参求值</p>\n</blockquote>\n<p>实参数量应与形参数量一致，并且，实参的类型必须与对应的形参类型匹配</p>\n<h2 id=\"函数的形参列表\"><a class=\"anchor\" href=\"#函数的形参列表\">#</a> 函数的形参列表</h2>\n<p>函数的形参列表可以为空，但是不能省略</p>\n<ul>\n<li>要想定义一个不带形参的函数，最常用的办法是书写一个空的形参列表</li>\n<li>为了与 C 语言兼容，也可以使用关键字 void 表示函数没有形参</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* ... */</span> <span class=\"token punctuation\">&#125;</span>     <span class=\"token comment\">// 隐式地定义空形参列表</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* ... */</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 显式地定义空形参列表</span></pre></td></tr></table></figure><p>形参列表中的形参通常用逗号隔开，其中，每个形参都是含有一个声明符的声明（即使两个形参的类型一样，也必须把两个类型都写出来）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">f3</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> v1<span class=\"token punctuation\">,</span> v2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* ... */</span> <span class=\"token punctuation\">&#125;</span>     <span class=\"token comment\">// 错误</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">f4</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> v1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> v2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* ... */</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 正确</span></pre></td></tr></table></figure><p>任意两个形参都不能同名，而且，函数最外层作用域中的局部变量也与函数形参同名</p>\n<p>形参名是可选的。如果函数不会使用到个别形参，通常不命名该形参，以表示其不会在函数体内被使用</p>\n<blockquote>\n<p>注意：即使某个形参不被函数使用，也必须为它提供一个实参</p>\n</blockquote>\n<h2 id=\"函数返回类型\"><a class=\"anchor\" href=\"#函数返回类型\">#</a> 函数返回类型</h2>\n<blockquote>\n<p>大多数类型都能用作函数的返回类型</p>\n</blockquote>\n<p>一种特殊的返回类型是 void ，它表示函数不返回任何值</p>\n<p>函数的返回类型不能是数组类型或函数类型，但可以是指向数组或函数的指针</p>\n<h2 id=\"局部对象\"><a class=\"anchor\" href=\"#局部对象\">#</a> 局部对象</h2>\n<p>在 C++ 语言中，名字有作用域，对象有生命周期（lifetime）</p>\n<ul>\n<li>名字的作用域：程序文本的一部分，名字在其中可见</li>\n<li>对象的生命周期：程序执行过程中该对象存在的一段时间</li>\n</ul>\n<p>形参和函数体内部定义的变量统称为局部变量（local variable）。它们对函数而言是 “局部” 的，仅在函数的作用域内可见</p>\n<blockquote>\n<p>Parameters and variables defined inside a function body are referred to as local variables. They are “local” to that function and hide declarations of the same name made in an outer scope.</p>\n</blockquote>\n<p>在所有函数体之外定义的对象存在于程序的整个执行过程中。此类对象在程序启动时被创建，直到程序结束才会销毁</p>\n<p>局部变量的生命周期依赖于定义的方式。对于普通局部变量对应的对象，当函数的控制路径经过变量定义语句时创建该对象，当到达定义所在的块末尾时销毁它</p>\n<h2 id=\"自动对象\"><a class=\"anchor\" href=\"#自动对象\">#</a> 自动对象</h2>\n<p>只存在于块执行期间的对象被称为 <strong>自动对象</strong>（automatic object）</p>\n<p>当块的执行结束后，块中创建的自动对象的值就变成未定义的了</p>\n<p>形参就是一种自动对象：函数开始时为形参申请存储空间，因为形参定义在函数体作用域之内，所以一旦函数终止，形参也就被销毁</p>\n<p>自动对象的初始化：</p>\n<ul>\n<li>形参对应的自动对象：用传递给函数的实参初始化形参对应的自动对象</li>\n<li>局部变量对应的自动对象：\n<ul>\n<li>如果变量定义本身含有初始值，就用这个初始值进行初始化</li>\n<li>否则，如果变量定义本身不含初始值，执行默认初始化</li>\n</ul>\n</li>\n</ul>\n<blockquote>\n<p>内置类型的未初始化局部变量将产生未定义的值</p>\n</blockquote>\n<h2 id=\"局部静态对象\"><a class=\"anchor\" href=\"#局部静态对象\">#</a> 局部静态对象</h2>\n<p>某些时候，有必要令局部变量的生命周期贯穿函数调用及之后的时间。此时，可以将局部变量定义成 <strong>static 类型</strong></p>\n<p><strong>局部静态对象</strong>（local static object）在程序第一次经过对象定义语句时进行初始化，并且直到程序终止才被销毁。在此期间，即使对象所在的函数结束执行，也不会对它有影响</p>\n<p>如果局部静态变量没有显式的初始值，它将执行值初始化，内置类型的局部静态变量初始化为 0</p>\n<h2 id=\"函数声明\"><a class=\"anchor\" href=\"#函数声明\">#</a> 函数声明</h2>\n<p>类似于变量，函数只能定义一次，但可以声明多次</p>\n<blockquote>\n<p>唯一的例外是，如果一个函数永远也不会被我们用到，那么它可以只有声明没有定义</p>\n</blockquote>\n<p>函数的声明和函数的定义非常类似，唯一的区别是，函数声明无须函数体，用一个分号替代即可</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 函数声明</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token double-colon punctuation\">::</span>const_iterator beg<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>           vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token double-colon punctuation\">::</span>const_iterator end<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>函数的声明不包含函数体，所以也就无须形参的名字（事实上，在函数的声明中经常省略形参的名字）</p>\n<p>函数的三要素（返回类型、函数名、形参类型）描述了函数的接口，说明了调用该函数所需的全部信息</p>\n<p>函数声明也称作<strong>函数原型</strong>（function prototype）</p>\n<h3 id=\"在头文件中进行函数声明\"><a class=\"anchor\" href=\"#在头文件中进行函数声明\">#</a> 在头文件中进行函数声明</h3>\n<p>类似于变量，函数也应该在头文件中声明而在源文件中定义</p>\n<blockquote>\n<p>允许把函数的声明直接放在使用该函数的源文件中，但是这么做可能会很烦琐而且容易出错。相反，如果把函数声明放在头文件中，就能确保同一函数的所有声明保持一致。而且，一旦我们想改变函数的接口，只需改变一条声明即可</p>\n</blockquote>\n<p><strong>含有函数声明的头文件应该被包含到定义函数的源文件中</strong></p>\n<h3 id=\"分离式编译\"><a class=\"anchor\" href=\"#分离式编译\">#</a> 分离式编译</h3>\n<p>为了允许编写程序时按照逻辑关系将其划分开来，C++ 语言支持所谓的分离式编译（separate compilation）</p>\n<p>分离式编译允许我们把程序分割到几个文件中去，每个文件独立编译</p>\n<p>如果我们修改了其中一个源文件，那么只需重新编译那个改动了的文件</p>\n<p>大多数编译器提供了分离式编译每个文件的机制，这一过程通常会产生一个后缀名是 .obj（Windows）或 .o（UNIX）的文件（该文件包含对象代码（object code））</p>\n<h1 id=\"参数传递\"><a class=\"anchor\" href=\"#参数传递\">#</a> 参数传递</h1>\n<p>每次调用函数时都会重新创建它的形参，并用传入的实参对形参进行初始化</p>\n<ul>\n<li>\n<p>当形参是引用类型时，它将绑定到对应的实参上。此时，我们说它对应的实参被 <strong>引用传递</strong>（passed by reference）或者函数被 <strong>传引用调用</strong>（called by reference）</p>\n</li>\n<li>\n<p>当实参的值被拷贝给形参时，形参和实参是两个相互独立的对象。我们说这样的实参被 <strong>值传递</strong>（passed by value）或者函数被 <strong>传值调用</strong>（called by value）</p>\n</li>\n</ul>\n<h2 id=\"传值参数\"><a class=\"anchor\" href=\"#传值参数\">#</a> 传值参数</h2>\n<p>函数对形参做的所有操作都不会影响实参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">fact</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> ret <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        ret <span class=\"token operator\">*=</span> val<span class=\"token operator\">--</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">return</span> ret<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"指针形参\"><a class=\"anchor\" href=\"#指针形参\">#</a> 指针形参</h3>\n<p>可以将指针作为函数的形参</p>\n<ul>\n<li>调用函数时，会将指针实参拷贝给形参（形参和实参是两个相互独立的对象）</li>\n<li>由于形参和实参具有相同的值，可以通过形参间接地访问实参所指的对象，并且可以可以修改它所指对象的值</li>\n<li>改变形参并不会影响实参</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 该函数接受一个指针，然后将指针所指的值置 0</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>ip<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 指针形参</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token operator\">*</span>ip <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 改变指针 ip 所指对象的值</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    ip <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 只改变了 ip 的局部拷贝，实参并未被改变</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>熟悉 C 的程序员常常使用指针类型的形参访问函数外部的对象。在 C++ 语言中，建议使用引用类型的形参替代指针</p>\n</blockquote>\n<h2 id=\"传引用参数\"><a class=\"anchor\" href=\"#传引用参数\">#</a> 传引用参数</h2>\n<p>引用形参绑定到对应的实参上</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 该函数接受一个 int 对象的引用，然后将对象的值置为 0</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">&amp;</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">//i 是传给 reset 函数的对象的另一个名字</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 改变了 i 所引对象的值</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"使用引用避免拷贝\"><a class=\"anchor\" href=\"#使用引用避免拷贝\">#</a> 使用引用避免拷贝</h3>\n<p>拷贝大的类类型对象或者容器对象是比较低效的，此时可以通过引用传入参数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 比较两个 string 对象的长度</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">isShorter</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">return</span> s1<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> s2<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>甚至，有的类类型（包括 IO 类型在内）根本就不支持拷贝操作。此时，函数只能通过引用形参访问该类型的对象</p>\n<blockquote>\n<p>如果函数无须改变引用形参的值，最好将其声明为常量引用</p>\n</blockquote>\n<h3 id=\"使用引用形参返回额外信息\"><a class=\"anchor\" href=\"#使用引用形参返回额外信息\">#</a> 使用引用形参返回额外信息</h3>\n<p>一个函数只能返回一个值，然而有时函数需要同时返回多个值，因此可以考虑通过引用形参获取多个结果</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 返回 s 中 c 第一次出现的位置索引</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 引用形参 occurs 负责统计 c 出现的总次数</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>string<span class=\"token double-colon punctuation\">::</span>size_type <span class=\"token function\">find_char</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> c<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>                           string<span class=\"token double-colon punctuation\">::</span>size_type <span class=\"token operator\">&amp;</span>occurs<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">auto</span> ret <span class=\"token operator\">=</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 第一次出现的位置（如果有的话）</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    occurs <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>            <span class=\"token comment\">// 出现次数置 0</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">decltype</span><span class=\"token punctuation\">(</span>ret<span class=\"token punctuation\">)</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">!=</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> c<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ret <span class=\"token operator\">==</span> s<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>                ret <span class=\"token operator\">=</span> i<span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 记录 c 第一次出现的位置</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            <span class=\"token operator\">++</span>occurs<span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 更新出现次数</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>         <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">return</span> ret<span class=\"token punctuation\">;</span>            <span class=\"token comment\">//c 出现次数通过 occurs 隐式地返回</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"const-形参和实参\"><a class=\"anchor\" href=\"#const-形参和实参\">#</a> const 形参和实参</h2>\n<p>在用实参初始化形参时，会忽略掉形参的顶层 const</p>\n<p>换而言之，当形参具有顶层 const 时，传给它常量对象或者非常量对象都是可以的（可参考 <strong>const 限定符</strong>）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fcn</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">/* fcn 可以读取 i ，但不能向 i 写值 */</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>调用 fcn 函数时，既可以传入 const int ，也可以传入 int</p>\n<p>在 C++ 语言中，允许我们定义若干具有相同名字的函数，不过前提是不同函数的形参列表应该有明显的区别，例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">helper</span> <span class=\"token punctuation\">(</span>string <span class=\"token operator\">&amp;</span>s<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> start<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* 第一个 helper 函数 */</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">helper</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* 第二个 helper 函数 */</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>然而，由于形参的顶层 const 会被忽略，以下两个同名函数不能同时定义</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fcn</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* */</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fcn</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* */</span> <span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：重复定义了 fcn (int)</span></pre></td></tr></table></figure><p>因为顶层 const 被忽略掉了，所以在上面的代码中传入两个 fcn 函数的参数可以完全一样，因此第二个 fcn 是错误的</p>\n<h3 id=\"const-与-指针或引用形参\"><a class=\"anchor\" href=\"#const-与-指针或引用形参\">#</a> const 与 指针或引用形参</h3>\n<p>形参的初始化方式和变量的初始化方式是一样的：</p>\n<ul>\n<li>可以使用非常量来初始化一个底层 const 对象，但是反过来不行</li>\n<li>一个引用必须用同类型的对象初始化</li>\n</ul>\n<p>变量初始化：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">42</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>cp <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>i<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：但是不能通过 cp 改变 i</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">&amp;</span>r <span class=\"token operator\">=</span> i<span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 正确：但是不能通过 r 改变 i</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">&amp;</span>r2 <span class=\"token operator\">=</span> <span class=\"token number\">42</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>p <span class=\"token operator\">=</span> cp<span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 错误：p 的类型和 cp 的类型不匹配（存在通过 p 改变 cp 所指对象的风险）</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">&amp;</span>r3 <span class=\"token operator\">=</span> r<span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 错误：r3 的类型和 r 的类型不匹配（存在通过 r3 改变 r 所引对象的风险）</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">&amp;</span>r4 <span class=\"token operator\">=</span> <span class=\"token number\">42</span><span class=\"token punctuation\">;</span>       <span class=\"token comment\">// 错误：不能用字面值初始化一个非常量引用</span></pre></td></tr></table></figure><p>参数传递：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> ci <span class=\"token operator\">=</span> i<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>string<span class=\"token double-colon punctuation\">::</span>size_type ctr <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 调用形参类型是 int * 的 reset 函数</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>ci<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 错误：不能用指向 const int 对象的指针初始化 int * 形参</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 调用形参类型是 int &amp; 的 reset 函数</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span>ci<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 错误：不能将普通引用绑定到 const 对象 ci 上</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 错误：不能将葡萄引用绑定到字面值上</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">reset</span><span class=\"token punctuation\">(</span>ctr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 错误：类型不匹配，ctr 是无符号类型</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">find_char</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World!\"</span><span class=\"token punctuation\">,</span> <span class=\"token char\">'o'</span><span class=\"token punctuation\">,</span> ctr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：find_char 的第一个形参是对常量的引用</span></pre></td></tr></table></figure><p>要想调用引用版本的 reset ，只能使用 int 类型的对象，而不能使用字面值、求值结果为 int 的表达式、需要转换的对象或者 const int 类型的对象。类似的，要想调用指针版本的 reset，只能使用 int* 类型的对象</p>\n<p>我们能传递一个字符串字面值作为 find_char 的第一个实参，这是因为该函数的引用形参是常量引用，而 C++ 允许我们用字面值初始化常量引用</p>\n<h3 id=\"尽量使用常量引用\"><a class=\"anchor\" href=\"#尽量使用常量引用\">#</a> 尽量使用常量引用</h3>\n<p>将函数不会改变的形参定义成（普通的）引用是一种比较常见的错误，这么做会给函数的调用者造成误导，即，函数可以修改它的实参的值</p>\n<p>此外，使用引用而非常量引用也会极大地限制函数所能接受的实参类型。例如，我们不能把 const 对象、字面值或者需要类型转换的对象传递给普通的引用形参</p>\n<h2 id=\"数组形参\"><a class=\"anchor\" href=\"#数组形参\">#</a> 数组形参</h2>\n<p>数组 无法直接通过数组名进行拷贝，因此，无法以值传递的方式使用数组参数</p>\n<p>由于 数组（通常）会被转换成指针，当我们为一个函数传递一个数组时，实际上传递的是指向数组首元素的指针</p>\n<p>尽管不能以值传递的方式传递数组，但是我们可以把形参写成类似数组的形式：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 尽管表现形式不同，但这三个 print 函数是等价的</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 每个函数都有一个 const int* 类型的形参</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 函数的意图是作用于一个数组</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 这里的维度表示我们期望的数组维度，实际不一定是这个维度</span></pre></td></tr></table></figure><p>当编译器处理对 print 函数的调用时，只检查传入的参数是否是 const int* 类型</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> j<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：&amp;i 的类型是 int*</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 正确：j 转换成 int* 并指向 j [0]</span></pre></td></tr></table></figure><p>如果我们传给 print 函数的是一个数组，则实参自动地转换成指向数组首元素的指针。其中，数组的大小对函数的调用没有影响</p>\n<blockquote>\n<p>以数组作为形参的函数必须确保使用数组时不会越界</p>\n</blockquote>\n<h3 id=\"数组指针形参\"><a class=\"anchor\" href=\"#数组指针形参\">#</a> 数组指针形参</h3>\n<p>因为数组是以指针的形式传递给函数的，所以一开始函数并不知道数组的确切尺寸，调用者应该为此提供一些额外的信息</p>\n<p>管理指针形参有三种常用的技术：</p>\n<ul>\n<li>使用标记指定数组长度</li>\n<li>使用标准库规范</li>\n<li>显式传递一个表示数组大小的形参</li>\n</ul>\n<h4 id=\"使用标记指定数组长度\"><a class=\"anchor\" href=\"#使用标记指定数组长度\">#</a> 使用标记指定数组长度</h4>\n<ul>\n<li>要求数组本身包含一个结束标记</li>\n<li>这种方法适用于那些有明显结束标记且该标记不会与普通数据混淆的情况</li>\n<li>典型示例：C 风格字符串，C 风格字符串存储在字符数组中，并且在最后一个字符后面跟着一个空字符</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 遇到空字符停止</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>cp<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cp<span class=\"token punctuation\">)</span>          <span class=\"token comment\">// 若 cp 不是一个空指针</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>cp<span class=\"token punctuation\">)</span>  <span class=\"token comment\">// 只要指针所指的字符不是空字符</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>            cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token operator\">*</span>cp<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 输出当前字符并将指针向前移动一个位置</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h4 id=\"使用标准库规范\"><a class=\"anchor\" href=\"#使用标准库规范\">#</a> 使用标准库规范</h4>\n<p>传递指向数组首元素和尾后元素的指针</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>beg<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>end<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 传入两个指针：一个指向首元素，另一个指向尾元素的下一位置</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 输出 beg 到 end 之间（不含 end ）的所有元素</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>beg <span class=\"token operator\">!=</span> end<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token operator\">*</span>beg<span class=\"token operator\">++</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 输出当前元素并将指针向前移动一个位置</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">int</span> j<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">end</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//begin 和 end 函数，分别得到指向数组 j 的首元素和尾后元素的指针</span></pre></td></tr></table></figure><h4 id=\"显式传递一个表示数组大小的形参\"><a class=\"anchor\" href=\"#显式传递一个表示数组大小的形参\">#</a> 显式传递一个表示数组大小的形参</h4>\n<p>即，专门定义一个形参表示数组大小</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//const int ia [] 等价于 const int* ia</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">//size 表示数组的大小，将它显式地传给函数，用于控制对 ia 的访问</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> ia<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> size_t size<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>size_t i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">!=</span> size<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> ia<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">int</span> j<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 大小为 3 的整型数组</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">,</span> <span class=\"token function\">end</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token function\">begin</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>正如之前所说，当函数不需要对数组元素执行写操作的时候，数组形参应该是指向 const 的指针（即，常量指针）。只有当函数确实要改变元素值的时候，才把形参定义成指向非常量的指针</p>\n<h3 id=\"数组引用形参\"><a class=\"anchor\" href=\"#数组引用形参\">#</a> 数组引用形参</h3>\n<p>C++ 允许将变量定义成数组的引用（详见 <strong>数组</strong> ），同样地，也允许将形参定义成数组的引用，此时，引用形参绑定到对应的数组上</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 正确：形参是数组的引用，维度是类型的一部分</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> elem <span class=\"token operator\">:</span> arr<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> elem <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>注意， <code>&amp;arr</code>  两端的括号必不可少：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token operator\">&amp;</span>arr <span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>   <span class=\"token comment\">// 错误：将 arr 声明成了引用的数组</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>arr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 正确：arr 是具有 10 个整数的整型数组的引用</span></pre></td></tr></table></figure><p>数组大小是构成数组类型的一部分，只要不超过维度，就可以在函数体内放心地使用数组</p>\n<p>然而，这一用法也在无形中限制了 print 函数的可用性，即，只能将函数作用于大小为 10 的数组：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> j<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> k<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">8</span><span class=\"token punctuation\">,</span><span class=\"token number\">9</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&amp;</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 错误：实参不是含有 10 个整数的数组</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 错误：实参不是含有 10 个整数的数组</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>k<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 正确：实参是含有 10 个整数的数组</span></pre></td></tr></table></figure><h3 id=\"传递多维数组\"><a class=\"anchor\" href=\"#传递多维数组\">#</a> 传递多维数组</h3>\n<p>将多维数组传递给函数时，真正传递的是指向数组首元素的指针</p>\n<p>因为我们处理的是数组的数组，首元素本身就是一个数组，数组第二维（以及后面所有维度）的大小都是数组类型的一部分，不能省略</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//matrix 指向数组的首元素，该数组的元素是由 10 个整数构成的数组</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>matrix<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> rowSize<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* ... */</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">//matrix 是一个指向含有 10 个整数的数组的指针</span></pre></td></tr></table></figure><p>注意， <code>*matrix</code>  两端的括号必不可少</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>matrix<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 10 个指针构成的数组</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>matrix<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 指向含有 10 个整数的数组的指针</span></pre></td></tr></table></figure><p>我们也可以使用数组的语法定义函数（此时编译器会一如既往地忽略掉第一个维度，所以最好不要把它包括在形参列表内）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//matrix 看似是一个二维数组，实则是指向含有 10 个整数的数组的指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> matrix<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> rowSize<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">/* ... */</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"main-处理命令行选项\"><a class=\"anchor\" href=\"#main-处理命令行选项\">#</a> main: 处理命令行选项</h2>\n<p>到目前为止，我们定义的 main 函数都只有空形参列表：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>然而，有时我们确实需要给 main 传递实参。一种常见的情况是，用户通过设置一组选项来确定函数所要执行的操作。例如，假定 main 函数位于可执行文件 prog 之内，我们可以向程序传递下面的选项：</p>\n<pre><code>prog -d -o ofile data0\n</code></pre>\n<p>这些命令行选项通过两个（可选的）形参传递给 main 函数：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>argv<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>第二个形参 argv 是一个数组，它的元素是指向 C 风格字符串的指针；第一个形参 argc 表示数组中字符串的数量</p>\n<p>因为第二个形参是数组，所以 main 函数也可以定义成：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token operator\">*</span>argv<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">//argv 执指向 char*</span></pre></td></tr></table></figure><p>当实参传给 main 函数之后，argv 的第一个元素指向程序的名字或者一个空字符串，接下来的元素依次传递命令行提供的实参。最后一个指针之后的元素值保证为 0</p>\n<p>以上面提供的命令行  <code>prog -d -o ofile data0</code>  为例，argc 等于 5，argv 包含如下 C 风格字符串</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>argv<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"prog\"</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 或者 argv [0] 也可以指向一个空字符串</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>argv<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"-d\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>argv<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"-o\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>argv<span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"ofile\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>argv<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"data0\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>argv<span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><blockquote>\n<p>当使用  <code>argv</code>  中的实参时，一定要记得可选的实参从  <code>argv[1]</code>  开始； <code>argv[0]</code>  保存程序的名字，而非用户输入</p>\n</blockquote>\n<h2 id=\"含有可变形参的函数\"><a class=\"anchor\" href=\"#含有可变形参的函数\">#</a> 含有可变形参的函数</h2>\n<p>有时我们无法提前预知应该向函数传递几个实参。例如，我们想要编写代码输出程序产生的错误信息，此时最好用同一个函数实现该项功能，以便对所有错误的处理能够整齐划一。然而，错误信息的种类不同，所以调用错误输出函数时传递的实参也各不相同</p>\n<p>为了编写能处理不同数量实参的函数，C++ 11 新标准提供了两种主要的方法：</p>\n<ul>\n<li>如果所有的实参类型相同，可以传递一个名为  <code>initializer_list</code>  的标准库类型</li>\n<li>如果实参的类型不同，我们可以编写一种特殊的函数，也就是所谓的可变参数模板</li>\n</ul>\n<p>C++ 还有一种特殊的形参类型（即省略符），可以用它传递可变数量的实参（这种功能<strong>一般只用于与 C 函数交互的接口程序</strong>）</p>\n<h3 id=\"initializer_list-形参\"><a class=\"anchor\" href=\"#initializer_list-形参\">#</a> initializer_list 形参</h3>\n<p>如果函数的实参数量未知、但是全部实参的类型都相同，我们可以使用 initializer_list 类型的形参</p>\n<p>initializer_list 是一种标准库类型，用于表示某种特定类型的值的数组</p>\n<p>initializer_list 类型定义在同名的头文件中</p>\n<p><img loading=\"lazy\" data-src=\"Cpp6-%E5%87%BD%E6%95%B0/initializer_list.png\" alt=\"\" /></p>\n<p>和 vector 一样，initializer_list 也是一种模板类型。定义 initializer_list 对象时，必须说明列表中所含元素的类型</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>initializer_list<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> ls<span class=\"token punctuation\">;</span> <span class=\"token comment\">//initializer_list 的元素类型是 string</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>initializer_list<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> li<span class=\"token punctuation\">;</span>    <span class=\"token comment\">//initializer_list 的元素类型是 int</span></pre></td></tr></table></figure><p>和 vector 不一样的是，initializer_list 对象中的元素永远是常量值，我们无法改变 initializer_list 对象中元素的值</p>\n<p>我们使用如下的形式编写输出错误信息的函数，使其可以作用于可变数量的实参：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">error_msg</span><span class=\"token punctuation\">(</span>initializer_list<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> il<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> beg <span class=\"token operator\">=</span> il<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> beg <span class=\"token operator\">!=</span> il<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>beg<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token operator\">*</span>beg <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span> <span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>其中，作用于 initializer_list 对象的 begin 和 end 操作类似于 vector 对应的成员</p>\n<ul>\n<li>begin () 成员提供一个指向列表首元素的指针</li>\n<li>end () 成员提供一个指向列表尾后元素的指针</li>\n</ul>\n<p>initializer_list 包含 begin 和 end 成员，因此可以使用 <strong>范围 for</strong> 循环处理其中的元素</p>\n<p>如果想向 initializer_list 形参中传递一个值的序列，则必须把序列放在一对花括号内</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//expected 和 actual 是 string 对象</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>expected <span class=\"token operator\">!=</span> actual<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token function\">error_msg</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"functionX\"</span><span class=\"token punctuation\">,</span> expected<span class=\"token punctuation\">,</span> actual<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">else</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token function\">error_msg</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"functionX\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"okay\"</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>含有 initializer_list 形参的函数也可以同时拥有其他形参。例如，调试系统可能有个名为 ErrCode 的类，用来表示不同类型的错误，因此我们可以改写之前的程序，使其包含一个 initializer_list 形参和一个 ErrCode 形参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">error_msg</span><span class=\"token punctuation\">(</span>ErrCode e<span class=\"token punctuation\">,</span> initializer_list<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> il<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> e<span class=\"token punctuation\">.</span><span class=\"token function\">msg</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\": \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">auto</span> <span class=\"token operator\">&amp;</span>elem <span class=\"token operator\">:</span> il<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> elem <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span> <span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>为了调用这个版本的 error_msg 函数，需要额外传递一个 ErrCode 实参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>expected <span class=\"token operator\">!=</span> actual<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token function\">error_msg</span><span class=\"token punctuation\">(</span><span class=\"token function\">ErrCode</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"functionX\"</span><span class=\"token punctuation\">,</span> expected<span class=\"token punctuation\">,</span> actual<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">else</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token function\">error_msg</span><span class=\"token punctuation\">(</span><span class=\"token function\">ErrCode</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"functionX\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"okay\"</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"省略符形参\"><a class=\"anchor\" href=\"#省略符形参\">#</a> 省略符形参</h3>\n<p>省略符形参是为了便于 C++ 程序访问某些（使用了名为 varargs 的 C 标准库功能的）C 代码而设置的</p>\n<p>通常，省略符形参不应用于其他目的</p>\n<blockquote>\n<p>省略符形参应该仅仅用于 C 和 C++ 通用的类型<br />\n特别应该注意的是，大多数类类型的对象在传递给省略符形参时都无法正确拷贝</p>\n</blockquote>\n<p><strong>省略符形参只能出现在形参列表的最后一个位置</strong>，它的形式无外乎以下两种:</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">foo</span><span class=\"token punctuation\">(</span>parm_list<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">foo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>第一种形式指定了 foo 函数的部分形参的类型，对应于这些形参的实参将会执行正常的类型检查</p>\n<p>省略符形参所对应的实参无须类型检查</p>\n<p>在第一种形式中，形参声明后面的逗号是可选的</p>\n<h1 id=\"返回类型和-return-语句\"><a class=\"anchor\" href=\"#返回类型和-return-语句\">#</a> 返回类型和 return 语句</h1>\n<p>return 语句：终止当前正在执行的函数，并将控制权返回到调用该函数的地方</p>\n<p>return 语句的两种形式：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 无返回值</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">return</span> expression<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 有返回值</span></pre></td></tr></table></figure><h2 id=\"无返回值函数\"><a class=\"anchor\" href=\"#无返回值函数\">#</a> 无返回值函数</h2>\n<p>没有返回值的 return 语句只能用在返回类型是 void 的函数中</p>\n<p>返回 void 的函数并不一定要有 return 语句，因为这类函数最后会隐式地执行 return</p>\n<p>一个返回类型是 void 的函数也能使用 return 语句的第二种形式，不过此时 return 语句的 expression 必须是另一个返回 void 的函数</p>\n<p>强行令 void 函数返回其他类型的表达式将产生编译错误</p>\n<h2 id=\"有返回值函数\"><a class=\"anchor\" href=\"#有返回值函数\">#</a> 有返回值函数</h2>\n<p>只要函数的返回类型不是 void ，该函数内的每条 return 语句就必须返回一个值</p>\n<p>return 语句返回值的类型必须与函数的返回类型相同，或者能隐式地转换成函数的返回类型</p>\n<h3 id=\"值是如何被返回的\"><a class=\"anchor\" href=\"#值是如何被返回的\">#</a> 值是如何被返回的</h3>\n<p>返回一个值的方式：返回的值用于初始化调用点的一个临时量，该临时量就是函数调用的结果</p>\n<p>如果函数返回的类型是局部变量，则会返回该变量的副本</p>\n<p>例如，书写一个返回类型是 string 的函数 make_plural，由于该函数的返回类型是 string ，返回值将被拷贝到调用点。即，该函数将返回 word 的副本或者一个未命名的临时 string 对象</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string <span class=\"token function\">make_plural</span><span class=\"token punctuation\">(</span>size_t ctr<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>word<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string ending<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>ctr <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> word <span class=\"token operator\">+</span> ending <span class=\"token operator\">:</span> word<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>如果函数返回引用类型，则不需要拷贝其所引对象</p>\n<p>例如：书写一个函数，其中形参和返回类型都是 const string 的引用，不管是调用函数还是返回结果都不会真正拷贝 string 对象</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 挑出两个 string 对象中较短的那个，返回其引用</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">return</span> s1<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> s2<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> s1 <span class=\"token operator\">:</span> s2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"不要返回局部对象的引用或指针\"><a class=\"anchor\" href=\"#不要返回局部对象的引用或指针\">#</a> 不要返回局部对象的引用或指针</h3>\n<p>函数完成后，它所占用的存储空间也随之被释放掉，因此，不要返回局部对象的引用或指针</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token function\">manip</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 严重错误：函数试图返回局部对象的引用</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    string ret<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>   <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>ret<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>       <span class=\"token keyword\">return</span> ret<span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 错误：返回局部对象的引用！</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>   <span class=\"token keyword\">else</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>       <span class=\"token keyword\">return</span> <span class=\"token string\">\"Empty\"</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 错误：\"Empty\" 是一个局部临时量</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h3 id=\"返回类类型的函数和调用运算符\"><a class=\"anchor\" href=\"#返回类类型的函数和调用运算符\">#</a> 返回类类型的函数和调用运算符</h3>\n<p>和其他运算符一样，调用运算符也有优先级和结合律</p>\n<p><strong>调用运算符的优先级 与 点运算符和箭头运算符 相同，并且也符合左结合律</strong></p>\n<p>如果函数返回指针、引用或类的对象，我们就能使用函数调用的结果访问结果对象的成员</p>\n<p>例如，我们可以通过如下形式得到较短 string 对象的长度：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 调用 string 对象的 size 成员，该 string 对象是由 shorterString 函数返回的</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">auto</span> sz <span class=\"token operator\">=</span> <span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span>s1<span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"引用返回左值\"><a class=\"anchor\" href=\"#引用返回左值\">#</a> 引用返回左值</h3>\n<p>函数的返回类型决定函数调用是否是左值：调用一个返回引用的函数将会得到左值，其他返回类型将得到右值</p>\n<p>因此，可以像使用其他左值那样来使用返回引用的函数，特别是，可以给返回类型为非常量引用的函数的结果赋值</p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">char</span> <span class=\"token operator\">&amp;</span><span class=\"token function\">get_val</span><span class=\"token punctuation\">(</span>string <span class=\"token operator\">&amp;</span>str<span class=\"token punctuation\">,</span> string<span class=\"token double-colon punctuation\">::</span>size_type ix<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">return</span> str<span class=\"token punctuation\">[</span>ix<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//get_val 假定索引值是有效的</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    string <span class=\"token function\">s</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"a value\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> s <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 输出 a value</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token function\">get_val</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token char\">'A'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 将 s [0] 的值改为 'A'</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> s <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 输出 A value</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>如果返回类型是常量引用，则不能给调用的结果赋值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hi\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"bye\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"X\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：返回值是个常量</span></pre></td></tr></table></figure><h3 id=\"列表初始化返回值\"><a class=\"anchor\" href=\"#列表初始化返回值\">#</a> 列表初始化返回值</h3>\n<p>C++ 11 标准规定，函数可以返回花括号包围的值的列表，该列表用来初始化函数调用点处的临时量</p>\n<ul>\n<li>如果列表为空，临时量执行值初始化</li>\n<li>否则，返回的值由函数的返回类型决定</li>\n</ul>\n<p>例如：定义一个返回 vector 对象的函数，其中，vector 对象用来存放表示错误信息的 string 对象</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> <span class=\"token function\">process</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// . . .</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token comment\">//expected 和 actual 是 string 对象</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>expected<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 返回一个空 vector 对象</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>expected <span class=\"token operator\">==</span> actual<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"functionX\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"okay\"</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回列表初始化的 vector 对象</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">else</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"functionX\"</span><span class=\"token punctuation\">,</span> expected<span class=\"token punctuation\">,</span> actual<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>如果函数返回的是内置类型，则花括号包围的列表最多包含一个值，而且该值所占空间不应该大于目标类型的空间</p>\n<p>如果函数返回的是类类型，由类本身来定义如何使用初始值</p>\n<h3 id=\"主函数-main-的返回值\"><a class=\"anchor\" href=\"#主函数-main-的返回值\">#</a> 主函数 main 的返回值</h3>\n<p>之前介绍过，如果函数的返回类型不是 void ，那么它必须返回一个值。但是这条规则有个例外：允许 main 函数没有 return 语句而直接结束</p>\n<p>这是因为，如果控制到达了 main 函数的结尾处而且没有 return 语句，编译器将隐式地插入一条返回 0 的 return 语句</p>\n<h3 id=\"递归\"><a class=\"anchor\" href=\"#递归\">#</a> 递归</h3>\n<p>如果一个函数调用了它自身，不管这种调用是直接的还是间接的，都称该函数为递归函数（recursive function）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 计算 val 的阶乘</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">factorial</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> val<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>val <span class=\"token operator\">></span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">return</span> <span class=\"token function\">factorial</span><span class=\"token punctuation\">(</span>val<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> val<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>main 函数不能调用它自己</p>\n</blockquote>\n<h2 id=\"返回数组指针\"><a class=\"anchor\" href=\"#返回数组指针\">#</a> 返回数组指针</h2>\n<p>因此数组不能被拷贝，所以函数不能返回数组。但是，函数可以返回数组的指针或者引用</p>\n<p>从语法上来说，要想定义一个返回数组的指针或引用的函数比较烦琐，但是有一些方法可以简化这一任务，其中最直接的方法是使用 <strong>类型别名</strong></p>\n<p>例如：func 函数返回一个指向包含 10 个整数的数组的指针，其中，arrT 是含有 10 个整数的数组的别名</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">int</span> arrT<span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//arrT 是一个类型别名，它表示的类型是含有 10 个整数的数组</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> arrT <span class=\"token operator\">=</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//arrT 的等价声明</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>arrT<span class=\"token operator\">*</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">//func 返回一个指向含有 10 个整数的数组的指针</span></pre></td></tr></table></figure><h3 id=\"声明一个返回数组指针的函数\"><a class=\"anchor\" href=\"#声明一个返回数组指针的函数\">#</a> 声明一个返回数组指针的函数</h3>\n<p>如果我们想定义一个返回数组指针的函数，并且不希望使用类型别名，则必须满足：</p>\n<ul>\n<li>数组的维度跟在函数名字之后</li>\n<li>函数的形参列表也跟在函数名字后面，并且形参列表应该先于数组的维度</li>\n</ul>\n<p>因此，返回数组指针的函数形式如下所示：</p>\n<pre><code>Type (*function(parameter_list))[dimension]\n</code></pre>\n<p>其中，Type 表示元素的类型，dimension 表示数组的大小，(*function (parameter_list)) 两端的括号必须存在（如果没有这对括号，函数的返回类型将是指针的数组）</p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token function\">func</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>可以按照以下的顺序来逐层理解该声明的含义：・</p>\n<ul>\n<li>func (int i) 表示调用 func 函数时需要一个 int 类型的实参</li>\n<li>(*func (int i)) 意味着我们可以对函数调用的结果执行解引用操作</li>\n<li>(*func (int i))[10] 表示解引用 func 的调用将得到一个大小为 10 的数组</li>\n<li>int (*func (int i))[10] 表示数组中的元素是 int 类型</li>\n</ul>\n<h3 id=\"使用尾置返回类型\"><a class=\"anchor\" href=\"#使用尾置返回类型\">#</a> 使用尾置返回类型</h3>\n<p>在 C++ 11 标准中还有一种可以简化上述 func 声明的方法，就是使用<strong>尾置返回类型</strong>（trailing return type）</p>\n<p><strong>任何函数的定义都能使用尾置返回</strong>，但是这种形式对于返回类型比较复杂的函数最有效，比如返回类型是数组的指针或者数组的引用</p>\n<p><strong>尾置返回类型跟在形参列表后面，并以一个  <code>-&gt;</code>  符号开头</strong>。为了表示函数真正的返回类型跟在形参列表之后，我们在本应该出现返回类型的地方放置一个  <code>auto</code></p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//func 接受一个 int 类型的实参，返回一个指针，该指针指向含有 10 个整数的数组</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">auto</span> <span class=\"token function\">func</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>因为我们把函数的返回类型放在了形参列表之后，所以可以清楚地看到 func 函数返回的是一个指针，并且该指针指向了含有 10 个整数的数组</p>\n<h3 id=\"使用-decltype\"><a class=\"anchor\" href=\"#使用-decltype\">#</a> 使用 decltype</h3>\n<p>如果我们知道函数返回的指针将指向哪个数组，可以使用  <code>decltype</code>  关键字声明返回类型</p>\n<p>例如，下面的函数返回一个指针，该指针根据参数 i 的不同指向两个已知数组中的某一个</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> odd<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">9</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> even<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span><span class=\"token number\">8</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 返回一个指针，该指针指向含有 5 个整数的数组</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">decltype</span><span class=\"token punctuation\">(</span>odd<span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span><span class=\"token function\">arrPtr</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">%</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> <span class=\"token operator\">&amp;</span>odd <span class=\"token operator\">:</span> <span class=\"token operator\">&amp;</span>even<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 返回一个指向数组的指针</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>arrPtr 使用关键字  <code>decltype</code>  表示它的返回类型是个指针，并且该指针所指对象的类型与 odd 一致。因为 odd 是数组，所以 arrPtr 返回一个指向含有 5 个整数的数组的指针</p>\n<p>注意：<strong> <code>decltype</code>  并不负责把数组类型转换成对应的指针</strong>，所以 decltype 的结果是个数组，要想表示 arrPtr 返回指针还必须在函数声明时加一个  <code>*</code>  符号</p>\n<h1 id=\"函数重载\"><a class=\"anchor\" href=\"#函数重载\">#</a> 函数重载</h1>\n<p>如果同一作用域内的几个函数名字相同但形参列表不同，我们称之为 <strong>重载</strong>（overloaded）<strong>函数</strong></p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>cp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>beg<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> <span class=\"token operator\">*</span>end<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> ia<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> size_t size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这些函数接受的形参类型不一样，但是执行的操作非常类似。当调用这些函数时，编译器会根据传递的实参类型推断想要的是哪个函数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> j<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello World\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 调用 print (const char*)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">,</span> <span class=\"token function\">end</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token function\">begin</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用 print (const int*, size_t)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">end</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">// 调用 print (const int*, const int*)</span></pre></td></tr></table></figure><blockquote>\n<p>main 函数不能重载</p>\n</blockquote>\n<h2 id=\"重载函数的定义与调用\"><a class=\"anchor\" href=\"#重载函数的定义与调用\">#</a> 重载函数的定义与调用</h2>\n<h3 id=\"定义重载函数\"><a class=\"anchor\" href=\"#定义重载函数\">#</a> 定义重载函数</h3>\n<p>重载的函数应该在形参数量或形参类型上有所不同</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 定义一组函数，分别根据名字、电话、账号等信息查找记录</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 根据 Account 查找记录</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Phone<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 根据 Phone 查找记录</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Name<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 根据 Name 查找记录</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>Account acct<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>Phone phone<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>Record r1 <span class=\"token operator\">=</span> <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>acct<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 调用接受 Account 的版本</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>Record r2 <span class=\"token operator\">=</span> <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>phone<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用接受 Phone 的版本</span></pre></td></tr></table></figure><p>不允许两个函数除了返回类型外其他所有要素都相同：假设有两个函数，它们的形参列表一样但是返回类型不同，则第二个函数的声明是错误的</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：与上一个函数相比只有返回类型不同</span></pre></td></tr></table></figure><h3 id=\"判断两个形参的类型是否相异\"><a class=\"anchor\" href=\"#判断两个形参的类型是否相异\">#</a> 判断两个形参的类型是否相异</h3>\n<p>有时候两个形参列表看起来不一样，但实际上是相同的</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 每一对声明都是同一个函数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account <span class=\"token operator\">&amp;</span>acct<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 省略了形参的名字</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">typedef</span> Phone Telno<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Phone<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Telno<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Telno 和 Phone 的类型相同（Telno 是 Phone 的别名）</span></pre></td></tr></table></figure><p>由于顶层 const 不影响传入函数的对象（详见 <strong>参数传递</strong> ），一个拥有顶层 const 的形参无法和另一个没有顶层 const 的形参区分开来</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>Phone<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Phone<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 重复声明了 Record lookup (Phone)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>Phone<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>Phone<span class=\"token operator\">*</span> <span class=\"token keyword\">const</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 重复声明了 Record lookup (Phone*)</span></pre></td></tr></table></figure><p>如果形参是某种类型的指针或引用，则可区分其指向的是常量对象还是非常量对象（此时考虑的是底层 const ），以实现函数重载</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 对于接受引用或指针的函数而言，常量对象与非常量对象对应的形参不同</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 定义了 4 个独立的重载函数</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>       <span class=\"token comment\">// 函数作用于 Account 的引用</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 新函数，作用于 Account 的常量引用</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>Account<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>       <span class=\"token comment\">// 新函数，作用于 Account 的指针</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 新函数，作用于指向 Account 常量的指针</span></pre></td></tr></table></figure><p>在上面的例子中，编译器可以通过实参是否是常量来推断应该调用哪个函数</p>\n<ul>\n<li>因为 const 不能转换成其他类型，所以我们只能把 const 对象（或指向 const 的指针）传递给 const 形参</li>\n<li>相反地，因为非常量可以转换成 const ，所以上面的 4 个函数都能作用于非常量对象或者指向非常量对象的指针</li>\n<li>不过，当我们要传递一个非常量对象或者指向非常量对象的指针时，编译器会优先选用非常量版本的函数</li>\n</ul>\n<h3 id=\"建议何时不应该重载函数\"><a class=\"anchor\" href=\"#建议何时不应该重载函数\">#</a> 建议：何时不应该重载函数</h3>\n<p>尽管函数重载能在一定程度上减轻我们为函数起名字、记名字的负担，但是最好只重载那些确实非常相似的操作</p>\n<p>有些情况下，给函数起不同的名字能使得程序更易理解</p>\n<p>例如，以下是几个负责移动屏幕光标的函数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Screen<span class=\"token operator\">&amp;</span> <span class=\"token function\">moveHome</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Screen<span class=\"token operator\">&amp;</span> <span class=\"token function\">moveAbs</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>Screen<span class=\"token operator\">&amp;</span> <span class=\"token function\">moveRel</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> string direction<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>乍看上去，似乎可以把这组函数统一命名为 move ，从而实现函数的重载。然而，重载之后这些函数失去了名字中本来拥有的信息（因为这些函数移动光标的具体方式各不相同）</p>\n<p>一般来说，是否重载函数要看哪个更容易理解</p>\n<h3 id=\"const_cast-和重载\"><a class=\"anchor\" href=\"#const_cast-和重载\">#</a> const_cast 和重载</h3>\n<p>const_cast 常常用于有函数重载的上下文中</p>\n<p>考虑下面的 shorterString 函数，其参数和返回类型都是 const string 的引用，我们可以对两个非常量的 string 实参调用这个函数，但返回的仍然是 const string 的引用</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 无论实参是常量还是非常量，返回类型都是 const string &amp;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 形参是 const string &amp; 类型</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">return</span> s1<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> s2<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> s1 <span class=\"token operator\">:</span> s2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>为了实现 “当实参不是常量时，得到的结果是一个普通的引用，即 string &amp;”，可以使用 const_cast 定义一种新的 shorterString 函数：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string <span class=\"token operator\">&amp;</span><span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span>string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 形参是 string &amp; 类型</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">auto</span> <span class=\"token operator\">&amp;</span>r <span class=\"token operator\">=</span> <span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span><span class=\"token generic-function\"><span class=\"token function\">const_cast</span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span>s1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>                            <span class=\"token generic-function\"><span class=\"token function\">const_cast</span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span>s2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用形参为 const string &amp; 类型的 shorterString 函数</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token generic-function\"><span class=\"token function\">const_cast</span><span class=\"token generic class-name\"><span class=\"token operator\">&lt;</span>string<span class=\"token operator\">&amp;</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>在这个版本的函数中，首先将它的实参强制转换成对 const 的引用，然后调用了 shorterString 函数的 const 版本。const 版本返回对 const string 的引用，这个引用事实上绑定在了某个初始的非常量实参上。因此，我们可以再将其转换回一个普通的 string &amp;</p>\n<h3 id=\"调用重载的函数\"><a class=\"anchor\" href=\"#调用重载的函数\">#</a> 调用重载的函数</h3>\n<p><strong>函数匹配</strong>（function matching）：把函数调用与一组重载函数中的某一个关联起来。具体而言，编译器首先将调用的实参与重载集合中每一个函数的形参进行比较，然后根据比较的结果决定到底调用哪个函数</p>\n<p>函数匹配也叫做<strong>重载确定</strong>（overload resolution）</p>\n<p>调用重载函数时，有三种可能的结果：</p>\n<ul>\n<li>编译器找到一个与实参<strong>最佳匹配</strong>（best match）的函数，并生成调用该函数的代码</li>\n<li>找不到任何一个函数与调用的实参匹配，此时编译器发出<strong>无匹配</strong>（no match）的错误信息</li>\n<li>有多于一个函数可以匹配，但是每一个都不是明显的最佳选择。此时也将发生错误，称为<strong>二义性调用</strong>（ambiguous call）</li>\n</ul>\n<h2 id=\"重载与作用域\"><a class=\"anchor\" href=\"#重载与作用域\">#</a> 重载与作用域</h2>\n<blockquote>\n<p>一般来说，将函数声明置于局部作用域内不是一个明智的选择。但是为了说明作用域和重载的相互关系，我们将暂时违反这一原则而使用局部函数声明</p>\n</blockquote>\n<p>如果我们在内层作用域中声明名字，它将隐藏外层作用域中声明的同名实体</p>\n<p>因此，在不同的作用域中，无法重载函数名</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string <span class=\"token function\">read</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">double</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 重载 print 函数</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fooBar</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> ival<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">bool</span> read <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 新作用域，隐藏了外层作用域中声明的 read</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    string s <span class=\"token operator\">=</span> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：read 是一个布尔对象，而不是函数（因为外层的 read 函数被隐藏了）</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token comment\">// 通常来说，在局部作用域中声明函数不是一个好的选择</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 新作用域，隐藏了外层作用域中的 print</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Value: \"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：print (const string &amp;) 被隐藏掉了</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span>ival<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 正确：当前 print (int) 可见</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token number\">3.14</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 正确：调用 print (int) （外层的 print (double) 被隐藏了）</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>当我们调用 print 函数时，编译器首先寻找对该函数名的声明，找到的是接受 int 值的那个局部声明。<strong>一旦在当前作用域中找到了所需的名字，编译器就会忽略掉外层作用域中的同名实体</strong>。剩下的工作就是检查函数调用是否有效了</p>\n<blockquote>\n<p>在 C++ 语言中，名字查找发生在类型检查之前</p>\n</blockquote>\n<p>第一个调用 print (&quot;Value:&quot;) 传入一个字符串字面值，但是当前作用域内 print 函数唯一的声明要求参数是 int 类型，由于字符串字面值无法转换成 int 类型，这个调用是错误的（虽然外层作用域中的 print (const string&amp;) 函数与本次调用匹配，但是它已经被隐藏掉了，根本不会被考虑）</p>\n<p>假设我们把 print (int) 和其他 print 函数声明放在同一个作用域中，则它将成为另一种重载形式：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">double</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//print 函数的重载形式</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">//print 函数的另一种重载形式</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">fooBar2</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> ival<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Value: \"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用 print (const string &amp;)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span>ival<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 调用 print (int)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token number\">3.14</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 调用 print (double)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h1 id=\"特殊用途语言特性\"><a class=\"anchor\" href=\"#特殊用途语言特性\">#</a> 特殊用途语言特性</h1>\n<p>本节我们介绍函数相关的三种语言特性，这些特性对大多数程序都有用，它们分别是：默认实参、内联函数和 constexpr 函数，以及在程序调试过程中常用的一些功能</p>\n<h2 id=\"默认实参\"><a class=\"anchor\" href=\"#默认实参\">#</a> 默认实参</h2>\n<p>有些函数的某个参数在大多数（但不是所有）调用中都被赋予了特定的值。此时，我们可以把这个特定值称为函数的<strong>默认实参</strong>（default argument）</p>\n<p>默认实参作为形参的初始值出现在形参列表中</p>\n<p>例如，我们使用 string 对象表示窗口的内容。一般情况下，我们希望该窗口的高、宽和背景字符都使用默认值，但是同时我们也应该允许用户为这几个参数自由指定与默认值不同的数值。因此，我们为每一个形参都提供了默认实参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">typedef</span> string<span class=\"token double-colon punctuation\">::</span>size_type sz<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>string <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span>sz ht <span class=\"token operator\">=</span> <span class=\"token number\">24</span><span class=\"token punctuation\">,</span> sz wid <span class=\"token operator\">=</span> <span class=\"token number\">80</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> backgrnd <span class=\"token operator\">=</span> <span class=\"token char\">' '</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>我们可以为一个或多个形参定义默认值，不过需要注意的是，<strong>一旦某个形参被赋予了默认值，它后面的所有形参都必须有默认值</strong></p>\n<p>调用含有默认实参的函数时，可以包含该实参，也可以省略该实参</p>\n<h3 id=\"使用默认实参调用函数\"><a class=\"anchor\" href=\"#使用默认实参调用函数\">#</a> 使用默认实参调用函数</h3>\n<p>如果我们想使用默认实参，只要在调用函数的时候省略该实参就可以了</p>\n<p>函数调用时实参按其位置解析，默认实参负责填补函数调用缺少的尾部实参（靠右侧位置）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string window<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>              <span class=\"token comment\">// 等价于 screen (24, 80, ' ')</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token number\">66</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>            <span class=\"token comment\">// 等价于 screen (66, 80, ' ')</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token number\">66</span><span class=\"token punctuation\">,</span> <span class=\"token number\">256</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>       <span class=\"token comment\">// 等价于 screen (66, 256, ' ')</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token number\">66</span><span class=\"token punctuation\">,</span> <span class=\"token number\">256</span><span class=\"token punctuation\">,</span> <span class=\"token char\">'#'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 等价于 screen (66, 256, '#')</span></pre></td></tr></table></figure><p>要想覆盖 backgrnd 的默认值，必须为 ht 和 wid 提供实参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">,</span> <span class=\"token char\">'?'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：只能省略尾部的实参</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token char\">'?'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">// 调用 screen ('?', 80, ' ')</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>                          <span class=\"token comment\">//char 型的 '?' 可以转换成 string::size_type 类型的值 63</span></pre></td></tr></table></figure><p>当设计含有默认实参的函数时，需要合理设置形参的顺序，尽量让不怎么使用默认值的形参出现在前面，让那些经常使用默认值的形参出现在后面</p>\n<h3 id=\"默认实参声明\"><a class=\"anchor\" href=\"#默认实参声明\">#</a> 默认实参声明</h3>\n<p>对于函数的声明来说，通常的习惯是将其放在头文件中，并且一个函数只声明一次，但是多次声明同一个函数也是合法的</p>\n<p>不过有一点需要注意，在给定的作用域中一个形参只能被赋予一次默认实参。换句话说，函数的后续声明只能为之前那些没有默认值的形参添加默认实参，而且该形参右侧的所有形参必须都有默认值</p>\n<p>假如给定</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 表示高度和宽度的形参没有默认值</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>string <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span>sz<span class=\"token punctuation\">,</span> sz<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">=</span> <span class=\"token char\">' '</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>我们就不能再修改一个已经存在的默认值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span>sz<span class=\"token punctuation\">,</span> sz<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">=</span> <span class=\"token char\">'*'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：重复赋予默认实参</span></pre></td></tr></table></figure><p>但是可以按照如下形式添加默认实参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span>sz <span class=\"token operator\">=</span> <span class=\"token number\">24</span><span class=\"token punctuation\">,</span> sz <span class=\"token operator\">=</span> <span class=\"token number\">80</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：添加默认实参</span></pre></td></tr></table></figure><blockquote>\n<p>通常，应该在函数声明中指定默认实参，并将该声明放在合适的头文件中</p>\n</blockquote>\n<h3 id=\"默认实参初始值\"><a class=\"anchor\" href=\"#默认实参初始值\">#</a> 默认实参初始值</h3>\n<p>除了<strong>局部变量不能作为默认实参</strong>外，只要表达式的类型能转换成形参所需的类型，该表达式就能作为默认实参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//wd、def 和 ht 的声明必须出现在函数之外</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>sz wd <span class=\"token operator\">=</span> <span class=\"token number\">80</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">char</span> def <span class=\"token operator\">=</span> <span class=\"token char\">' '</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>sz <span class=\"token function\">ht</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>string <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span>sz <span class=\"token operator\">=</span> <span class=\"token function\">ht</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> sz <span class=\"token operator\">=</span> wd<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">=</span> def<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>string window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用 screen (ht (), 80, ' ')</span></pre></td></tr></table></figure><p>用作默认实参的名字（例如 ht () ）会在函数声明所在的作用域内解析，但是会在函数调用时才求值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f2</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    def <span class=\"token operator\">=</span> <span class=\"token char\">'*'</span><span class=\"token punctuation\">;</span>          <span class=\"token comment\">// 改变了默认实参的值</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    sz wd <span class=\"token operator\">=</span> <span class=\"token number\">100</span><span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 隐藏了外层定义的 wd ，但是没有改变默认值</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    window <span class=\"token operator\">=</span> <span class=\"token function\">screen</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 调用 screen (ht (), 80, '*')</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>我们在函数 f2 内部改变了 def 的值，所以对 screen 的调用将会传递这个更新过的值。另一方面，虽然我们的函数还声明了一个局部变量用于隐藏外层的 wd ，但是该局部变量与传递给 screen 的默认实参没有任何关系</p>\n<h2 id=\"内联函数和-constexpr-函数\"><a class=\"anchor\" href=\"#内联函数和-constexpr-函数\">#</a> 内联函数和 constexpr 函数</h2>\n<p>此前我们编写了一个函数 shroterString ，用于比较两个 string 形参的长度并返回长度较小的 string 的引用。将这种规模较小的操作定义成函数，具有以下优点：</p>\n<ul>\n<li>便于阅读</li>\n<li>可以确保行为的统一</li>\n<li>如果我们需要修改计算过程，修改函数要比修改所有等价表达式更容易</li>\n<li>可以被其他应用重复利用</li>\n</ul>\n<p>然而，使用 shorterString 函数也存在一个潜在的缺点：调用函数一般比求等价表达式的值要慢一些</p>\n<p>在大多数机器上，一次函数调用其实包含着一系列工作：</p>\n<ul>\n<li>调用前要先保存寄存器，并在返回时恢复</li>\n<li>可能需要拷贝实参</li>\n<li>程序转向一个新的位置继续执行</li>\n</ul>\n<h3 id=\"内联函数可以避免函数调用的开销\"><a class=\"anchor\" href=\"#内联函数可以避免函数调用的开销\">#</a> 内联函数可以避免函数调用的开销</h3>\n<p>将函数指定为<strong>内联函数</strong>（inline），通常就是将它在每个调用点上 “内联地” 展开</p>\n<p>假设我们把 shorterString 函数定义成内联函数，则如下调用</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span>s1<span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>将在编译过程中展开成类似于下面的形式</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token punctuation\">(</span>s1<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> s2<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> s1 <span class=\"token operator\">:</span> s2<span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>从而消除了 shorterString 函数的运行时开销</p>\n<p><strong>在函数返回类型的前面加上加上关键字  <code>inline</code>  ，即可将其声明为内联函数</strong></p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 内联版本：寻找两个 string 对象中较短的那个</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">inline</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span> <span class=\"token function\">shorterString</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">return</span> s1<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;=</span> s2<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> s1 <span class=\"token operator\">:</span> s2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>内联说明只是向编译器发出的一个请求，编译器可以选择忽略这个请求</p>\n</blockquote>\n<p>一般来说，内联机制用于优化规模较小、流程直接、频繁调用的函数</p>\n<p>很多编译器都不支持内联递归函数，而且，一个太长的函数也不太可能在调用点 “内联地” 展开</p>\n<h3 id=\"constexpr-函数\"><a class=\"anchor\" href=\"#constexpr-函数\">#</a> constexpr 函数</h3>\n<p><strong>constexpr 函数</strong>（constexpr function）是指能用于常量表达式的函数</p>\n<p>constexpr 函数的定义：</p>\n<ul>\n<li>函数的返回类型及所有形参的类型都必须是字面值类型</li>\n<li>函数体中必须有且只有一条 return 语句</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">constexpr</span> <span class=\"token keyword\">int</span> <span class=\"token function\">new_sz</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> <span class=\"token number\">42</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">constexpr</span> <span class=\"token keyword\">int</span> foo <span class=\"token operator\">=</span> <span class=\"token function\">new_sz</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 正确：foo 是一个常量表达式</span></pre></td></tr></table></figure><p>在上面的代码中，我们把 new_sz 定义成一个无参数的 constexpr 函数，于是，new_sz 函数返回的是常量表达式，因此可以用 new_sz 函数来初始化 constexpr 类型的变量 foo</p>\n<p>执行该初始化任务时，编译器把对 constexpr 函数的调用替换成其结果值。为了能在编译过程中随时展开，<strong>constexpr 函数被隐式地指定为内联函数</strong></p>\n<blockquote>\n<p>constexpr 函数体内也可以包含其他语句，只要这些语句在运行时不执行任何操作就行。例如，constexpr 函数中可以有空语句、类型别名以及 using 声明</p>\n</blockquote>\n<p>constexpr 函数的返回值可以不是一个常量</p>\n<p>例如：定义一个 constexpr 函数 scale 。当我们给 scale 函数传入一个形如字面值 2 的常量表达式时，它的返回类型也是常量表达式，此时，编译器用相应的结果值替换对 scale 函数的调用。相反，如果我们用一个非常量表达式调用 scale 函数，比如 int 类型的对象 i ，则返回值是一个非常量表达式</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 如果 arg 是常量表达式，则 scale (arg) 也是常量表达式</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">constexpr</span> size_t <span class=\"token function\">scale</span><span class=\"token punctuation\">(</span>size_t cnt<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token keyword\">return</span> <span class=\"token function\">new_sz</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> cnt<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">// 当 scale 的实参是常量表达式时，它的返回值也是常量表达式；反之则不是</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> arr<span class=\"token punctuation\">[</span><span class=\"token function\">scale</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：scale (2) 是常量表达式</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>         <span class=\"token comment\">//i 不是常量表达式</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">int</span> a2<span class=\"token punctuation\">[</span><span class=\"token function\">scale</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 错误：scale (i) 不是常量表达式</span></pre></td></tr></table></figure><p>当把 scale 函数用在需要常量表达式的上下文中时，编译器会负责检查函数的结果是否符合要求。如果结果恰好不是常量表达式，编译器将发出错误信息</p>\n<blockquote>\n<p>constexpr 函数不一定返回常量表达式</p>\n</blockquote>\n<h3 id=\"把内联函数和-constexpr-函数放在头文件内\"><a class=\"anchor\" href=\"#把内联函数和-constexpr-函数放在头文件内\">#</a> 把内联函数和 constexpr 函数放在头文件内</h3>\n<p>和其他函数不一样，内联函数和 constexpr 函数可以在程序中多次定义</p>\n<p>不过，对于某个给定的内联函数或者 constexpr 函数来说，它的多个定义必须完全一致</p>\n<p>因此，内联函数和 constexpr 函数通常定义在头文件中</p>\n<h2 id=\"调试帮助\"><a class=\"anchor\" href=\"#调试帮助\">#</a> 调试帮助</h2>\n<p>C++ 程序员有时会用到一种类似于 <strong>头文件保护</strong> 的技术，以便有选择地执行调试代码</p>\n<p>基本思想：程序可以包含一些用于调试的代码，这些代码只在开发程序时使用。当应用程序编写完成准备发布时，要先屏蔽掉调试代码</p>\n<p>这种方法用到两项预处理功能： <code>assert</code>  和  <code>NDEBUG</code></p>\n<h3 id=\"assert-预处理宏\"><a class=\"anchor\" href=\"#assert-预处理宏\">#</a> assert 预处理宏</h3>\n<p>assert 是一种预处理宏（preprocessor marco）</p>\n<p>预处理宏是一个行为类似于内联函数的预处理变量</p>\n<p>assert 宏使用一个表达式作为它的条件：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">assert</span><span class=\"token punctuation\">(</span>expr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>其首先对 expr 求值，如果表达式为假（即，值为 0），assert 输出信息并终止程序的执行。如果表达式为真（即，值不为 0），assert 什么也不做</p>\n<p>assert 宏定义在  <code>cassert</code>  头文件中，即：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span><span class=\"token string\">&lt;cassert></span></span></pre></td></tr></table></figure><blockquote>\n<p>预处理名字由预处理器而非编译器管理，因此我们可以直接使用预处理名字，即，直接使用 assert 而不是 std::assert，也不需要为 assert 提供 using 声明</p>\n</blockquote>\n<blockquote>\n<p>和预处理变量一样，宏名字在程序内必须唯一。因此，含有 cassert 头文件的程序不能再定义名为 assert 的变量、函数或者其他实体</p>\n</blockquote>\n<p><strong>assert 宏常用于检查 “不能发生” 的条件</strong></p>\n<p>例如，一个对输入文本进行操作的程序，可能要求所有给定单词的长度都大于某个阈值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">assert</span><span class=\"token punctuation\">(</span>word<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">></span> threshold<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"ndebug-预处理变量\"><a class=\"anchor\" href=\"#ndebug-预处理变量\">#</a> NDEBUG 预处理变量</h3>\n<p>NDEBUG 是一个预处理变量，表示当前不处于调试状态（not debug），可用于控制 assert 的行为：</p>\n<ul>\n<li>如果没有定义 NDEBUG ，assert 将执行运行时检查</li>\n<li>如果定义了 NDEBUG ，则 assert 什么也不做</li>\n</ul>\n<p>默认状态下，没有定义 NDEBUG</p>\n<p>我们可以使用一个 #define 语句定义 NDEBUG ，从而关闭调试状态</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">define</span> <span class=\"token macro-name\">NDEBUG</span> <span class=\"token comment\">// 关闭调试状态（必须定义在 cassert 头文件之前）</span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;cassert></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">void</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> x <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token function\">assert</span><span class=\"token punctuation\">(</span>x<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>定义 NDEBUG 能避免检查各种条件所需的运行时开销（其实根本就不会执行运行时检查），因此，assert 应该仅用于验证那些确实不可能发生的事情</p>\n<blockquote>\n<p>我们可以把 assert 当成调试程序的一种辅助手段，但是不能用它替代真正的运行时逻辑检查，也不能替代程序本身应该包含的错误检查</p>\n</blockquote>\n<p>除了用于 assert 外，也可以使用 NDEBUG 编写自己的条件调试代码（详见 <strong>预处理变量</strong> ）</p>\n<ul>\n<li>如果 NDEBUG 未定义，将执行 #ifndef 和 #endif 之间的代码</li>\n<li>如果定义了 NDEBUG ，则会忽略 #ifndef 和 #endif 之间的代码</li>\n</ul>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">print</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> ia<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> size_t size<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">ifndef</span> <span class=\"token expression\">NDEBUG</span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">//_ _func_ _ 是编译器定义的一个局部静态变量，用于存放函数的名字</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>cerr <span class=\"token operator\">&lt;&lt;</span> _ _func_ _ <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\": array size is \"</span> <span class=\"token operator\">&lt;&lt;</span> size <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">endif</span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">// ...</span></pre></td></tr></table></figure><p>在这段代码中，我们使用变量  <code>_ _func_ _</code>  输出当前调试的函数的名字（即 &quot;print&quot; ）</p>\n<p>编译器为每个函数都定义了  <code>_ _func_ _</code>  ，它是  <code>const char</code>  的一个静态数组，用于存放函数的名字</p>\n<p>除了 C++ 编译器定义的  <code>_ _func_ _</code>  之外，预处理器还定义了另外 4 个用于程序调试的名字：</p>\n<ul>\n<li><code>_ _FILE_ _</code>  ：存放文件名的字符串字面值</li>\n<li><code>_ _LINE_ _</code>  ：存放当前行号的整型字面值</li>\n<li><code>_ _LINE_ _</code>  ：存放当前行号的整型字面值</li>\n<li><code>_ _DATE_ _</code>  ：存放文件编译日期的字符串字面值</li>\n</ul>\n<p>可以使用这些常量在错误消息中提供更多信息，例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>word<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span> threshold<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    cerr <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"Error: \"</span> <span class=\"token operator\">&lt;&lt;</span> _ _FILE_ _</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" : in function \"</span> <span class=\"token operator\">&lt;&lt;</span> _ _func_ _</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" at line \"</span> <span class=\"token operator\">&lt;&lt;</span> _ _LINE_ _ <span class=\"token operator\">&lt;&lt;</span> endl</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"       Compiled on \"</span> <span class=\"token operator\">&lt;&lt;</span> _ _DATE_ _</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" at \"</span> <span class=\"token operator\">&lt;&lt;</span> _ _TIME_ _ <span class=\"token operator\">&lt;&lt;</span> endl</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"       Word read was \\\"\"</span> <span class=\"token operator\">&lt;&lt;</span> word</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"\\\":  Length too short\"</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>如果我们给程序提供了一个长度小于 threshold 的 string 对象，将得到下面的错误消息：</p>\n<pre><code>Error:wdebug.cc : in function main at line 27\n       Compiled on Jul 11 2012 at 20:50:03\n       Word read was &quot;foo&quot;: Length too short\n</code></pre>\n<h1 id=\"函数匹配\"><a class=\"anchor\" href=\"#函数匹配\">#</a> 函数匹配</h1>\n<p>当重载函数的形参数量相等、并且某些形参的类型可以由其他类型转换得到时，不太容易确定某次调用应该选用哪个重载函数</p>\n<h2 id=\"函数匹配-2\"><a class=\"anchor\" href=\"#函数匹配-2\">#</a> 函数匹配</h2>\n<p>函数匹配：从一组重载函数中选取最佳函数的过程</p>\n<h3 id=\"函数匹配的步骤\"><a class=\"anchor\" href=\"#函数匹配的步骤\">#</a> 函数匹配的步骤</h3>\n<p>选定本次调用对应的重载函数集</p>\n<ul>\n<li>集合中的函数称为 <strong>候选函数</strong>（candidate function）</li>\n<li>候选函数具备两个特征：\n<ul>\n<li>与被调用的函数同名</li>\n<li>其声明在调用点可见</li>\n</ul>\n</li>\n</ul>\n<p>考察本次调用提供的实参，从候选函数中选出能被这组实参调用的函数</p>\n<ul>\n<li>这些新选出的函数称为 <strong>可行函数</strong>（viable function）</li>\n<li>可行函数具备两个特征：\n<ul>\n<li>形参数量与本次调用提供的实参数量相等（如果函数含有默认实参，在调用该函数时，传入的实参数量可能少于它实际使用的实参数量）</li>\n<li>每个实参的类型与对应的形参类型相同，或者能转换成形参的类型</li>\n</ul>\n</li>\n<li>如果没找到可行函数，编译器将报告无匹配函数的错误</li>\n</ul>\n<p>逐一检查函数调用提供的实参，寻找形参类型与实参类型最匹配的那个可行函数（即，寻找<strong>最佳匹配</strong>）</p>\n<ul>\n<li>如果有且只有一个函数满足下列条件，则匹配成功：\n<ul>\n<li>该函数每个实参的匹配都不劣于其他可行函数需要的匹配</li>\n<li>至少有一个实参的匹配优于其他可行函数提供的匹配</li>\n</ul>\n</li>\n<li>下一节将介绍到：实参类型与形参类型越接近，它们匹配得越好</li>\n<li>如果在检查了所有实参之后没有任何一个函数脱颖而出，则该调用是错误的。此时，编译器将报告二义性调用的信息</li>\n</ul>\n<blockquote>\n<p>调用重载函数时应尽量避免强制类型转换，如果在实际应用中确实需要强制类型转换，则说明我们设计的形参列表不合理</p>\n</blockquote>\n<h3 id=\"实例分析\"><a class=\"anchor\" href=\"#实例分析\">#</a> 实例分析</h3>\n<p>以下面这组函数及其调用为例：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">double</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">double</span> <span class=\"token operator\">=</span> <span class=\"token number\">3.14</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token number\">5.6</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 调用 f (double, double)</span></pre></td></tr></table></figure><p>第一步：可以确定上述 4 个名为 f 的函数均为候选函数</p>\n<p>第二步：可以根据实参的数量排除 void f () 和 void f (int, int) ，选出  void f (int) 和 void f (double, double = 3.14) 两个可行函数</p>\n<ul>\n<li>排除的两个函数：我们的调用提供了一个实参，而 void f () 不使用形参，void f (int, int) 使用两个形参</li>\n<li>可行的两个函数：void f (int) 使用一个 int 形参，而我们调用传入的 double 实参可以转换成形参类型 int ；void f (double, double = 3.14) 本应接受两个 double 实参，但因为它含有一个默认实参，所以可以只用一个实参来调用它</li>\n</ul>\n<p>第三步：逐一考察实参，寻找最佳匹配</p>\n<ul>\n<li>调用提供了一个（显式的）double 型实参，如果调用 f (int) ，实参将不得不从 double 转换成 int</li>\n<li>相反，可行函数 void (double, double) 则与实参精确匹配</li>\n<li><strong>精确匹配比需要类型转换的匹配更好</strong>，因此，编译器把 f (5.6) 解析成对函数 void (double, double) 的调用，并使用默认值填补我们未提供的第二个实参</li>\n</ul>\n<p>当实参的数量有两个或更多时，函数匹配就比较复杂了</p>\n<p>例如，考察形如 f (42, 2.56) 的调用：</p>\n<p>第一步：4 个名为 f 的函数均为候选函数</p>\n<p>第二步：确定 void f (int, int) 和 void f (double, double) 为可行函数</p>\n<p>第三步：逐一考察实参，寻找最佳匹配</p>\n<ul>\n<li>考虑第一个实参 42 ：函数 f (int, int) 能精确匹配，而函数 f (double, double) 需要先将 int 类型实参转换成 double 类型。此时，函数 f (int, int) 优于 函数 f (double, double)</li>\n<li>接着考虑第二个实参 2.56 ：函数 f (double, double) 能精确匹配，而函数 f (int, int) 须将 2.56 从 double 类型转换成 int 型。此时，函数 f (double, double) 优于 函数 f (int, int)</li>\n<li>由于每个可行函数各自在一个实参上实现了更好的匹配，无法从整体上判断孰优孰劣。编译器最终将因为这个调用具有二义性而拒绝其请求</li>\n</ul>\n<blockquote>\n<p>看起来我们似乎可以通过强制类型转换其中的一个实参来实现函数的匹配，但是在设计良好的系统中，不应该对实参进行强制类型转换</p>\n</blockquote>\n<h2 id=\"实参类型转换\"><a class=\"anchor\" href=\"#实参类型转换\">#</a> 实参类型转换</h2>\n<p>为了确定最佳匹配，编译器将实参类型到形参类型的转换划分成几个等级，具体排序如下所示（越靠前的，匹配程度越好）：</p>\n<ul>\n<li>精确匹配，其包括以下情况：\n<ul>\n<li>实参类型和形参类型相同</li>\n<li>实参从数组类型或函数类型转换成对应的指针类型</li>\n<li>向实参添加顶层 const 或者从实参中删除顶层 const</li>\n</ul>\n</li>\n<li>通过 const 转换实现的匹配</li>\n<li>通过类型提升实现的匹配</li>\n<li>通过算术类型转换或指针转换实现的匹配</li>\n<li>通过类类型转换实现的匹配</li>\n</ul>\n<h3 id=\"需要类型提升和算术类型转换的匹配\"><a class=\"anchor\" href=\"#需要类型提升和算术类型转换的匹配\">#</a> 需要类型提升和算术类型转换的匹配</h3>\n<p><strong>小整型一般都会提升到 int 类型或更大的整数类型</strong></p>\n<p>例如，假设有两个函数，一个接受 int 、另一个接受 short ，则</p>\n<ul>\n<li>只有当调用提供的是 short 类型的值时才会选择 short 版本的函数</li>\n<li>有时候，即使实参是一个很小的整数值，也会直接将它提升成 int 类型，此时使用 short 版本反而会导致类型转换</li>\n</ul>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">ff</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">ff</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">short</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">ff</span><span class=\"token punctuation\">(</span><span class=\"token char\">'a'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//char 提升成 int ，调用 f (int)</span></pre></td></tr></table></figure><p><strong>所有算术类型转换的级别都一样</strong></p>\n<p>例如，从 int 向 unsigned int 的转换并不比从 int 向 double 的转换级别高</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">manip</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">long</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">manip</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">float</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">manip</span><span class=\"token punctuation\">(</span><span class=\"token number\">3.14</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：二义性调用</span></pre></td></tr></table></figure><h3 id=\"函数匹配和-const-实参\"><a class=\"anchor\" href=\"#函数匹配和-const-实参\">#</a> 函数匹配和 const 实参</h3>\n<p><strong>如果重载函数的区别仅在于函数的引用类型的形参是否为常量引用（或者，指针类型的形参是否为常量指针），编译器将通过实参是否为常量来决定选择哪个函数</strong></p>\n<blockquote>\n<p>When we call an overloaded function that differs on whether a reference or pointer parameter refers or points to const, the compiler uses the constness of the argument to decide which function to call.</p>\n</blockquote>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>       <span class=\"token comment\">// 函数的参数是 Account 的引用</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Record <span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Account<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 函数的参数是 Account 的常量引用</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">const</span> Account a<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>Account b<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 调用 lookup (const Account&amp;)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">lookup</span><span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 调用 lookup (Account&amp;)</span></pre></td></tr></table></figure><p>第一个调用传入的是 const 对象 a ：因为不能把普通引用绑定到 const 对象上，唯一可行的函数是 以常量引用作为形参的函数 lookup (const Account&amp;) ，并且调用该函数与实参 a 精确匹配</p>\n<p>第二个调用传入的是非常量对象 b ：对于该调用而言，两个函数都是可行的，因为 b 既可以用来初始化常量引用也可以用来初始化非常量引用。然而，用非常量对象来初始化常量引用需要类型转换，因此，应该选用非常量版本的函数 lookup (Account&amp;)</p>\n<p>指针类型的形参也是类似的：如果两个函数的唯一区别是指针形参指向常量或非常量，编译器通过实参是否为常量来决定选用哪个函数</p>\n<ul>\n<li>如果实参是指向常量的指针，调用形参为 const* 的函数</li>\n<li>如果实参是指向非常量的指针，调用形参是普通指针的函数</li>\n</ul>\n<h1 id=\"函数指针\"><a class=\"anchor\" href=\"#函数指针\">#</a> 函数指针</h1>\n<p>函数指针（function pointer）指向的是函数而非对象</p>\n<p>类似于其他指针，函数指针也指向一个特定的类型（即，函数的类型）</p>\n<p>函数的类型由它的返回类型和形参类型共同决定，与函数名无关</p>\n<blockquote>\n<p>A function pointer is just that—a pointer that denotes a function rather than an object. Like any other pointer, a function pointer points to a particular type. A function’s type is determined by its return type and the types of its parameters. The function’s name is not part of its type.</p>\n</blockquote>\n<p>例如，以下函数的类型是 bool (const string &amp;, const string &amp;)</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 比较两个 string 对象的长度</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">lengthCompare</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>要想声明一个可以指向该函数的指针，只需要用指针替换函数名即可：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//pf 指向一个函数，该函数的参数是两个 const string 的引用，返回值是 bool 类型</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>针对 bool (*pf)(const string &amp;, const string &amp;) 的分析逻辑：</p>\n<ul>\n<li>pf 前面有个 * ，表示 pf 是指针</li>\n<li>右侧是形参列表，表示 pf 指向的是函数</li>\n<li>再观察左侧，发现函数的返回类型是布尔值</li>\n<li>因此，pf 就是一个指向函数的指针，其中该函数的参数是两个 const string 的引用，返回值是 bool 类型</li>\n</ul>\n<blockquote>\n<p>*pf 两端的括号必不可少，如果不写这对括号（即： <code>bool *pf(const string &amp;, const string &amp;);</code>  ），pf 将是一个返回类型为 bool * 的函数</p>\n</blockquote>\n<h2 id=\"使用函数指针\"><a class=\"anchor\" href=\"#使用函数指针\">#</a> 使用函数指针</h2>\n<p>当我们把函数名作为一个值使用时，该函数自动地转换成指针</p>\n<p>例如，按照如下形式我们可以将函数 lengthCompare 的地址赋给 pf</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pf <span class=\"token operator\">=</span> lengthCompare<span class=\"token punctuation\">;</span>  <span class=\"token comment\">//pf 指向名为 lengthCompare 的函数</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>pf <span class=\"token operator\">=</span> <span class=\"token operator\">&amp;</span>lengthCompare<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 等价的赋值语句（取地址符是可选的）</span></pre></td></tr></table></figure><p>我们可以直接使用指向函数的指针来调用该函数，而无须提前解引用指针</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">bool</span> b1 <span class=\"token operator\">=</span> <span class=\"token function\">pf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"goodbye\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 调用 lengthCompare</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">bool</span> b2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"goodbye\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 等价的调用</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">bool</span> b3 <span class=\"token operator\">=</span> <span class=\"token function\">lengthCompare</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"goodbye\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 等价的调用</span></pre></td></tr></table></figure><p>指向不同函数类型的指针是不可以转换的，但是，我们可以为函数指针赋一个 nullptr 或者值为 0 的整型常量表达式，表示该指针没有指向任何一个函数</p>\n<blockquote>\n<p>There is no conversion between pointers to one function type and pointers to another function type. However, as usual, we can assign nullptr or a zero-valued integer constant expression to a function pointer to indicate that the pointer does not point to any function.</p>\n</blockquote>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>string<span class=\"token double-colon punctuation\">::</span>size_type <span class=\"token function\">sumLength</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">cstringCompare</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span><span class=\"token operator\">*</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>pf <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>              <span class=\"token comment\">// 正确：pf 不指向任何函数</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>pf <span class=\"token operator\">=</span> sumLength<span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 错误：返回类型不匹配</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>pf <span class=\"token operator\">=</span> cstringCompare<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：形参类型不匹配</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>pf <span class=\"token operator\">=</span> lengthCompare<span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 正确：函数和指针的类型精确匹配</span></pre></td></tr></table></figure><h2 id=\"重载函数的指针\"><a class=\"anchor\" href=\"#重载函数的指针\">#</a> 重载函数的指针</h2>\n<p>如果定义了指向重载函数的指针，编译器通过指针类型决定选用哪个函数，指针类型必须与重载函数中的某一个精确匹配</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">ff</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">ff</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> ff<span class=\"token punctuation\">;</span>  <span class=\"token comment\">//pf1 指向 ff (unsigned)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> ff<span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 错误：没有任何一个 ff 与该形参列表匹配</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">double</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf3<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> ff<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：ff 和 pf3 的返回类型不匹配</span></pre></td></tr></table></figure><h2 id=\"函数指针形参\"><a class=\"anchor\" href=\"#函数指针形参\">#</a> 函数指针形参</h2>\n<p>类似于数组，我们不能定义函数类型的形参，但是，<strong>可以将指向函数的指针作为形参</strong></p>\n<p>我们可以定义一个类似于函数类型的形参，它会自动地转换成指向函数的指针（类似于 <strong>数组形参</strong> ）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 第三个形参是函数类型，它会自动地转换成指向函数的指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">useBigger</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>               <span class=\"token keyword\">bool</span> <span class=\"token function\">pf</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">// 等价的声明：显式地将形参定义成指向函数的指针</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">useBigger</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s1<span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span>s2<span class=\"token punctuation\">,</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>               <span class=\"token keyword\">bool</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>pf<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>如果我们直接将函数作为实参使用，它会自动转换成指针</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 自动将函数 lengthCompare 转换成指向该函数的指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">useBigger</span><span class=\"token punctuation\">(</span>s1<span class=\"token punctuation\">,</span> s2<span class=\"token punctuation\">,</span> lengthCompare<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>由于直接将函数指针类型作为形参（例如，useBigger 的声明语句中的第三个形参）会显得冗长，可以使用 类型别名 和 decltype 来简化函数指针的代码</p>\n<p>例如：首先使用 typedef 和 decltype 来定义自己的函数类型和函数指针类型</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// Func 和 Func2 是函数类型</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">bool</span> <span class=\"token function\">Func</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 函数类型</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">decltype</span><span class=\"token punctuation\">(</span>lengthCompare<span class=\"token punctuation\">)</span> Func2<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 函数类型的等价声明</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">// FuncP 和 FuncP2 是指向函数的指针</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">bool</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>FuncP<span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 函数指针类型</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">decltype</span><span class=\"token punctuation\">(</span>lengthCompare<span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span>FuncP2<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 函数指针类型的等价声明</span></pre></td></tr></table></figure><blockquote>\n<p>注意：decltype 返回的是函数类型，不会将函数类型自动转换成指针类型，所以需要再加上  <code>*</code>  才能得到指针</p>\n</blockquote>\n<p>然后重新声明 useBigger 函数：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">//useBigger 的等价声明，其中使用了类型别名</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">useBigger</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> Func<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">useBigger</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> FuncP2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这两个声明语句声明的是同一个函数，在第一条语句中，编译器自动地将 Func 表示的函数类型转换成指针</p>\n<h2 id=\"返回指向函数的指针\"><a class=\"anchor\" href=\"#返回指向函数的指针\">#</a> 返回指向函数的指针</h2>\n<p>类似于数组，我们不能返回一个函数，但是，<strong>可以返回指向函数类型的指针</strong></p>\n<p>由于编译器不会自动将函数返回类型当成对应的指针类型处理，我们必须显式地将返回类型写成指针形式</p>\n<p>声明一个返回函数指针的函数，最直接的办法是（类似于 <strong>返回数组指针</strong> ）：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token function\">f1</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>按照由内向外的顺序阅读这条声明语句：</p>\n<ul>\n<li>f1 有形参列表，所以 f1 是一个函数</li>\n<li>f1 前面有 * ，所以 f1 返回的是一个指针</li>\n<li>进一步观察发现，指针所指向的类型为 int (int*, int) ，其包含形参列表，因此，该指针指向的是一个返回类型为 int 的函数</li>\n</ul>\n<p>声明一个返回函数指针的函数，最简单的办法是使用类型别名：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">using</span> F <span class=\"token operator\">=</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">// F 是函数类型</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> PF <span class=\"token operator\">=</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// PF 是函数指针类型</span></pre></td></tr></table></figure><p>必须时刻注意的是，和函数类型的形参不一样，返回类型不会自动地转换成指针，因此，我们必须显式地将返回类型指定为指针</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>PF <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：PF 是指向函数的指针，f1 返回指向函数的指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>F <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 错误：F 是函数类型，f1 不能返回一个函数</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>F <span class=\"token operator\">*</span><span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：将函数返回类型显式地指定为指向函数的指针</span></pre></td></tr></table></figure><p>此外，我们也可以使用尾置返回类型的方式来声明一个返回函数指针的函数（可参考 <strong>使用尾置返回类型</strong> ）：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">auto</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token keyword\">int</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span><span class=\"token operator\">*</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h2 id=\"将-auto-和-decltype-用于函数指针类型\"><a class=\"anchor\" href=\"#将-auto-和-decltype-用于函数指针类型\">#</a> 将 auto 和 decltype 用于函数指针类型</h2>\n<p>如果我们明确知道返回的函数是哪一个，可以使用 decltype 关键字将返回类型声明为 函数指针类型</p>\n<p>例如，假定有两个函数，它们的返回类型都是 string::size_type ，并且各有两个 const string&amp; 类型的形参</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string<span class=\"token double-colon punctuation\">::</span>size_type <span class=\"token function\">sumLength</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>string<span class=\"token double-colon punctuation\">::</span>size_type <span class=\"token function\">largerLength</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">const</span> string<span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>此时，我们可以编写第三个函数，它接受一个 string 类型的参数，返回一个指针，该指针指向前两个函数中的某一个</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 根据其形参的取值，getFcn 函数返回指向 sumLength 或者 largerLength 的指针</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">decltype</span><span class=\"token punctuation\">(</span>sumLength<span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span><span class=\"token function\">getFcn</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> string <span class=\"token operator\">&amp;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>注意：<strong> <code>decltype</code>  并不负责把函数类型转换成对应的指针</strong>，所以 decltype 的结果是个函数类型，因此，我们显式地加上  <code>*</code>  以表明我们需要返回指针而不是函数本身</p>\n<h1 id=\"术语表\"><a class=\"anchor\" href=\"#术语表\">#</a> 术语表</h1>\n<p><strong>二义性调用（ambiguous call）</strong> ：是一种编译时发生的错误。造成二义性调用的原因：在函数匹配时，两个或多个函数提供的匹配一样好，编译器找不到唯一的最佳匹配</p>\n<p><strong>实参（argument）</strong> ：函数调用时提供的值，用于初始化函数形参</p>\n<p><strong>Assert</strong> ：是一个预处理宏，作用于一条表示条件的表达式</p>\n<ul>\n<li>当未定义预处理变量 NDEBUG 时，assert 对条件求值</li>\n<li>如果 assert 的条件为假，输出一条错误信息并终止当前程序的执行</li>\n</ul>\n<p><strong>自动对象（automatic object）</strong> ：仅存在于函数执行过程中的对象</p>\n<ul>\n<li>当程序的控制流经过此类对象的定义语句时，创建该对象</li>\n<li>当到达了定义所在的块的末尾时，销毁该对象</li>\n</ul>\n<p><strong>最佳匹配（best match）</strong> ：从一组重载函数中为调用选出的一个函数。最佳匹配（如果存在的话）至少在一个实参上比其他所有可行函数更优，同时，在其他实参的匹配上不会更差</p>\n<p><strong>传引用调用（call by reference）</strong> ：对引用传递的函数的调用</p>\n<p><strong>传值调用（call by value）</strong> ：对值传递的函数的调用</p>\n<p><strong>候选函数（candidate function）</strong> ：解析某次函数调用时考虑的一组函数。候选函数的名字应该与函数调用使用的名字一致，并且在调用点候选函数的声明在作用域之内</p>\n<p><strong>constexpr</strong> ：可以返回常量表达式的函数。一个 constexpr 函数被隐式地声明成内联函数</p>\n<p><strong>默认实参（default argument）</strong> ：当调用缺少了某个实参时，为该实参指定的默认值</p>\n<p><strong>可执行文件（executable file）</strong> ；是操作系统能够执行的文件，包含着与程序有关的代码</p>\n<p><strong>函数（function）</strong> ：可调用的计算单元</p>\n<p><strong>函数体（function body）</strong> ：是一个块，用于定义函数所执行的操作</p>\n<p><strong>函数匹配（function matching）</strong> ：编译器解析重载函数调用的过程，在此过程中，实参与每个重载函数的形参列表逐一比较</p>\n<p><strong>函数原型（function prototype）</strong> ：函数的声明，包含函数名字、返回类型和形参类型。要想调用某函数，在调用点之前必须声明该函数的原型</p>\n<p><strong>隐藏名字（hidden name）</strong> ：某个作用域内声明的名字会隐藏掉外层作用域中声明的同名实体</p>\n<p><strong>initializer_list</strong> ：是一个标准类，表示的是一组花括号包围的类型相同的对象，对象之间以逗号隔开</p>\n<p><strong>内联函数（inline function）</strong> ：请求编译器在可能的情况下在调用点展开函数。内联函数可以避免常见的函数调用开销</p>\n<p><strong>链接（link）</strong> ：是一个编译过程，负责把若干对象文件链接起来形成可执行程序</p>\n<p><strong>局部静态对象（local static object）</strong> ：它的值在函数调用结束后仍然存在。在第一次使用局部静态对象前创建并初始化它，当程序结束时局部静态对象才被销毁</p>\n<p><strong>局部变量（local variable）</strong> ：定义在块中的变量</p>\n<p><strong>无匹配（no match）</strong> ：是一种编译时发生的错误，原因是在函数匹配过程中所有函数的形参都不能与调用提供的实参匹配</p>\n<p><strong>对象代码（object code）</strong> ：编译器将我们的源代码转换成对象代码格式</p>\n<p><strong>对象文件（object file）</strong> ：编译器根据给定的源文件生成的保存对象代码的文件。一个或多个对象文件经过链接生成可执行文件</p>\n<p><strong>对象生命周期（object lifetime）</strong> ：每个对象都有相应的生命周期</p>\n<ul>\n<li>块内定义的非静态对象的生命周期从它的定义开始，到定义所在的块末尾为止</li>\n<li>程序启动后创建全局对象</li>\n<li>程序控制流经过局部静态对象的定义时创建该局部静态对象</li>\n<li>当 main 函数结束时销毁全局对象和局部静态对象</li>\n</ul>\n<p><strong>重载确定（overload resolution）</strong> ：参见函数匹配</p>\n<p><strong>重载函数（overloaded function）</strong> ：函数名与其他函数相同的函数。多个重载函数必须在形参数量或形参类型上有所区别</p>\n<p><strong>形参（parameter）</strong> ：在函数的形参列表中声明的局部变量。用实参初始化形参</p>\n<p><strong>引用传递（pass by reference）</strong> ：描述如何将实参传递给引用类型的形参。引用形参和其他形式的引用工作机理类似，形参被绑定到相应的实参上</p>\n<p><strong>值传递（pass by value）</strong> ：描述如何将实参传递给非引用类型的形参。非引用类型的形参实际上是相应实参值的一个副本</p>\n<p><strong>预处理宏（preprocessor macro）</strong> ：类似于内联函数的一种预处理功能。除了 assert 之外，现代 C++ 程序很少再使用预处理宏了</p>\n<p><strong>递归循环（recursion loop）</strong> ：描述某个递归函数没有终止条件，因而不断调用自身直至耗尽程序栈空间的过程</p>\n<p><strong>递归函数（recursive function）</strong> ：直接或间接调用自身的函数</p>\n<p><strong>返回类型（return type）</strong> ：是函数声明的一部分，用于指定函数返回值的类型</p>\n<p><strong>分离式编译（separate compilation）</strong> ：把一个程序分割成多个独立源文件的能力</p>\n<p><strong>尾置返回类型（trailing return type）</strong> ：在参数列表后面指定的返回类型</p>\n<p><strong>可行函数（viable function）</strong> ：是候选函数的子集。可行函数能匹配本次调用，它的形参数量与调用提供的实参数量相等，并且每个实参类型都能转换成相应的形参类型</p>\n<p><strong>() 运算符（ () operator）</strong> ：调用运算符，用于执行某函数。括号前面是函数名或函数指针，括号内是以逗号隔开的实参列表（可能为空）</p>\n<p>参考：C++ Primer 中文版（第 5 版）</p>\n",
            "tags": [
                "C++"
            ]
        },
        {
            "id": "https://jiankychen.github.io/cpp-statement.html",
            "url": "https://jiankychen.github.io/cpp-statement.html",
            "title": "C++ 语句",
            "date_published": "2022-09-12T02:23:26.000Z",
            "content_html": "<h1 id=\"语句与语句作用域\"><a class=\"anchor\" href=\"#语句与语句作用域\">#</a> 语句与语句作用域</h1>\n<h2 id=\"简单语句\"><a class=\"anchor\" href=\"#简单语句\">#</a> 简单语句</h2>\n<p>表达式语句（expression statement）：执行表达式并丢弃掉求值结果</p>\n<p>空语句（null statement）：空语句中只含有一个单独的分号</p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 重复读入数据直至到达文件末尾或某次输入的值等于 sought</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> s <span class=\"token operator\">&amp;&amp;</span> s <span class=\"token operator\">!=</span> sought<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token punctuation\">;</span> <span class=\"token comment\">// 空语句</span></pre></td></tr></table></figure><blockquote>\n<p>使用空语句时应该加上注释，从而令读这段代码的人知道该语句是有意省略的</p>\n</blockquote>\n<p><strong>别漏写分号，也别多写分号</strong>：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>ival <span class=\"token operator\">=</span> v1 <span class=\"token operator\">+</span> v2<span class=\"token punctuation\">;</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 正确：第二个分号表示一条多余的空语句</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>iter <span class=\"token operator\">!=</span> svec<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">;</span> <span class=\"token comment\">//while 循环体是那条空语句（无休止循环）</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token operator\">++</span>iter<span class=\"token punctuation\">;</span>                  <span class=\"token comment\">// 递增运算不输于循环的一部分</span></pre></td></tr></table></figure><p><strong>复合语句</strong>（compound statement）是指用花括号括起来的（可能为空的）语句和声明的序列，复合语句也被称作 <strong>块</strong>（block）</p>\n<p>一个块就是一个作用域，在块中引入的名字只能在块内部以及嵌套在块中的子块里访问</p>\n<blockquote>\n<p><strong>块不以分号作为结束</strong></p>\n</blockquote>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>val <span class=\"token operator\">&lt;=</span> <span class=\"token number\">10</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    sum <span class=\"token operator\">+=</span> val<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token operator\">++</span>val<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>空块：是指内部没有任何语句的一对花括号。空块的作用等价于空语句</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> s <span class=\"token operator\">&amp;&amp;</span> s <span class=\"token operator\">!=</span> sought<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token punctuation\">&#123;</span> <span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 空块</span></pre></td></tr></table></figure><h2 id=\"语句作用域\"><a class=\"anchor\" href=\"#语句作用域\">#</a> 语句作用域</h2>\n<p>可以在 if 、switch 、while 和 for 语句的控制结构内定义变量。但是需要注意，定义在控制结构中的变量只在相应语句的内部可见，一旦语句结束，变量也就超出其作用范围了</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token function\">get_num</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 每次迭代时创建并初始化 i</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> i <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 错误：在循环外部无法访问 i</span></pre></td></tr></table></figure><p>如果其他代码也需要访问控制变量，则变量必须定义在语句的外部</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 寻找第一个负值元素</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">auto</span> beg <span class=\"token operator\">=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 注意要初始化</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>beg <span class=\"token operator\">!=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">*</span>beg <span class=\"token operator\">>=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token operator\">++</span>beg<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>beg <span class=\"token operator\">==</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// 此时我们知道 v 中的所有元素都大于等于 0</span></pre></td></tr></table></figure><h1 id=\"条件语句\"><a class=\"anchor\" href=\"#条件语句\">#</a> 条件语句</h1>\n<p>C++ 语言提供了两种按条件执行的语句</p>\n<ul>\n<li>if 语句：根据条件决定控制流</li>\n<li>switch 语句：计算一个整型表达式的值，然后根据这个值从几条执行路径中选择一条</li>\n</ul>\n<h2 id=\"if-语句\"><a class=\"anchor\" href=\"#if-语句\">#</a> if 语句</h2>\n<p>简单 if 语句的语法形式：</p>\n<pre><code>if (condition)\n    statement\n</code></pre>\n<p>if else 语句的形式：</p>\n<pre><code>if (condition)\n    statement\nelse\n    statement2\n</code></pre>\n<p>如果 condition 为真，执行 statement 。当 statement 执行完成后，程序继续执行 if 语句后面的其他语句</p>\n<p>如果 condition 为假，跳过 statement 。对于简单 if 语句来说，程序继续执行 if 语句后面的其他语句；对于 if else 语句来说，执行 statement2</p>\n<p>注意：在这两个版本的 if 语句中，condition 都必须用圆括号包围起来</p>\n<blockquote>\n<p>condition 可以是一个表达式，也可以是一个初始化了的变量声明。不管是表达式还是变量，其类型都必须能转换成布尔类型</p>\n</blockquote>\n<h3 id=\"嵌套-if-语句\"><a class=\"anchor\" href=\"#嵌套-if-语句\">#</a> 嵌套 if 语句</h3>\n<p>例如：把数字形式表示的成绩转换成字母形式，并在合格的成绩后面添加一个加号或减号（如果成绩的末位是 8 或者 9 ，添加一个加号；如果末位是 0 、1 或 2 ，添加一个减号）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> scores <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token string\">\"F\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"D\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"C\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"B\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"A\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"A++\"</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>string lettergrade<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grade <span class=\"token operator\">&lt;</span> <span class=\"token number\">60</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 成绩不合格，对应的字母是 F</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    lettergrade <span class=\"token operator\">=</span> scores<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">else</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    lettergrade <span class=\"token operator\">=</span> scores<span class=\"token punctuation\">[</span><span class=\"token punctuation\">(</span>grade <span class=\"token operator\">-</span> <span class=\"token number\">50</span><span class=\"token punctuation\">)</span><span class=\"token operator\">/</span><span class=\"token number\">10</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 获得字母形式的成绩</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grade <span class=\"token operator\">!=</span> <span class=\"token number\">100</span><span class=\"token punctuation\">)</span>  <span class=\"token comment\">// 只要不是 A++（100 分），就考虑添加加号或者减号</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grade <span class=\"token operator\">%</span> <span class=\"token number\">10</span> <span class=\"token operator\">></span> <span class=\"token number\">7</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            lettergrade <span class=\"token operator\">+=</span> <span class=\"token char\">'+'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 末尾是 8 或者 9 的成绩添加一个加号</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grade <span class=\"token operator\">%</span> <span class=\"token number\">10</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            lettergrade <span class=\"token operator\">+=</span> <span class=\"token char\">'-'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 末尾是 0 、1 或者 2 的成绩添加一个减号</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>注意使用花括号</p>\n</blockquote>\n<h3 id=\"悬垂-else\"><a class=\"anchor\" href=\"#悬垂-else\">#</a> 悬垂 else</h3>\n<p>当一个 if 语句嵌套在另一个 if 语句内部时，很可能 if 分支会多于 else 分支。此时，我们怎么知道某个给定的 else 是和哪个 if 匹配呢？</p>\n<p>这个问题通常称作 <strong>悬垂 else</strong>（dangling else）</p>\n<p>C++ 规定 else 与离它最近的尚未匹配的 if 匹配</p>\n<blockquote>\n<p>In C++, the ambiguity is resolved by specifying that each  <code>else</code>  is matched with the closest preceding unmatched  <code>if</code> .</p>\n</blockquote>\n<h3 id=\"使用花括号控制执行路径\"><a class=\"anchor\" href=\"#使用花括号控制执行路径\">#</a> 使用花括号控制执行路径</h3>\n<p>要想使 else 分支和外层的 if 语句匹配起来，可以在内层 if 语句的两端加上花括号，使其成为一个块</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 末位是 8 或者 9 的成绩添加一个加号；如果末位是 0 、1 或 2 的成绩添加一个减号</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grade <span class=\"token operator\">%</span> <span class=\"token number\">10</span> <span class=\"token operator\">>=</span> <span class=\"token number\">3</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grade <span class=\"token operator\">%</span> <span class=\"token number\">10</span> <span class=\"token operator\">></span> <span class=\"token number\">7</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        lettergrade <span class=\"token operator\">+=</span> <span class=\"token char\">'+'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 末尾是 8 或者 9 的成绩添加一个加号</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">else</span>                  <span class=\"token comment\">// 花括号强迫 else 与外层 if 匹配</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    lettergrade <span class=\"token operator\">+=</span> <span class=\"token char\">'-'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 末位是 0 、1 或 2 的成绩添加一个减号</span></pre></td></tr></table></figure><h2 id=\"switch-语句\"><a class=\"anchor\" href=\"#switch-语句\">#</a> switch 语句</h2>\n<p>switch 语句（switch statement）提供了一条便利的途径使得我们能够在若干固定选项中做出选择</p>\n<p>例如，利用 switch 语句统计五个元音字母在文本中出现的次数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 为每个元音字母初始化其计数值</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">unsigned</span> aCnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> eCnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> iCnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> oCnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> uCnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">char</span> ch<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> ch<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 如果 ch 是元音字母，将其对应的计数值加 1</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>ch<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">case</span> <span class=\"token char\">'a'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token operator\">++</span>aCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">case</span> <span class=\"token char\">'e'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            <span class=\"token operator\">++</span>eCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">case</span> <span class=\"token char\">'i'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token operator\">++</span>iCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">case</span> <span class=\"token char\">'o'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            <span class=\"token operator\">++</span>oCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">case</span> <span class=\"token char\">'u'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            <span class=\"token operator\">++</span>uCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token comment\">// 打印结果</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"Number of vowel a: \\t\"</span> <span class=\"token operator\">&lt;&lt;</span> aCnt <span class=\"token operator\">&lt;&lt;</span> <span class=\"token char\">'\\n'</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>     <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"Number of vowel e: \\t\"</span> <span class=\"token operator\">&lt;&lt;</span> eCnt <span class=\"token operator\">&lt;&lt;</span> <span class=\"token char\">'\\n'</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>     <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"Number of vowel i: \\t\"</span> <span class=\"token operator\">&lt;&lt;</span> iCnt <span class=\"token operator\">&lt;&lt;</span> <span class=\"token char\">'\\n'</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>     <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"Number of vowel o: \\t\"</span> <span class=\"token operator\">&lt;&lt;</span> oCnt <span class=\"token operator\">&lt;&lt;</span> <span class=\"token char\">'\\n'</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>     <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"Number of vowel u: \\t\"</span> <span class=\"token operator\">&lt;&lt;</span> uCnt <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>switch 语句首先对括号里的表达式求值，该表达式（可以是一个初始化的变量声明）紧跟在关键字 switch 的后面。表达式的值转换成整数类型，然后与每个 case 标签的值比较</p>\n<p>如果表达式和某个 case 标签的值匹配成功，程序从该标签之后的第一条语句开始执行，直到到达了 switch 的结尾或者是遇到一条 break 语句为止</p>\n<blockquote>\n<p>break 语句的作用是中断当前的控制流。此例中，break 语句将控制权转移到 switch 语句外面</p>\n</blockquote>\n<p>如果 switch 语句的表达式和所有 case 都没有匹配上，将直接跳转到 switch 结构之后的第一条语句</p>\n<p>case 关键字和它对应的值一起被称为 <strong>case 标签</strong>（case label）</p>\n<p>case 标签必须是整型常量表达式</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">char</span> ch <span class=\"token operator\">=</span> <span class=\"token function\">getVal</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> ival <span class=\"token operator\">=</span> <span class=\"token number\">42</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">switch</span><span class=\"token punctuation\">(</span>ch<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token number\">3.14</span><span class=\"token operator\">:</span> <span class=\"token comment\">// 错误：case 标签不是一个整数</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">case</span> ival<span class=\"token operator\">:</span> <span class=\"token comment\">// 错误：case 标签不是一个常量</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token comment\">// ...</span></pre></td></tr></table></figure><blockquote>\n<p>任何两个 case 标签的值不能相同，否则就会引发错误</p>\n</blockquote>\n<p>default 也是一种特殊的 case 标签</p>\n<h3 id=\"switch-内部的控制流\"><a class=\"anchor\" href=\"#switch-内部的控制流\">#</a> switch 内部的控制流</h3>\n<p>如果某个 case 标签匹配成功，将从该标签开始往后顺序执行所有 case 分支，除非程序显式地中断了这一过程，否则，执行到 switch 的结尾处才会停下来</p>\n<p>要想避免执行后续 case 分支的代码，我们必须显式地告诉编译器终止执行过程。大多数情况下，在下一个 case 标签之前应该有一条 break 语句</p>\n<p>然而，由于每个 case 标签只能对应一个值，有时候我们希望两个或更多个值共享同一组操作。此时，我们就故意省略掉 break 语句，使得程序能够连续执行若干个 case 标签</p>\n<p>例如：统计所有元音字母出现的总次数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">unsigned</span> vowelCnt <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// ...</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>ch<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'a'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'e'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'i'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'o'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'u'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>       <span class=\"token operator\">++</span>vowelCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>       <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>C++ 程序的形式比较自由，所以 case 标签之后不一定非得换行。把几个 case 标签写在一行里，强调这些 case 代表的是某个范围内的值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>ch<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 另一种合法的书写形式</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'a'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'e'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'i'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'o'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'u'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>       <span class=\"token operator\">++</span>vowelCnt<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>       <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>一般不要省略 case 分支最后的 break 语句。如果没写 break 语句，最好加一段注释说清楚程序的逻辑</p>\n</blockquote>\n<blockquote>\n<p>尽管 switch 语句不是非得在最后一个标签后面写上 break ，但是为了安全起见，最好这么做。因为这样的话，即使以后再增加新的 case 分支，也不用再在前面补充 break 语句了</p>\n</blockquote>\n<h3 id=\"default-标签\"><a class=\"anchor\" href=\"#default-标签\">#</a> default 标签</h3>\n<p>如果没有任何一个 case 标签能匹配上 switch 表达式的值，程序将执行紧跟在 <strong>default 标签</strong>（default label）后面的语句</p>\n<p>例如，可以增加一个计数值来统计非元音字母的数量</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>ch<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'a'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'e'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'i'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'o'</span><span class=\"token operator\">:</span> <span class=\"token keyword\">case</span> <span class=\"token char\">'u'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token operator\">++</span>vowelCnt<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 元音字母的数量</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">default</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token operator\">++</span>otherCnt<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 非元音字母的数量</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><blockquote>\n<p>即使不准备在 default 标签下做任何工作，定义一个 default 标签也是有用的。其目的在于告诉程序的读者，我们已经考虑到了默认的情况，只是目前什么也没做</p>\n</blockquote>\n<p>标签不应该孤零零地出现，它后面必须跟一条语句或者另外一个 case 标签。如果 switch 结构以一个空的 default 标签作为结束，则该 default 标签后面必须跟一条空语句或一个空块</p>\n<h1 id=\"迭代语句\"><a class=\"anchor\" href=\"#迭代语句\">#</a> 迭代语句</h1>\n<p>迭代语句通常称为循环，它重复执行操作直到满足某个条件才停下来</p>\n<ul>\n<li>while 和 for 语句在执行循环体之前检查条件</li>\n<li>do while 语句先执行循环体，然后再检查条件</li>\n</ul>\n<h2 id=\"while-语句\"><a class=\"anchor\" href=\"#while-语句\">#</a> while 语句</h2>\n<p>只要条件为真，while 语句（while statement）就重复地执行循环体</p>\n<p>语法形式为：</p>\n<pre><code>while (condition)\n    statement\n</code></pre>\n<p>condition 不能为空，如果 condition 第一次求值就得 false ， statement 一次都不执行</p>\n<p>condition 可以是一个表达式或者是一个带初始化的变量声明</p>\n<p><strong>定义在 while 条件部分或者 while 循环体内的变量，每次迭代都经历从创建到销毁的过程</strong></p>\n<p>当不确定到底要迭代多少次时，使用 while 循环比较合适</p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> v<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 重复读入数据，直至到达文件末尾或者遇到其他输入问题</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> i<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    v<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">// 寻找第一个负值元素</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">auto</span> beg <span class=\"token operator\">=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>beg <span class=\"token operator\">!=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">*</span>beg <span class=\"token operator\">>=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token operator\">++</span>beg<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>beg <span class=\"token operator\">==</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token comment\">// 此时我们知道 v 中的所有元素都大于等于 0</span></pre></td></tr></table></figure><h2 id=\"传统的-for-语句\"><a class=\"anchor\" href=\"#传统的-for-语句\">#</a> 传统的 for 语句</h2>\n<p>for 语句的语法形式：</p>\n<pre><code>for (init-statement; condition; expression)\n    statement\n</code></pre>\n<p>关键字 for 及括号里的部分称为 for 语句头</p>\n<p>init-statement 必须是以下三种形式中的一种：声明语句、表达式语句或者空语句。因为这些语句都以分号作为结束，for 语句的语法形式也可以看作：</p>\n<pre><code>for (initializer; condition; expression)\n    statement\n</code></pre>\n<p>其中：</p>\n<ul>\n<li>init-statement 负责初始化一个值，这个值将随着循环的进行而改变</li>\n<li>condition 作为循环控制的条件，只要 condition 为真，就执行一次 statement 。如果 condition 第一次的求值结果就是 false ，则 statement 一次也不会执行</li>\n<li>expression 负责在每次循环迭代之后修改 init-statement 初始化的变量，这个变量正好就是 condition 检查的对象</li>\n<li>statement 可以是一条单独的语句也可以是一条复合语句</li>\n</ul>\n<blockquote>\n<p>for 语句头中定义的对象只在 for 循环体内可见</p>\n</blockquote>\n<h3 id=\"for-语句头中的多重定义\"><a class=\"anchor\" href=\"#for-语句头中的多重定义\">#</a> for 语句头中的多重定义</h3>\n<p>init-statement 可以定义多个对象，但只能有一条声明语句，因此，所有变量的基础类型必须相同</p>\n<p>例如：下列代码在 init-statement 里同时定义了索引 i 和循环控制变量 sz</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 记录下 v 的大小，当到达原来的最后一个元素后结束循环</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">decltype</span><span class=\"token punctuation\">(</span>v<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> sz <span class=\"token operator\">=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">!=</span> sz<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    v<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>v<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"省略-for-语句头的某些部分\"><a class=\"anchor\" href=\"#省略-for-语句头的某些部分\">#</a> 省略 for 语句头的某些部分</h3>\n<p>for 语句头能省略掉 init-statement 、condition 和 expression 中的任何一个（或者全部）</p>\n<p>如果无须初始化，则我们可以使用一条空语句作为 init-statement ，例如</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">auto</span> beg <span class=\"token operator\">=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span> <span class=\"token comment\">/* 空语句 */</span><span class=\"token punctuation\">;</span> beg <span class=\"token operator\">!=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">*</span>beg <span class=\"token operator\">>=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>beg<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token punctuation\">;</span> <span class=\"token comment\">// 什么也不做</span></pre></td></tr></table></figure><p>注意，分号必须保留，以表明我们省略掉了 init-statement 。说得更准确一点，分号表示的是一个空的 init-statement</p>\n<p>省略 condition 的效果等价于在条件部分写了一个 true 。因为条件的值永远是 true ，所以在循环体内必须有语句负责退出循环，否则循环就会无休止地执行下去</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">/* 条件为空 */</span> <span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 对 i 进行处理，循环内部的代码必须能够终止迭代过程</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>我们也能省略掉 for 语句头中的 expression ，但是在这样的循环中就要求条件部分或者循环体必须改变迭代变量的值</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> v<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">;</span> cin <span class=\"token operator\">>></span> i<span class=\"token punctuation\">;</span> <span class=\"token comment\">/* 表达式为空 */</span> <span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>   v<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>因为条件部分能改变 i 的值，所以这个循环无须表达式部分。其中，条件部分不断检查输入流的内容，只要读取完所有的输入或者遇到一个输入错误就终止循环</p>\n<h2 id=\"范围-for-语句\"><a class=\"anchor\" href=\"#范围-for-语句\">#</a> 范围 for 语句</h2>\n<p>C++ 11 新标准引入了一种更简单的 for 语句，这种语句可以遍历容器或其他序列的所有元素</p>\n<p>范围 for 语句（range for statement）的语法形式：</p>\n<pre><code>for (declaration : expression)\n    statement\n</code></pre>\n<p>expression 表示的必须是一个序列，比如用花括号括起来的初始值列表、数组或者 vector 或 string 等类型的对象，这些类型的共同特点是拥有能返回迭代器的 begin 和 end 成员</p>\n<p>declaration 定义一个变量，序列中的每个元素都得能转换成该变量的类型</p>\n<ul>\n<li>确保类型相容最简单的办法是使用 auto 类型说明符</li>\n<li>如果需要对序列中的元素执行写操作，循环变量必须声明成引用类型</li>\n</ul>\n<p>每次迭代都会重新定义循环控制变量，并将其初始化成序列中的下一个值，之后才会执行 statement</p>\n<p>statement 可以是一条单独的语句也可以是一个块</p>\n<p>所有元素都处理完毕后循环终止</p>\n<p>例如：把 vector 对象中的每个元素都翻倍</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> v <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">,</span><span class=\"token number\">7</span><span class=\"token punctuation\">,</span><span class=\"token number\">8</span><span class=\"token punctuation\">,</span><span class=\"token number\">9</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">// 范围变量必须是引用类型，这样才能对元素执行写操作</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> <span class=\"token operator\">&amp;</span>r <span class=\"token operator\">:</span> v<span class=\"token punctuation\">)</span>   <span class=\"token comment\">// 对于 v 中的每一个元素</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    r <span class=\"token operator\">*=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>         <span class=\"token comment\">// 将 v 中每个元素的值翻倍</span></pre></td></tr></table></figure><p>其等价于</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> beg <span class=\"token operator\">=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> end <span class=\"token operator\">=</span> v<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> beg <span class=\"token operator\">!=</span> end<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>beg<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">auto</span> <span class=\"token operator\">&amp;</span>r <span class=\"token operator\">=</span> <span class=\"token operator\">*</span>beg<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    r <span class=\"token operator\">*=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>不能通过范围 for 语句增加 vector 对象（或者其他容器）的元素：因为在范围 for 语句中，预存了 end () 的值。一旦在序列中添加（删除）元素，end 函数的值就可能变得无效了</p>\n<h2 id=\"do-while-语句\"><a class=\"anchor\" href=\"#do-while-语句\">#</a> do while 语句</h2>\n<p>do while 语句（do while statement）和 while 语句非常相似，唯一的区别是，do while 语句先执行循环体后检查条件</p>\n<p>即，不管条件的值如何，do while 语句都至少执行一次循环</p>\n<p>do while 语句的语法形式：</p>\n<pre><code>do\n    statement\nwhile (condition);\n</code></pre>\n<p><strong>do while 语句应该在后面用一个分号表示语句结束</strong></p>\n<p>在 do while 语句中，首先执行一次 statement 然后才求 condition 的值（ condition 不能为空）。如果 condition 的值为假，循环终止；否则，重复循环过程</p>\n<p>condition 使用的变量必须定义在循环体之外</p>\n<p>例如，可以使用 do while 循环（不断地）执行加法运算</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 不断提示用户输入一对数，然后求其和</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>string rsp<span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 作为循环的条件，不能定义在 do 的内部</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">do</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"please enter two values: \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> val1 <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> val2 <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    cin  <span class=\"token operator\">>></span> val1 <span class=\"token operator\">>></span> val2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"The sum of \"</span> <span class=\"token operator\">&lt;&lt;</span> val1 <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" and \"</span> <span class=\"token operator\">&lt;&lt;</span> val2</pre></td></tr><tr><td data-num=\"8\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" = \"</span> <span class=\"token operator\">&lt;&lt;</span> val1 <span class=\"token operator\">+</span> val2 <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"\\n\\n\"</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>         <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"More? Enter yes or no: \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    cin  <span class=\"token operator\">>></span> rsp<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>rsp<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> rsp<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">!=</span> <span class=\"token char\">'n'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>因为 do while 先执行语句（或者块）后判断条件，所以不允许在条件部分定义变量</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">do</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// . . .</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token function\">mumble</span><span class=\"token punctuation\">(</span>foo<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> foo <span class=\"token operator\">=</span> <span class=\"token function\">get_foo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：将变量声明放在了 do while 的条件部分</span></pre></td></tr></table></figure><h1 id=\"跳转语句\"><a class=\"anchor\" href=\"#跳转语句\">#</a> 跳转语句</h1>\n<p>跳转语句用于中断当前的执行过程</p>\n<p>C++ 语言提供了 4 种跳转语句：</p>\n<ul>\n<li>break</li>\n<li>continue</li>\n<li>goto</li>\n<li>return</li>\n</ul>\n<h2 id=\"break-语句\"><a class=\"anchor\" href=\"#break-语句\">#</a> break 语句</h2>\n<p>break 语句（break statement）负责终止离它最近的 <strong>while 、do while 、for 或 switch 语句</strong>，并从这些语句之后的第一条语句开始继续执行</p>\n<p>break 语句只能出现在迭代语句或者 switch 语句内部（包括嵌套在此类循环里的语句或块的内部）。<strong>break 语句的作用范围仅限于最近的循环或者 switch</strong></p>\n<p>例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string buf<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> buf <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>buf<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">switch</span><span class=\"token punctuation\">(</span>buf<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'-'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token comment\">// 处理到第一个空白为止</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> it <span class=\"token operator\">=</span> buf<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span> it <span class=\"token operator\">!=</span> buf<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>it<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>              <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">*</span>it <span class=\"token operator\">==</span> <span class=\"token char\">' '</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>                   <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// #1，离开 for 循环</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>              <span class=\"token comment\">// . . .</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token comment\">//break #1 将控制权转移到这里</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token comment\">// 剩余的 '-' 处理</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// #2，离开 switch 语句</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token keyword\">case</span> <span class=\"token char\">'+'</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token comment\">// . . .</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 结束 switch</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>   <span class=\"token comment\">//break #2 将控制权转移到这里</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// 结束 while</span></pre></td></tr></table></figure><p>标记为 #1 的 break 语句负责终止连字符 case 标签后面的 for 循环。它不但不会终止 switch 语句，甚至连当前的 case 分支也终止不了。接下来，程序继续执行 for 循环之后的第一条语句，这条语句可能接着处理连字符的情况，也可能是另一条用于终止当前分支的 break 语句</p>\n<p>标记为 #2 的 break 语句负责终止 switch 语句，但是不能终止 while 循环。执行完这个 break 后，程序继续执行 while 的条件部分</p>\n<h2 id=\"continue-语句\"><a class=\"anchor\" href=\"#continue-语句\">#</a> continue 语句</h2>\n<p>continue 语句（continue statement）终止最近的循环中的当前迭代并立即开始下一次迭代</p>\n<p><strong>continue 语句只能出现在 for 、while 和 do while 循环的内部</strong>，或者嵌套在此类循环里的语句或块的内部</p>\n<p>和 break 语句类似的是，出现在嵌套循环中的 continue 语句也仅作用于离它最近的循环</p>\n<p>和 break 语句不同的是，只有当 switch 语句嵌套在迭代语句内部时，才能在 switch 里使用 continue （即，continue 对循环起作用，而不对 switch 起作用）</p>\n<p>continue 语句中断当前的迭代，但是仍然继续执行循环</p>\n<ul>\n<li>对于 while 或者 do while 语句来说，继续判断条件的值</li>\n<li>对于传统的 for 循环来说，继续执行 for 语句头的 expression</li>\n<li>对于范围 for 语句来说，用序列中的下一个元素初始化循环控制变量</li>\n</ul>\n<p>例如：从标准输入中读取单词并处理以下画线开头的单词</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>string buf<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> buf <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>buf<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>buf<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">!=</span> <span class=\"token char\">'_'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// get another input</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// still here? the input starts with an underscore; process buf . . .</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"goto-语句\"><a class=\"anchor\" href=\"#goto-语句\">#</a> goto 语句</h2>\n<p>goto 语句（goto statement）的作用：从 goto 语句无条件跳转到同一函数内的另一条语句</p>\n<blockquote>\n<p>不要在程序中使用 goto 语句，因为它使得程序既难理解又难修改</p>\n</blockquote>\n<p>goto 语句的语法形式：</p>\n<pre><code>goto label;\n</code></pre>\n<p>其中，label 是用于标识一条语句的标示符</p>\n<p>带标签语句（labeled statement）是一种特殊的语句，在它之前有一个标示符以及一个冒号，例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>end<span class=\"token operator\">:</span> <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 带标签语句，可以作为 goto 的目标</span></pre></td></tr></table></figure><p>标签标示符独立于变量或其他标示符的名字，因此，标签标示符可以和程序中其他实体的标识符使用同一个名字而不会相互干扰</p>\n<p>goto 语句和控制权转向的那条带标签的语句必须位于同一个函数之内</p>\n<p>和 switch 语句类似，goto 语句也不能将程序的控制权从变量的作用域之外转移到作用域之内：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// . . .</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">goto</span> end<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">int</span> ix <span class=\"token operator\">=</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 错误：goto 语句绕过了一个带初始化的变量定义</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>end<span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token comment\">// 错误：此处的代码需要 ix，但是 goto 语句绕过了它的声明</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    ix <span class=\"token operator\">=</span> <span class=\"token number\">42</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>向后跳过一个已经执行的定义是合法的。跳回到变量定义之前意味着系统将销毁该变量，然后重新创建它。例如：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// backward jump over an initialized variable definition is okay</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>  begin<span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> sz <span class=\"token operator\">=</span> <span class=\"token function\">get_size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>sz <span class=\"token operator\">&lt;=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">goto</span> begin<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>在上面的代码中，goto 语句执行后将销毁 sz 。因为跳回到 begin 的动作跨过了 sz 的定义语句，所以 sz 将重新定义并初始化</p>\n<h1 id=\"try-语句块和异常处理\"><a class=\"anchor\" href=\"#try-语句块和异常处理\">#</a> try 语句块和异常处理</h1>\n<p>异常是指存在于运行时的反常行为，这些行为超出了函数正常功能的范围</p>\n<p>典型的异常包括失去数据库连接以及遇到意外输入等</p>\n<p>异常处理机制包括异常检测和异常处理两个部分</p>\n<p>在 C++ 语言中，异常处理包括：</p>\n<ul>\n<li><strong>throw 表达式</strong>（throw expression）：异常检测部分使用 throw 表达式来表示它遇到了无法处理的问题。通常描述为：throw 引发（raise）了异常</li>\n<li><strong>try 语句块</strong>（try block）：异常处理部分使用 try 语句块处理异常\n<ul>\n<li>try 语句块以关键字 try 开始，并以一个或多个 <strong>catch 子句</strong>（catch clause）结束</li>\n<li>try 语句块中代码抛出的异常通常会被某个 catch 子句处理。catch 子句通常也被称作 <strong>异常处理代码</strong>（exception handler）</li>\n</ul>\n</li>\n<li>一套 <strong>异常类</strong>（exception class）：用于在 throw 表达式和相关的 catch 子句之间传递异常的具体信息</li>\n</ul>\n<h2 id=\"throw-表达式\"><a class=\"anchor\" href=\"#throw-表达式\">#</a> throw 表达式</h2>\n<p>throw 表达式包含关键字 throw 和紧随其后的一个表达式，其中表达式的类型就是抛出的异常类型</p>\n<p>throw 表达式后面通常紧跟一个分号</p>\n<p>例如：在执行两个 Sales_item 对象相加时，需要先检查它们是否是关于同一种书籍的</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Sales_item item1<span class=\"token punctuation\">,</span> item2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>cin <span class=\"token operator\">>></span> item1 <span class=\"token operator\">>></span> item2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">// 首先检查两条数据是否是关于同一种书籍的</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>item1<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> item2<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">throw</span> <span class=\"token function\">runtime_error</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Data must refer to same ISBN\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">// 如果程序执行到这里，则说明两个 ISBN 相同</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>cout <span class=\"token operator\">&lt;&lt;</span> item1 <span class=\"token operator\">+</span> item2 <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>在这段代码中，如果 ISBN 不一样，就会抛出一个异常（该异常是类型 runtime_error 的对象）</p>\n<blockquote>\n<p>类型 runtime_error 是标准库异常类型的一种，定义在 stdexcept 头文件中</p>\n</blockquote>\n<p>抛出异常将终止当前的函数，并把控制权转移给能处理该异常的代码</p>\n<h2 id=\"try-语句块\"><a class=\"anchor\" href=\"#try-语句块\">#</a> try 语句块</h2>\n<p>try 语句块包括关键字 try 以及紧随其后的一个块（花括号括起来的语句序列），其通用语法形式为：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">try</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    program<span class=\"token operator\">-</span>statements</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>exception<span class=\"token operator\">-</span>declaration<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    handler<span class=\"token operator\">-</span>statements</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>exception<span class=\"token operator\">-</span>declaration<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    handler<span class=\"token operator\">-</span>statements</pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token punctuation\">&#125;</span> <span class=\"token comment\">// ...</span></pre></td></tr></table></figure><p>跟在 try 块之后的是一个或多个 catch 子句</p>\n<p>catch 字句包括三部分：</p>\n<ul>\n<li>关键字 catch</li>\n<li>括号内一个（可能未命名的）对象的声明（称作异常声明，exception declaration）</li>\n<li>一个块（用于处理异常）</li>\n</ul>\n<p>当选中某个 catch 子句处理异常之后，就会执行与之对应的块</p>\n<p>catch 一旦完成，程序将会跳转到 try 语句块对应的最后一个 catch 子句之后，以继续执行后续语句</p>\n<p>try 语句块中的 program-statements 可以是任意 C++ 语句，包括声明在内的</p>\n<blockquote>\n<p>try 语句块内声明的变量在块外部无法访问，特别是，在 catch 子句内也无法访问</p>\n</blockquote>\n<h3 id=\"编写-handler-statements\"><a class=\"anchor\" href=\"#编写-handler-statements\">#</a> 编写 handler-statements</h3>\n<p>例如：可以将程序原本需要执行的任务放在 try 语句块中（这段代码可能会抛出一个 runtime_error 类型的异常），然后在 try 语句块之后跟一个 catch 字句（用于处理类型为 runtime_error 的异常）</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> item1 <span class=\"token operator\">>></span> item2<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">try</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>item1<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> item2<span class=\"token punctuation\">.</span><span class=\"token function\">isbn</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>            <span class=\"token keyword\">throw</span> <span class=\"token function\">runtime_error</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Data must refer to same ISBN\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> item1 <span class=\"token operator\">+</span> item2 <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>runtime_error err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 异常类型为 runtime_error ，异常命名为 err</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token comment\">// 提醒用户两个 ISBN 必须一致，询问是否重新输入</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> err<span class=\"token punctuation\">.</span><span class=\"token function\">what</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>             <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\"\\nTry Again?  Enter y or n\"</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">char</span> c<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        cin <span class=\"token operator\">>></span> c<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>cin <span class=\"token operator\">||</span> c <span class=\"token operator\">==</span> <span class=\"token char\">'n'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">// 用户输入 'n'，跳出 while 循环</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token comment\">// 否则，程序控制权跳回到 while 条件部分，准备下一次迭代</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>其中，what 是 runtime-error 类的一个成员函数，返回的是（初始化一个具体对象时所用的）string 对象的副本</p>\n<p>在上例中，如果 try 语句块中抛出异常，catch 子句将会输出：</p>\n<pre><code>Data must refer to same ISBN\nTry Again? Enter y or n\n</code></pre>\n<h3 id=\"函数在寻找处理代码的过程中退出\"><a class=\"anchor\" href=\"#函数在寻找处理代码的过程中退出\">#</a> 函数在寻找处理代码的过程中退出</h3>\n<p>程序在遇到抛出异常的代码前，可能已经经过了多个 try 语句块（例如，一个 try 语句块可能调用了包含另一个 try 语句块的函数）</p>\n<p>此时，寻找 异常处理代码 的过程为：</p>\n<ul>\n<li>当异常被抛出时，首先搜索抛出该异常的函数</li>\n<li>如果没找到匹配的 catch 子句，则终止该函数，并在调用该函数的函数中继续寻找</li>\n<li>以此类推，沿着程序的执行路径逐层回退，直到找到适当类型的 catch 子句为止</li>\n</ul>\n<p>如果最终还是没能找到任何匹配的 catch 子句，程序将会转到名为 <strong>terminate</strong> 的标准库函数。该函数的行为与系统有关，一般情况下，执行该函数将导致程序非正常退出</p>\n<p>如果一段程序没有 try 语句块且发生了异常，系统也会调用 terminate 函数并终止当前程序的执行</p>\n<h2 id=\"标准异常\"><a class=\"anchor\" href=\"#标准异常\">#</a> 标准异常</h2>\n<p>C++ 标准库定义了一组类，用于报告标准库函数遇到的问题</p>\n<p>C++ 定义了 4 个包含异常类的头文件：</p>\n<ul>\n<li>exception 头文件定义了最通用的异常类 exception，它只报告异常的发生，不提供任何额外信息</li>\n<li>stdexcept 头文件定义了几种常用的异常类（见表 5.1）\n<ul>\n<li><img loading=\"lazy\" data-src=\"Cpp5-%E8%AF%AD%E5%8F%A5/stdexcept.png\" alt=\"\" /></li>\n</ul>\n</li>\n<li>new 头文件定义了 bad_alloc 异常类型</li>\n<li>type_info 头文件定义了 bad_cast 异常类型</li>\n</ul>\n<p>标准库异常类只定义了以下几种运算：</p>\n<ul>\n<li>创建或拷贝异常类型的对象</li>\n<li>为异常类型的对象赋值</li>\n</ul>\n<p>对于 exception 、bad_alloc 和 bad_cast 异常类型，只能以默认初始化的方式来初始化这些类型的对象，而不允许为这些对象提供初始值</p>\n<p>对于其他异常类型，则应该使用 string 对象或者 C 风格字符串来初始化这些类型的对象，而不允许使用默认初始化的方式</p>\n<ul>\n<li>当创建此类对象时，必须提供初始值，该初始值含有错误相关的信息</li>\n</ul>\n<p>每个异常类型都只定义了一个名为 what 的成员函数：</p>\n<ul>\n<li>what 函数没有任何参数，返回值是一个指向 C 风格字符串的  <code>const char*</code> （该字符串的目的是提供关于异常的一些文本信息）</li>\n<li>what 函数返回的 C 风格字符串的内容与异常对象的类型有关：如果异常类型有一个字符串初始值，则 what 返回该字符串；对于其他无初始值的异常类型，what 返回的内容由编译器决定</li>\n</ul>\n<h1 id=\"术语表\"><a class=\"anchor\" href=\"#术语表\">#</a> 术语表</h1>\n<p><strong>块（block）</strong>：包围在花括号内的由 0 条或多条语句组成的序列。块也是一条语句，所以只要是能使用语句的地方，就可以使用块</p>\n<p><strong>break 语句（break statement）</strong>：终止离它最近的循环或 switch 语句。控制权转移到循环或 switch 之后的第一条语句</p>\n<p><strong>case 标签（case label）</strong>：在 switch 语句中紧跟在 case 关键字之后的常量表达式。在同一个 switch 语句中任意两个 case 标签的值不能相同</p>\n<p><strong>catch 子句（catch clause）</strong>：由 catch 关键字、括号里的异常声明以及语句块三部分组成。catch 子句的代码负责处理在异常声明中定义的异常</p>\n<p><strong>复合语句（compound statement）</strong>：块</p>\n<p><strong>continue 语句（continue statement）</strong>：终止离它最近的循环的当前迭代。控制权转移到 while 或 do while 语句的条件部分、或者范围 for 循环的下一次迭代、或者传统 for 循环头部的表达式</p>\n<p><strong>悬垂 else（dangling else）</strong>：是一个俗语，指的是如何处理嵌套 if 语句中 if 分支多于 else 分支的情况</p>\n<ul>\n<li>C++ 语言规定，else 应该与前一个未匹配的 if 匹配在一起</li>\n<li>使用花括号可以把位于内层的 if 语句隐藏起来，这样就能更好地控制 else 该与哪个 if 匹配</li>\n</ul>\n<p><strong>default 标签（default label）</strong>：是一种特殊的 case 标签，当 switch 表达式的值与所有 case 标签都无法匹配时，程序执行 default 标签下的内容</p>\n<p><strong>do while 语句（do while statement）</strong>：与 while 语句类似，但 do while 语句先执行循环体，再判断条件。循环体代码至少会执行一次</p>\n<p><strong>异常类（exception class）</strong>：标准库定义的一组类，用于表示程序发生的错误</p>\n<p><strong>异常声明（exception declaration）</strong>：位于 catch 子句中的声明，指定了该 catch 子句能处理的异常类型</p>\n<p><strong>异常处理代码（exception handler）</strong>：程序某处引发异常后，用于处理该异常的另一处代码。和 catch 子句是同义词</p>\n<p><strong>异常安全（exception safe）</strong>：是一个术语，表示的含义是当抛出异常后，程序能执行正确的行为</p>\n<p><strong>表达式语句（expression statement）</strong>：即一条表达式后面跟上一个分号，令表达式执行求值过程</p>\n<p><strong>控制流（flow of control）</strong>：程序的执行路径</p>\n<p><strong>for 语句（for statement）</strong>：提供迭代执行的迭代语句。常常用于遍历一个容器或者重复计算若干次</p>\n<p><strong>goto 语句（goto statement）</strong>：令控制权无条件转移到同一函数中一个指定的带标签语句。goto 语句容易造成程序的控制流混乱，应禁止使用</p>\n<p><strong>if else 语句（if else statement）</strong>：判断条件，根据其结果分别执行 if 分支或 else 分支的语句</p>\n<p><strong>if 语句（if statement）</strong>：判断条件，根据其结果有选择地执行语句。如果条件为真，执行 if 分支的代码；如果条件为假，控制权转移到 if 结构之后的第一条语句</p>\n<p><strong>带标签语句（labeled statement）</strong>：前面带有标签的语句。所谓标签是指一个标识符以及紧跟着的一个冒号。对于同一个标识符来说，用作标签的同时还能用于其他目的，互不干扰</p>\n<p><strong>空语句（null statement）</strong>：只含有一个分号的语句</p>\n<p><strong>引发（raise）</strong>：含义类似于 throw 。在 C++ 语言中既可以说抛出异常，也可以说引发异常</p>\n<p><strong>范围 for 语句（range for statement）</strong>：在一个序列中进行迭代的语句</p>\n<p><strong>switch 语句（switch statement）</strong>：一种条件语句</p>\n<ul>\n<li>首先求 switch 关键字后面表达式的值</li>\n<li>如果某个 case 标签的值与表达式的值相等，程序直接跨过之前的代码从这个 case 标签开始执行</li>\n<li>当所有 case 标签都无法匹配时，如果有 default 标签，从 default 标签继续执行；如果没有，结束 switch 语句</li>\n</ul>\n<p><strong>terminate</strong> ：是一个标准库函数，当异常没有被捕捉到时调用。terminate 终止当前程序的执行</p>\n<p><strong>throw 表达式（throw expression）</strong>：一种中断当前执行路径的表达式。throw 表达式抛出一个异常并把控制权转移到能处理该异常的最近的 catch 子句</p>\n<p><strong>try 语句块（try block）</strong>：跟在 try 关键字后面的块，以及一个或多个 catch 子句。如果 try 语句块的代码引发异常并且其中一个 catch 子句匹配该异常类型，则异常被该 catch 子句处理。否则，异常将由外围 try 语句块处理，或者程序终止</p>\n<p><strong>while 语句（while statement）</strong>：只要指定的条件为真，就一直迭代执行目标语句</p>\n<p>参考：C++ Primer 中文版（第 5 版）</p>\n",
            "tags": [
                "C++"
            ]
        },
        {
            "id": "https://jiankychen.github.io/leetcode-input&output.html",
            "url": "https://jiankychen.github.io/leetcode-input&output.html",
            "title": "常见输入输出",
            "date_published": "2022-09-09T09:08:49.000Z",
            "content_html": "<h2 id=\"场景一多组空格分隔的两个正整数\"><a class=\"anchor\" href=\"#场景一多组空格分隔的两个正整数\">#</a> 场景一：多组空格分隔的两个正整数</h2>\n<p>输入描述：</p>\n<pre><code>输入包括两个正整数 a, b (1 &lt;= a, b &lt;= 1000)，输入数据包括多组\n</code></pre>\n<p>输出描述：</p>\n<pre><code>输出 a + b 的结果\n</code></pre>\n<p>数据范围：</p>\n<pre><code>数据组数 1 &lt;= t &lt;= 100\n</code></pre>\n<p>输入示例：</p>\n<pre><code>1 5\n10 20\n</code></pre>\n<p>输出示例：</p>\n<pre><code>6\n30\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> b <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> a <span class=\"token operator\">>></span> b<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> a <span class=\"token operator\">+</span> b <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 64 位输出请用 printf (\"% lld\")</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景二第一行组数接空格分隔的两个正整数\"><a class=\"anchor\" href=\"#场景二第一行组数接空格分隔的两个正整数\">#</a> 场景二：第一行组数接空格分隔的两个正整数</h2>\n<p>输入描述：</p>\n<pre><code>输入第一行包括一个数据组数 t (1 &lt;= t &lt;= 100)\n接下来每行包括两个正整数 a, b (1 &lt;= a, b &lt;= 1000)\n</code></pre>\n<p>输出描述：</p>\n<pre><code>输出 a + b 的结果\n</code></pre>\n<p>数据范围：</p>\n<pre><code>数据组数 1 &lt;= t &lt;= 100\n</code></pre>\n<p>输入示例：</p>\n<pre><code>2\n1 5\n10 20\n</code></pre>\n<p>输出示例：</p>\n<pre><code>6\n30\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> t <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    cin <span class=\"token operator\">>></span> t<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> b <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> t<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        cin <span class=\"token operator\">>></span> a <span class=\"token operator\">>></span> b<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> a <span class=\"token operator\">+</span> b <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景三空格分隔的两个正整数-以-0-0-结束\"><a class=\"anchor\" href=\"#场景三空格分隔的两个正整数-以-0-0-结束\">#</a> 场景三：空格分隔的两个正整数 以 0 0 结束</h2>\n<p>输入描述：</p>\n<pre><code>输入包括两个正整数 a, b (1 &lt;= a, b &lt;= 10^9)，输入数据有多组，如果输入为 0 0 则结束输入\n</code></pre>\n<p>输出描述：</p>\n<pre><code>输出 a + b 的结果\n</code></pre>\n<p>数据范围：</p>\n<pre><code>数据组数 1 &lt;= t &lt;= 100\n</code></pre>\n<p>输入示例：</p>\n<pre><code>1 5\n10 20\n0 0\n</code></pre>\n<p>输出示例：</p>\n<pre><code>6\n30\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> b <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> a <span class=\"token operator\">>></span> b<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>a <span class=\"token operator\">==</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> b <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> a <span class=\"token operator\">+</span> b <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景四每行第一个为个数后带空格分割整数-以-0-结束\"><a class=\"anchor\" href=\"#场景四每行第一个为个数后带空格分割整数-以-0-结束\">#</a> 场景四：每行第一个为个数后带空格分割整数 以 0 结束</h2>\n<p>输入描述：</p>\n<pre><code>输入数据有多组，每行表示一组输入数据\n每行的第一个整数为整数的个数 n (1 &lt;= n &lt;= 100)\n接下来 n 个正整数，即需要求和的每个正整数\n</code></pre>\n<p>输出描述：</p>\n<pre><code>每组数据输出求和的结果\n</code></pre>\n<p>数据范围：</p>\n<pre><code>数据组数 1 &lt;= t &lt;= 100\n每组数据中整数个数满足 1 &lt;= n &lt;= 100\n每组数据中的值满足 1 &lt;= val &lt;= 100\n</code></pre>\n<p>输入示例：</p>\n<pre><code>4 1 2 3 4\n5 1 2 3 4 5\n</code></pre>\n<p>输出示例：</p>\n<pre><code>10\n15\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>n <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">break</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">int</span> sum <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            cin <span class=\"token operator\">>></span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            sum <span class=\"token operator\">+=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> sum <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景五第一行组数接个数以及空格分隔的整数\"><a class=\"anchor\" href=\"#场景五第一行组数接个数以及空格分隔的整数\">#</a> 场景五：第一行组数接个数以及空格分隔的整数</h2>\n<p>输入描述：</p>\n<pre><code>输入的第一行包括一个正整数 t (1 &lt;= t &lt;= 100)，表示数据组数\n接下来 t 行，每行一组数据\n每行的第一个整数为整数的个数 n (1 &lt;= n &lt;= 100)\n接下来 n 个正整数，即需要求和的每个正整数\n</code></pre>\n<p>输出描述：</p>\n<pre><code>每组数据输出求和的结果\n</code></pre>\n<p>数据范围：</p>\n<pre><code>数据组数 1 &lt;= t &lt;= 100\n每组数据中整数个数满足 1 &lt;= n &lt;= 100\n每组数据中的值满足 1 &lt;= val &lt;= 100\n</code></pre>\n<p>输入示例：</p>\n<pre><code>2\n4 1 2 3 4\n5 1 2 3 4 5\n</code></pre>\n<p>输出示例：</p>\n<pre><code>10\n15\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> t <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    cin <span class=\"token operator\">>></span> t<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> t<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        cin <span class=\"token operator\">>></span> n<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">int</span> sum <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>            cin <span class=\"token operator\">>></span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            sum <span class=\"token operator\">+=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> sum <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景六多组未知数量的正整数\"><a class=\"anchor\" href=\"#场景六多组未知数量的正整数\">#</a> 场景六：多组未知数量的正整数</h2>\n<p>输入描述：</p>\n<pre><code>输入数据有多组，每行表示一组输入数据\n每行不定有 n 个整数，空格隔开 (1 &lt;= n &lt;= 100)\n</code></pre>\n<p>输出描述：</p>\n<pre><code>每组数据输出求和的结果\n</code></pre>\n<p>输入示例：</p>\n<pre><code>1 2 3\n4 5\n0 0 0 0 0\n</code></pre>\n<p>输出示例：</p>\n<pre><code>6\n9\n0\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 借助 stringstream，把每行数据输入到一个 string ，再转换成一个流</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sstream></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    string str<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getline</span><span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        stringstream <span class=\"token function\">ss</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 将字符串 str 拷贝至 stringstream 流</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">int</span> sum <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>ss <span class=\"token operator\">>></span> num<span class=\"token punctuation\">)</span> sum <span class=\"token operator\">+=</span> num<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 等效于 while (getline (ss, t, ' ')) sum += stoi (t);</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> sum <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>其中， <code>getline (istream&amp; is, string&amp; str, char delim)</code>  ：（参考：<a href=\"https://cplusplus.com/reference/string/string/getline/\">std::getline</a> ）</p>\n<ul>\n<li>Extracts characters from  <code>is</code>  and stores them into  <code>str</code>  until the delimitation character  <code>delim</code>  is found.</li>\n<li>If the delimiter is found, it is extracted and discarded (i.e. it is not stored and the next input operation will begin after it).</li>\n<li>Note that any content in  <code>str</code>  before the call is replaced by the newly extracted sequence.</li>\n</ul>\n<blockquote>\n<p><code>getline (istream&amp;  is, string&amp; str)</code>  ：Extracts characters from  <code>is</code>  and stores them into  <code>str</code>  until the newline character,  <code>'\\n'</code> , is found.</p>\n</blockquote>\n<blockquote>\n<p>注意：如果在使用  <code>getline()</code>  函数之前已经使用过  <code>cin</code>  ，则需使用  <code>cin.get()</code>  （或者， <code>cin.ignore()</code>  或  <code>getchar()</code>  ）读取缓冲区中的换行符  <code>\\n</code>  ，然后再使用  <code>getline()</code>  （参考：<a href=\"https://blog.csdn.net/weixin_43646672/article/details/104675523?spm=1001.2101.3001.6650.8&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-8-104675523-blog-119514017.pc_relevant_multi_platform_featuressortv2dupreplace&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-8-104675523-blog-119514017.pc_relevant_multi_platform_featuressortv2dupreplace&amp;utm_relevant_index=8\">C++ 中 cin 和 getline 使用出错的解决方法</a> ）</p>\n<ul>\n<li><code>cin.get()</code>  ：可以读入包括空格，跳格，回车符在内的空白字符</li>\n<li><code>cin.ignore()</code>  ：丢弃输入的第一个字符。用来防止接收上次输入的回车符</li>\n<li><code>getchar()</code>  ：读取一个字符，包括回车，空格</li>\n</ul>\n</blockquote>\n<p>或者：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 每次 cin >> 时判断下一位是不是换行符，即 cin.get () == '\\n'</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">int</span> sum <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">int</span> num <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> num<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        sum <span class=\"token operator\">+=</span> num<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token char\">'\\n'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            cout <span class=\"token operator\">&lt;&lt;</span> sum <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            sum <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景七一行多个空格分隔的字符串\"><a class=\"anchor\" href=\"#场景七一行多个空格分隔的字符串\">#</a> 场景七：一行多个空格分隔的字符串</h2>\n<p>输入描述：</p>\n<pre><code>输入有两行，第一行 n\n第二行是 n 个字符串，字符串之间用空格隔开\n</code></pre>\n<p>输出描述：</p>\n<pre><code>输出一行排序后的字符串，空格隔开，无结尾空格\n</code></pre>\n<p>输入示例：</p>\n<pre><code>5\nc d a bb e\n</code></pre>\n<p>输出示例：</p>\n<pre><code>a bb c d e\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;vector></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;algorithm></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    cin <span class=\"token operator\">>></span> n<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> <span class=\"token function\">words</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        cin <span class=\"token operator\">>></span> words<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token function\">sort</span><span class=\"token punctuation\">(</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> n <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>n <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 无结尾空格</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景八多行空格分隔的字符串\"><a class=\"anchor\" href=\"#场景八多行空格分隔的字符串\">#</a> 场景八：多行空格分隔的字符串</h2>\n<p>输入描述：</p>\n<pre><code>多个测试用例，每个测试用例一行\n每行通过空格隔开，有 n 个字符，n &lt; 100\n</code></pre>\n<p>输出描述：</p>\n<pre><code>对于每组测试用例，输出一行排序过的字符串，每个字符串通过空格隔开\n</code></pre>\n<p>输入示例：</p>\n<pre><code>a c bb\nf dddd\nnowcoder\n</code></pre>\n<p>输出示例：</p>\n<pre><code>a bb c\ndddd f\nnowcoder\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// getline()</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;vector></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sstream></span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;algorithm></span></span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    string str1<span class=\"token punctuation\">,</span> str2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> words<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getline</span><span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">,</span> str1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        stringstream <span class=\"token function\">ss</span><span class=\"token punctuation\">(</span>str1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getline</span><span class=\"token punctuation\">(</span>ss<span class=\"token punctuation\">,</span> str2<span class=\"token punctuation\">,</span> <span class=\"token char\">' '</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>str2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 等效于 while (ss>> str2) words.push_back (str2);</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token function\">sort</span><span class=\"token punctuation\">(</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        words<span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 清空 words 数组</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>或者：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 判断换行符 cin.get () == '\\n'</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;vector></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;algorithm></span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    string word<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> words<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>cin <span class=\"token operator\">>></span> word<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        words<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>word<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token char\">'\\n'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 等效于 if (getchar () == '\\n')</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token function\">sort</span><span class=\"token punctuation\">(</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\" \"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            words<span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><h2 id=\"场景九多行逗号分隔的字符串\"><a class=\"anchor\" href=\"#场景九多行逗号分隔的字符串\">#</a> 场景九：多行逗号分隔的字符串</h2>\n<p>输入描述：</p>\n<pre><code>多个测试用例，每个测试用例一行\n每行通过 ',' 隔开，有 n 个字符，n &lt; 100\n</code></pre>\n<p>输出描述：</p>\n<pre><code>对于每组用例输出一行排序后的字符串，用 ',' 隔开，无结尾空格\n</code></pre>\n<p>输入示例：</p>\n<pre><code>a,c,bb\nf,dddd\nnowcoder\n</code></pre>\n<p>输出示例：</p>\n<pre><code>a,bb,c\ndddd,f\nnowcoder\n</code></pre>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;string></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;vector></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;sstream></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;algorithm></span></span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">using</span> <span class=\"token keyword\">namespace</span> std<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    string str1<span class=\"token punctuation\">,</span> str2<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">></span> words<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getline</span><span class=\"token punctuation\">(</span>cin<span class=\"token punctuation\">,</span> str1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        stringstream <span class=\"token function\">ss</span><span class=\"token punctuation\">(</span>str1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getline</span><span class=\"token punctuation\">(</span>ss<span class=\"token punctuation\">,</span> str2<span class=\"token punctuation\">,</span> <span class=\"token char\">','</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>str2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>        <span class=\"token function\">sort</span><span class=\"token punctuation\">(</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> words<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>            cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> <span class=\"token string\">\",\"</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        cout <span class=\"token operator\">&lt;&lt;</span> words<span class=\"token punctuation\">[</span>words<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;&lt;</span> endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        words<span class=\"token punctuation\">.</span><span class=\"token function\">clear</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>参考：</p>\n<ul>\n<li><a href=\"https://ac.nowcoder.com/acm/contest/5657#question\">OJ 在线编程常见输入输出练习</a></li>\n<li><a href=\"https://blog.csdn.net/qq_39295220/article/details/116785551?utm_term=%E7%89%9B%E5%AE%A2%E7%BD%91%E6%80%8E%E4%B9%88%E6%8C%89acm%E6%A8%A1%E5%BC%8F%E7%BB%83%E9%A2%98&amp;utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~sobaiduweb~default-1-116785551&amp;spm=3001.4430.\">ACM 模式输入输出案例总结</a></li>\n</ul>\n",
            "tags": [
                "Coding"
            ]
        },
        {
            "id": "https://jiankychen.github.io/latex-citation.html",
            "url": "https://jiankychen.github.io/latex-citation.html",
            "title": "LaTeX：跨 tex 文件的交叉引用",
            "date_published": "2022-08-29T12:45:58.000Z",
            "content_html": "<h2 id=\"教程\"><a class=\"anchor\" href=\"#教程\">#</a> 教程</h2>\n<p>如果需要在 response.tex 中引用 revision.tex 的某一段文本，可通过以下步骤实现：</p>\n<ol>\n<li>\n<p>在 revision.tex 中，将需要引用的文本放在  <code>%&lt;*tag&gt;</code>  和  <code>%&lt;/tag&gt;</code>  之间，即：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">%&lt;*tag></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>Here is the text to be cited.</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\">%&lt;/tag></span></pre></td></tr></table></figure></li>\n<li>\n<p>在 response.tex 中，添加  <code>catchfilebetweentags</code>  这个包，即：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function selector\">\\usepackage</span><span class=\"token punctuation\">&#123;</span><span class=\"token keyword\">catchfilebetweentags</span><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></li>\n<li>\n<p>在 response.tex 中，利用  <code>\\ExecuteMetaData</code>  命令引用文本，即：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function selector\">\\ExecuteMetaData</span><span class=\"token punctuation\">[</span>revision<span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#123;</span>tag<span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure></li>\n</ol>\n<p>然而，如果需要引用的文本中包含了  <code>\\ref</code>  、 <code>\\eqref</code>  、 <code>\\cite</code>  命令，response.tex 将无法正常编译以及显示编号</p>\n<p>此时，还需要让 response.tex 获取 revision.tex 所生成的 labels 和 citations ，即，在  response.tex 中添加如下命令：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">% copy labels</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function selector\">\\usepackage</span><span class=\"token punctuation\">&#123;</span><span class=\"token keyword\">xr</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function selector\">\\externaldocument</span><span class=\"token punctuation\">&#123;</span>revision<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">% copy citations</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function selector\">\\usepackage</span><span class=\"token punctuation\">&#123;</span><span class=\"token keyword\">xcite</span><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function selector\">\\externalcitedocument</span><span class=\"token punctuation\">&#123;</span>revision<span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>这是因为，revision.tex 生成的 labels 和 citations 全都保存在 revision.aux 文件中，而  <code>\\externaldocument</code>  和  <code>\\externalcitedocument</code>  可以分别读取 aux 文件中的 labels 和 citations</p>\n<p>执行完以上操作，无论是 revision.tex 中的什么文本，都能在 response.tex 中正常编译并显示（测试使用的是 IEEE 的论文模板）</p>\n<blockquote>\n<p>可能不适用于其余期刊的论文模板，因为其他期刊论文模板可能修改了 aux 文件中 labels 和 citations 的格式（应该是都可以通过编译的，只不过显示效果依赖于期刊模板）</p>\n</blockquote>\n<h2 id=\"示例\"><a class=\"anchor\" href=\"#示例\">#</a> 示例</h2>\n<p>例如，在 revision.tex 中写到：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">%&lt;*lemma></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function selector\">\\blue</span><span class=\"token punctuation\">&#123;</span>The transmission energy consumption of an SN can be minimal when constraints </pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function selector\">\\eqref</span><span class=\"token punctuation\">&#123;</span>eqn:power_low_energy_node<span class=\"token punctuation\">&#125;</span> - <span class=\"token function selector\">\\eqref</span><span class=\"token punctuation\">&#123;</span>eqn:power_CH<span class=\"token punctuation\">&#125;</span> are met with equality.<span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\">%&lt;/lemma></span></pre></td></tr></table></figure><p>在 response.tex 中引用 revision.tex 的内容：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>We have rewritten Lemma 1 as: ``<span class=\"token function selector\">\\ExecuteMetaData</span><span class=\"token punctuation\">[</span>revision<span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#123;</span>lemma<span class=\"token punctuation\">&#125;</span>''</pre></td></tr></table></figure><p>编译得到的 response.pdf 显示：<br />\n<img loading=\"lazy\" data-src=\"LATEX-%E4%BA%A4%E5%8F%89%E5%BC%95%E7%94%A8/1.png\" alt=\"\" /><br />\n可以看到，revision.tex 对公式的引用，即，  <code>\\eqref&#123;eqn:power_low_energy_node&#125; - \\eqref&#123;eqn:power_CH&#125;</code>  ，也能在 response.tex 中正常编译（并且，response.pdf 显示出的公式编号与 revision.pdf 相同）</p>\n<blockquote>\n<p>为了使用  <code>\\blue&#123;&#125;</code>  命令（使  <code>&#123;&#125;</code>  内的文字变蓝色），需要先在导言区定义： <code>\\newcommand&#123;\\blue&#125;[1]&#123;&#123;&#123;\\color&#123;blue&#125; #1&#125;&#125;&#125;</code></p>\n</blockquote>\n<p>再例如，在 revision.tex 中写到：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">%&lt;*collection></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>With CDG scheme <span class=\"token function selector\">\\cite</span><span class=\"token punctuation\">&#123;</span><span class=\"token keyword\">CDG2009</span><span class=\"token punctuation\">&#125;</span>, each SN sends the collected data along the data collection </pre></td></tr><tr><td data-num=\"3\"></td><td><pre>route to the CH, and the UAV flies to collect data along the trajectory obtained from the </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>configuration phase.</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\">%&lt;/collection></span></pre></td></tr></table></figure><p>在 response.tex 中引用：</p>\n<figure class=\"highlight tex\"><figcaption data-lang=\"TeX\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>To reveal the data collection mechanism, we have added the following sentence in Section </pre></td></tr><tr><td data-num=\"2\"></td><td><pre>IV: ``<span class=\"token function selector\">\\blue</span><span class=\"token punctuation\">&#123;</span><span class=\"token function selector\">\\ExecuteMetaData</span><span class=\"token punctuation\">[</span>revision<span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#123;</span>collection<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">&#125;</span>''</pre></td></tr></table></figure><p>编译得到的 response.pdf 显示：<br />\n<img loading=\"lazy\" data-src=\"LATEX-%E4%BA%A4%E5%8F%89%E5%BC%95%E7%94%A8/2.png\" alt=\"\" /><br />\n可以看到，revision.tex 对参考文献的引用， <code>\\cite&#123;CDG2009&#125;</code>  ，也能在 response.tex 中奏效</p>\n<p>类似的，revision.tex 中关于表格（table）、算法（algorithm）、图片（figure）等的引用（通过 \\label 命令打标签、通过 \\ref 命令引用），也能采用以上方式在 response.tex 中正常编译并显示</p>\n",
            "tags": [
                "Tutorial",
                "LaTeX"
            ]
        },
        {
            "id": "https://jiankychen.github.io/leetcode-sort.html",
            "url": "https://jiankychen.github.io/leetcode-sort.html",
            "title": "LeetCode - 排序专题",
            "date_published": "2022-08-22T05:39:22.000Z",
            "content_html": "<h1 id=\"leetcode-215-数组中的第-k-个最大元素\"><a class=\"anchor\" href=\"#leetcode-215-数组中的第-k-个最大元素\">#</a> LeetCode 215. 数组中的第 K 个最大元素</h1>\n<p><a href=\"https://leetcode.cn/problems/kth-largest-element-in-an-array/\">215. Kth Largest Element in an Array</a></p>\n<p>给定整数数组  <code>nums</code>  和整数  <code>k</code> ，请返回数组中第  <code>k</code>  个最大的元素。</p>\n<p>请注意，你需要找的是数组排序后的第  <code>k</code>  个最大的元素，而不是第  <code>k</code>  个不同的元素。</p>\n<p>你必须设计并实现时间复杂度为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span> 的算法解决此问题。</p>\n<p><strong>示例 1：</strong></p>\n<pre><code>输入：nums = [3,2,1,5,6,4], k = 2\n输出：5\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：nums = [3,2,3,1,2,4,5,5,6], k = 4\n输出：4\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>k</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">\\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>nums.length</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding=\"application/x-tex\">\\le 10^5</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8141em;\"></span><span class=\"mord\">1</span><span class=\"mord\"><span class=\"mord\">0</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">5</span></span></span></span></span></span></span></span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>−</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">-10^4 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9501em;vertical-align:-0.136em;\"></span><span class=\"mord\">−</span><span class=\"mord\">1</span><span class=\"mord\"><span class=\"mord\">0</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">4</span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>nums[i]</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding=\"application/x-tex\">\\le 10^4</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8141em;\"></span><span class=\"mord\">1</span><span class=\"mord\"><span class=\"mord\">0</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">4</span></span></span></span></span></span></span></span></span></span></span></li>\n</ul>\n<h2 id=\"思路\"><a class=\"anchor\" href=\"#思路\">#</a> 思路</h2>\n<p>数组第 k 个最大元素，即，数组降序排序后的第 k 个元素（或者，升序排序后的倒数第 k 个元素）</p>\n<p>对整个数组排序的时间复杂度至少为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\log{n})</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mop\">lo<span style=\"margin-right:0.01389em;\">g</span></span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord\"><span class=\"mord mathnormal\">n</span></span><span class=\"mclose\">)</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 是数组 nums 的长度</p>\n<p>有一种基于快速排序的算法，可以确定某一个元素在排序以后的位置，即，<strong>快速选择</strong> 算法</p>\n<h2 id=\"method-1-基于快速排序的选择方法\"><a class=\"anchor\" href=\"#method-1-基于快速排序的选择方法\">#</a> Method 1: 基于快速排序的选择方法</h2>\n<p>算法思路：（以 寻找降序排序后的第 k 个元素 为例）</p>\n<p>快速排序的划分操作：从区间 [left, right] 中选择任意一个元素作为基准，调整子数组，使得位置 p 左侧的元素都大于等于基准元素，位置 p 右侧的元素都小于基准元素，于是，基准元素的最终位置就是 p</p>\n<p>即，nums [p] 左侧元素全都大于等于 nums [p]，nums [q] 右侧元素全都小于 nums [p]，于是，nums [p] 就是第 p + 1 个最大元素（数组索引从 0 开始）</p>\n<p>因此，可按如下方案求解该问题：</p>\n<ul>\n<li>\n<p>如果某次划分的 p 为 k - 1 时，即找到了第 k 个最大元素，可直接返回 nums [p]</p>\n</li>\n<li>\n<p>如果 p 小于 k - 1，则需要查找值更小的元素，即，继续划分 p 右侧的子区间</p>\n</li>\n<li>\n<p>如果 p 大于 k - 1，则需要查找值更大的元素，即，继续划分 p 左侧的子区间</p>\n</li>\n</ul>\n<p>特别地，我们应随机选择基准元素，使得快速算法算法的时间代价的期望为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 划分子序列</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">partition</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> nums<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> left<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> right<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 随机选择基准，以该基准作为分界线</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">int</span> x <span class=\"token operator\">=</span> left <span class=\"token operator\">+</span> <span class=\"token function\">rand</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>right <span class=\"token operator\">-</span> left <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 随机生成一个位于区间 [left, right] 内的数</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> pivot <span class=\"token operator\">=</span> nums<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>        <span class=\"token comment\">// 划分子序列的基准</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token function\">swap</span><span class=\"token punctuation\">(</span>nums<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> nums<span class=\"token punctuation\">[</span>right<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 将基准移至最右侧</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">int</span> pos <span class=\"token operator\">=</span> left <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>         <span class=\"token comment\">// 分界线 pos 及其左边的元素一定大于等于 pivot</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> left<span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> right<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 划分子序列</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>nums<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">>=</span> pivot<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token function\">swap</span><span class=\"token punctuation\">(</span>nums<span class=\"token punctuation\">[</span><span class=\"token operator\">++</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> nums<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    <span class=\"token function\">swap</span><span class=\"token punctuation\">(</span>nums<span class=\"token punctuation\">[</span><span class=\"token operator\">++</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> nums<span class=\"token punctuation\">[</span>right<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 将 pivot 放到分界线位置</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">return</span> pos<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 分界线</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token comment\">// 快速选择</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">quickSelect</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> nums<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> left<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> right<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> index<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 寻找降序排列后下标为 index 的元素</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 为降低空间复杂度，这里采用 while 循环，而不采用递归</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token keyword\">int</span> pos <span class=\"token operator\">=</span> <span class=\"token function\">partition</span><span class=\"token punctuation\">(</span>nums<span class=\"token punctuation\">,</span> left<span class=\"token punctuation\">,</span> right<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//nums [pos] 为第 pos + 1 个最大元素（数组索引从 0 开始）</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>pos <span class=\"token operator\">==</span> index<span class=\"token punctuation\">)</span>     <span class=\"token comment\">// 寻找到目标下标，该位置元素值即为第 k 个最大元素</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>            <span class=\"token keyword\">return</span> nums<span class=\"token punctuation\">[</span>pos<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>pos <span class=\"token operator\">&lt;</span> index<span class=\"token punctuation\">)</span> <span class=\"token comment\">// 分界线在目标下标左侧</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            left <span class=\"token operator\">=</span> pos <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>        <span class=\"token keyword\">else</span>                  <span class=\"token comment\">// 分界线在目标下标右侧</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>            right <span class=\"token operator\">=</span> pos <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">findKthLargest</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> nums<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> k<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token function\">srand</span><span class=\"token punctuation\">(</span><span class=\"token function\">time</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token function\">quickSelect</span><span class=\"token punctuation\">(</span>nums<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> nums<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> k <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 是数组 nums 的长度</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mn>1</mn><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(1)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord\">1</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>参考：</p>\n<ul>\n<li><a href=\"https://leetcode.cn/problems/kth-largest-element-in-an-array/solution/shu-zu-zhong-de-di-kge-zui-da-yuan-su-by-leetcode-/\">leetcode-solution</a></li>\n<li><a href=\"https://leetcode.cn/problems/kth-largest-element-in-an-array/solution/partitionfen-er-zhi-zhi-you-xian-dui-lie-java-dai-/\">liweiwei1419</a></li>\n</ul>\n",
            "tags": [
                "Coding",
                "排序"
            ]
        },
        {
            "id": "https://jiankychen.github.io/leetcode-search.html",
            "url": "https://jiankychen.github.io/leetcode-search.html",
            "title": "LeetCode - 搜索专题",
            "date_published": "2022-08-16T08:38:30.000Z",
            "content_html": "<h1 id=\"leetcode-200-岛屿数量\"><a class=\"anchor\" href=\"#leetcode-200-岛屿数量\">#</a> LeetCode 200. 岛屿数量</h1>\n<p><a href=\"https://leetcode.cn/problems/number-of-islands/\">200. Number of Islands</a></p>\n<p>给你一个由 '1'（陆地）和 '0'（水）组成的的二维网格，请你计算网格中岛屿的数量。</p>\n<p>岛屿总是被水包围，并且每座岛屿只能由水平方向和 / 或竖直方向上相邻的陆地连接形成。</p>\n<p>此外，你可以假设该网格的四条边均被水包围。</p>\n<p><strong>示例 1：</strong></p>\n<pre><code>输入：grid = [\n  [&quot;1&quot;,&quot;1&quot;,&quot;1&quot;,&quot;1&quot;,&quot;0&quot;],\n  [&quot;1&quot;,&quot;1&quot;,&quot;0&quot;,&quot;1&quot;,&quot;0&quot;],\n  [&quot;1&quot;,&quot;1&quot;,&quot;0&quot;,&quot;0&quot;,&quot;0&quot;],\n  [&quot;0&quot;,&quot;0&quot;,&quot;0&quot;,&quot;0&quot;,&quot;0&quot;]\n]\n输出：1\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：grid = [\n  [&quot;1&quot;,&quot;1&quot;,&quot;0&quot;,&quot;0&quot;,&quot;0&quot;],\n  [&quot;1&quot;,&quot;1&quot;,&quot;0&quot;,&quot;0&quot;,&quot;0&quot;],\n  [&quot;0&quot;,&quot;0&quot;,&quot;1&quot;,&quot;0&quot;,&quot;0&quot;],\n  [&quot;0&quot;,&quot;0&quot;,&quot;0&quot;,&quot;1&quot;,&quot;1&quot;]\n]\n输出：3\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><code>m == grid.length</code></li>\n<li><code>n == grid[i].length</code></li>\n<li><code>1 &lt;= m, n &lt;= 300</code></li>\n<li><code>grid[i][j]</code>  的值为 '0' 或 '1'</li>\n</ul>\n<h2 id=\"method-1-深度优先搜索\"><a class=\"anchor\" href=\"#method-1-深度优先搜索\">#</a> Method 1: 深度优先搜索</h2>\n<p>算法思路：</p>\n<p>扫描整个二维网格，如果某一个位置为 '1'，则表示查找到一个岛屿，此时需以其为起始位置开始进行深度优先搜索</p>\n<p>深度优先搜索的具体操作：</p>\n<ul>\n<li>将搜索到的 '1' 重新标记为 '0'</li>\n<li>从该位置出发，向 4 个方向探索与之相连的位置</li>\n</ul>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> directions <span class=\"token operator\">=</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">!</span><span class=\"token operator\">--</span>swig￼<span class=\"token number\">0</span><span class=\"token operator\">--</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">helper</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">char</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> m <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    grid<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'0'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 标记 (i, j) 位置，表示已访问过该位置</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> k <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> k <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>k<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 向四个方向进行搜索</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">int</span> newi <span class=\"token operator\">=</span> i <span class=\"token operator\">+</span> directions<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">int</span> newj <span class=\"token operator\">=</span> j <span class=\"token operator\">+</span> directions<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>newi <span class=\"token operator\">>=</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> newi <span class=\"token operator\">&lt;</span> m <span class=\"token operator\">&amp;&amp;</span> newj <span class=\"token operator\">>=</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> newj <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>newi<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>newj<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token char\">'1'</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>                <span class=\"token function\">helper</span><span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">,</span> newi<span class=\"token punctuation\">,</span> newj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">numIslands</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">char</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">int</span> m <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">int</span> ans <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> m<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>    <span class=\"token comment\">// 遍历起点位置</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token char\">'1'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 发现一座岛屿</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>                <span class=\"token function\">helper</span><span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">,</span> i<span class=\"token punctuation\">,</span> j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 扫描整块岛屿</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>                <span class=\"token operator\">++</span>ans<span class=\"token punctuation\">;</span>               <span class=\"token comment\">// 岛屿数量加 1</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token keyword\">return</span> ans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 是二维网格的行数和列数</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>，最坏情况下，递归的深度为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi><mo>×</mo><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">m \\times n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6667em;vertical-align:-0.0833em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span></p>\n<h2 id=\"method-2-广度优先搜索\"><a class=\"anchor\" href=\"#method-2-广度优先搜索\">#</a> Method 2: 广度优先搜索</h2>\n<p>算法思路：</p>\n<p>扫描整个二维网格，每发现一个位置为 '1'，就表示查找到一个岛屿，将该位置加入队列，针对该岛屿开始广度优先搜索，直到队列为空</p>\n<ul>\n<li>将搜索到的 '1' 重新标记为 '0'</li>\n<li>从该位置出发，向 4 个方向探索与之相连的位置</li>\n</ul>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">numIslands</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">char</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> m <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> ans <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> directions <span class=\"token operator\">=</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">!</span><span class=\"token operator\">--</span>swig￼<span class=\"token number\">1</span><span class=\"token operator\">--</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> m<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token char\">'1'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>                <span class=\"token operator\">++</span>ans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>                grid<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'0'</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>                queue<span class=\"token operator\">&lt;</span>pair<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token operator\">>></span> que<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>                que<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>i<span class=\"token punctuation\">,</span> j<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>                <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>que<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>                    <span class=\"token keyword\">auto</span> neighbor <span class=\"token operator\">=</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>                    que<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                    <span class=\"token keyword\">int</span> x <span class=\"token operator\">=</span> neighbor<span class=\"token punctuation\">.</span>first<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                    <span class=\"token keyword\">int</span> y <span class=\"token operator\">=</span> neighbor<span class=\"token punctuation\">.</span>second<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>                    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> k <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> k <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>k<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>                        <span class=\"token keyword\">int</span> newx <span class=\"token operator\">=</span> x <span class=\"token operator\">+</span> directions<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>                        <span class=\"token keyword\">int</span> newy <span class=\"token operator\">=</span> y <span class=\"token operator\">+</span> directions<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>                        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token number\">0</span> <span class=\"token operator\">&lt;=</span> newx <span class=\"token operator\">&amp;&amp;</span> newx <span class=\"token operator\">&lt;</span> m <span class=\"token operator\">&amp;&amp;</span> <span class=\"token number\">0</span> <span class=\"token operator\">&lt;=</span> newy <span class=\"token operator\">&amp;&amp;</span> newy <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>                            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">[</span>newx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>newy<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token char\">'1'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>                                que<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>newx<span class=\"token punctuation\">,</span> newy<span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>                                grid<span class=\"token punctuation\">[</span>newx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>newy<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token char\">'0'</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>                            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>                        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>                    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre>    <span class=\"token keyword\">return</span> ans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m \\times n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span> 和 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 是二维网格的行数和列数</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>min</mi><mo>⁡</mo><mo stretchy=\"false\">(</mo><mi>m</mi><mo>×</mo><mi>n</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(\\min(m \\times n))</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mop\">min</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">))</span></span></span></span>，在最坏情况下，整个网格均为陆地，队列的大小为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>min</mi><mo>⁡</mo><mo stretchy=\"false\">(</mo><mi>m</mi><mo separator=\"true\">,</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\min(m, n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mop\">min</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em;\"></span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h1 id=\"leetcode-207-课程表\"><a class=\"anchor\" href=\"#leetcode-207-课程表\">#</a> LeetCode 207. 课程表</h1>\n<p><a href=\"https://leetcode.cn/problems/course-schedule/\">207. Course Schedule</a></p>\n<p>你这个学期必须选修  <code>numCourses</code>  门课程，记为  <code>0</code>  到  <code>numCourses - 1</code>  。</p>\n<p>在选修某些课程之前需要一些先修课程。 先修课程按数组  <code>prerequisites</code>  给出，其中  <code>prerequisites[i] = [ai, bi]</code>  ，表示如果要学习课程  <code>ai</code>  则 必须 先学习课程   <code>bi</code>  。</p>\n<ul>\n<li>例如，先修课程对  <code>[0, 1]</code>  表示：想要学习课程  <code>0</code>  ，你需要先完成课程  <code>1</code>  。</li>\n</ul>\n<p>请你判断是否可能完成所有课程的学习？如果可以，返回  <code>true</code>  ；否则，返回  <code>false</code>  。</p>\n<p><strong>示例 1：</strong></p>\n<pre><code>输入：numCourses = 2, prerequisites = [[1,0]]\n输出：true\n解释：总共有 2 门课程。学习课程 1 之前，你需要完成课程 0 。这是可能的。\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：numCourses = 2, prerequisites = [[1,0],[0,1]]\n输出：false\n解释：总共有 2 门课程。学习课程 1 之前，你需要先完成​课程 0 ；并且学习课程 0 之前，你还应先完成课程 1 。这是不可能的。\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>numCourses</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>2000</mn></mrow><annotation encoding=\"application/x-tex\">\\le 2000</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">2000</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">0 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">0</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>prerequisites.length</code>  \\le 5000$</li>\n<li><code>prerequisites[i].length</code>  == 2</li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">0 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">0</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>ai</code> ,  <code>bi</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>&lt;</mo></mrow><annotation encoding=\"application/x-tex\">&lt;</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.5782em;vertical-align:-0.0391em;\"></span><span class=\"mrel\">&lt;</span></span></span></span>  <code>numCourses</code></li>\n<li><code>prerequisites[i]</code>  中的所有课程对 互不相同</li>\n</ul>\n<h2 id=\"思路\"><a class=\"anchor\" href=\"#思路\">#</a> 思路</h2>\n<p>给定一个包含 n 个节点的有向图 G，我们给出它的节点编号的一种排列，如果满足：</p>\n<ul>\n<li>对于图 G 中的任意一条有向边 (u, v)，u 在排列中都出现在 v 的前面</li>\n</ul>\n<p>那么称该排列是图 G 的 <strong>拓扑排序</strong></p>\n<p>根据上述定义，有以下结论：</p>\n<ul>\n<li>如果图 G 中存在环（即图 G 不是 <strong>有向无环图</strong> ），图 G 不存在拓扑排序</li>\n<li>如果图 G 是有向无环图，它的拓扑排序可能不止一种</li>\n</ul>\n<p>在本题中，我们可以将每一门课看成一个节点，如果学习课程 A 之前必须完成课程 B，则可以连接一条从 B 到 A 的有向边，然后判断该图是否存在拓扑排序（也就是判断该图是否为有向无环图）</p>\n<h2 id=\"method-1-广度优先遍历\"><a class=\"anchor\" href=\"#method-1-广度优先遍历\">#</a> Method 1: 广度优先遍历</h2>\n<p>算法思路：</p>\n<p>我们考虑拓扑排序中最前面的节点，该节点一定不会有任何入边，也就是它没有任何的先修课程要求。当我们将一个节点加入答案中后，我们就可以移除它的所有出边，代表着它的相邻节点少了一门先修课程的要求。如果某个相邻节点变成了「没有任何入边的节点」，那么就代表着这门课可以开始学习了。按照这样的流程，我们不断地将没有入边的节点加入答案，直到答案中包含所有的节点（得到了一种拓扑排序）或者不存在没有入边的节点（图中包含环）</p>\n<p>算法流程：</p>\n<p>使用一个队列来进行广度优先搜索：初始时，所有入度为 0 的节点都被放入队列中，它们就是可以作为拓扑排序最前面的节点，并且，它们之间的相对顺序是无关紧要的</p>\n<p>在广度优先搜索的每一步中，我们取出队首的节点 u：</p>\n<ul>\n<li>\n<p>将 u 放入答案数组中</p>\n</li>\n<li>\n<p>移除 u 的所有出边，也就是将 u 的所有相邻节点的入度减少 1。如果某个相邻节点 v 的入度变为 0，就将 v 放入答案数组中</p>\n</li>\n</ul>\n<p>在广度优先搜索的过程结束后，如果答案数组中包含了这 numCourses 个节点，那就说明我们找到了一种拓扑排序，否则，说明图中存在环，也就不存在拓扑排序了</p>\n<blockquote>\n<p>特别地，可以只用一个变量来记录入度为 0 的节点个数，而无需将节点实际放入答案数组中。在广度优先搜索结束后，判断该变量的值是否等于课程数，就能知道是否存在一种拓扑排序</p>\n</blockquote>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">canFinish</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> numCourses<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> prerequisites<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> edges<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 有向图的边（邻接表）</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> indeg<span class=\"token punctuation\">;</span>         <span class=\"token comment\">// 节点的入度</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    edges<span class=\"token punctuation\">.</span><span class=\"token function\">resize</span><span class=\"token punctuation\">(</span>numCourses<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    indeg<span class=\"token punctuation\">.</span><span class=\"token function\">resize</span><span class=\"token punctuation\">(</span>numCourses<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> info <span class=\"token operator\">:</span> prerequisites<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        edges<span class=\"token punctuation\">[</span>info<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>info<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 建立一条从 info [1] 到 info [0] 的有向边</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token operator\">++</span>indeg<span class=\"token punctuation\">[</span>info<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>                  <span class=\"token comment\">// 更新节点 info [0] 的入度</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    queue<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> que<span class=\"token punctuation\">;</span>  <span class=\"token comment\">// 存放入度为 0 的节点</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> numCourses<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>indeg<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">int</span> visited <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 入度为 0 的节点个数（可选修的课程数）</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>que<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token operator\">++</span>visited<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">int</span> u <span class=\"token operator\">=</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        que<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> v <span class=\"token operator\">:</span> edges<span class=\"token punctuation\">[</span>u<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 移除 u 的所有出边</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>            <span class=\"token operator\">--</span>indeg<span class=\"token punctuation\">[</span>v<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>indeg<span class=\"token punctuation\">[</span>v<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>v<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    </pre></td></tr><tr><td data-num=\"27\"></td><td><pre>    <span class=\"token keyword\">return</span> visited <span class=\"token operator\">==</span> numCourses<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>n</mi></mrow><annotation encoding=\"application/x-tex\">n</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">n</span></span></span></span> 为课程数（即，numCourses），<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>m</mi></mrow><annotation encoding=\"application/x-tex\">m</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.4306em;\"></span><span class=\"mord mathnormal\">m</span></span></span></span> 为先修课程的要求数（即，prerequisites 中一维数组的数量）</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，其中，邻接表所需空间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，队列所需空间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mclose\">)</span></span></span></span></p>\n<h2 id=\"method-2-深度优先搜索\"><a class=\"anchor\" href=\"#method-2-深度优先搜索\">#</a> Method 2: 深度优先搜索</h2>\n<p>算法思路：</p>\n<p>借助一个标志列表 flags，用于判断每个节点 i （课程）的状态</p>\n<ul>\n<li>未被访问：flags [i] == 0</li>\n<li>被其他节点启动的深度优先搜索访问过：flags [i] == -1</li>\n<li>被当前节点启动的深度优先搜索访问过：flags [i] == 1</li>\n</ul>\n<p>对 numCourses 个节点依次执行深度优先搜索，判断以每个节点起步的深度优先搜索是否存在环，若存在环直接返回 false</p>\n<ul>\n<li>终止条件：\n<ul>\n<li>当 flag [i] == -1，说明当前访问节点已被其他节点启动的深度优先搜索访问过，无需再重复搜索，直接返回 true</li>\n<li>当 flag [i] == 1，说明在本轮深度优先搜索中节点 i 被第 2 次访问，即，有环存在，直接返回 false</li>\n</ul>\n</li>\n<li>将当前访问节点 i 对应 flag [i] 置 1</li>\n<li>递归访问当前节点 i 的所有邻接节点 j，若发现环则直接返回 false</li>\n<li>当前节点所有邻接节点已被遍历，并没有发现环，将当前节点 flag 置为 -1 并返回 true</li>\n</ul>\n<p>待整个图的深度优先搜索结束，如果未发现环，返回 true</p>\n<p>代码实现：</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> edges<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> flags<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">DFS</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 判断是否存在以 i 起始的拓扑排序</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>flags<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>flags<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    flags<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">:</span> edges<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">DFS</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>    flags<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">bool</span> <span class=\"token function\">canFinish</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> numCourses<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> prerequisites<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    edges<span class=\"token punctuation\">.</span><span class=\"token function\">resize</span><span class=\"token punctuation\">(</span>numCourses<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    flags<span class=\"token punctuation\">.</span><span class=\"token function\">resize</span><span class=\"token punctuation\">(</span>numCourses<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">auto</span> info <span class=\"token operator\">:</span> prerequisites<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        edges<span class=\"token punctuation\">[</span>info<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>info<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> numCourses<span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>flags<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">DFS</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>+</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n + m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span></p>\n<p>参考：<a href=\"https://leetcode.cn/problems/course-schedule/solution/ke-cheng-biao-by-leetcode-solution/\">leetcode-solution</a></p>\n<h1 id=\"leetcode-399-除法求值\"><a class=\"anchor\" href=\"#leetcode-399-除法求值\">#</a> LeetCode 399. 除法求值</h1>\n<p><a href=\"https://leetcode.cn/problems/evaluate-division/\">399. Evaluate Division</a></p>\n<p>给你一个变量对数组  <code>equations</code>  和一个实数值数组  <code>values</code>  作为已知条件，其中  <code>equations[i] = [Ai, Bi]</code>  和  <code>values[i]</code>  共同表示等式  <code>Ai / Bi = values[i]</code>  。每个  <code>Ai</code>  或  <code>Bi</code>  是一个表示单个变量的字符串。</p>\n<p>另有一些以数组  <code>queries</code>  表示的问题，其中  <code>queries[j] = [Cj, Dj]</code>  表示第  <code>j</code>  个问题，请你根据已知条件找出  <code>Cj / Dj = ?</code>  的结果作为答案。</p>\n<p>返回 <strong>所有问题的答案</strong> 。如果存在某个无法确定的答案，则用  <code>-1.0</code>  替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串，也需要用  <code>-1.0</code>  替代这个答案。</p>\n<p><strong>注意：</strong> 输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况，且不存在任何矛盾的结果。</p>\n<p><strong>示例 1：</strong></p>\n<pre><code>输入：equations = [[&quot;a&quot;,&quot;b&quot;],[&quot;b&quot;,&quot;c&quot;]], values = [2.0,3.0], queries = [[&quot;a&quot;,&quot;c&quot;],[&quot;b&quot;,&quot;a&quot;],[&quot;a&quot;,&quot;e&quot;],[&quot;a&quot;,&quot;a&quot;],[&quot;x&quot;,&quot;x&quot;]]\n输出：[6.00000,0.50000,-1.00000,1.00000,-1.00000]\n解释：\n    条件：a / b = 2.0, b / c = 3.0\n    问题：a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?\n    结果：[6.0, 0.5, -1.0, 1.0, -1.0 ]\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：equations = [[&quot;a&quot;,&quot;b&quot;],[&quot;b&quot;,&quot;c&quot;],[&quot;bc&quot;,&quot;cd&quot;]], values = [1.5,2.5,5.0], queries = [[&quot;a&quot;,&quot;c&quot;],[&quot;c&quot;,&quot;b&quot;],[&quot;bc&quot;,&quot;cd&quot;],[&quot;cd&quot;,&quot;bc&quot;]]\n输出：[3.75000,0.40000,5.00000,0.20000]\n</code></pre>\n<p><strong>示例 3：</strong></p>\n<pre><code>输入：equations = [[&quot;a&quot;,&quot;b&quot;]], values = [0.5], queries = [[&quot;a&quot;,&quot;b&quot;],[&quot;b&quot;,&quot;a&quot;],[&quot;a&quot;,&quot;c&quot;],[&quot;x&quot;,&quot;y&quot;]]\n输出：[0.50000,2.00000,-1.00000,-1.00000]\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li>1 &lt;= equations.length &lt;= 20</li>\n<li>equations[i].length == 2</li>\n<li>1 &lt;= Ai.length, Bi.length &lt;= 5</li>\n<li>values.length == equations.length</li>\n<li>0.0 &lt; values[i] &lt;= 20.0</li>\n<li>1 &lt;= queries.length &lt;= 20</li>\n<li>queries[i].length == 2</li>\n<li>1 &lt;= Cj.length, Dj.length &lt;= 5</li>\n<li>Ai, Bi, Cj, Dj 由小写英文字母与数字组成</li>\n</ul>\n<h2 id=\"method-1-广度优先搜索\"><a class=\"anchor\" href=\"#method-1-广度优先搜索\">#</a> Method 1: 广度优先搜索</h2>\n<h2 id=\"算法思路\"><a class=\"anchor\" href=\"#算法思路\">#</a> 算法思路</h2>\n<p>可以将整个问题建模成一个图：将变量字符串视为图的顶点，将两个变量的比值视为两顶点之间边的权值，试对任意两点（两个变量）求其路径长度（两个变量的比值）</p>\n<p>首先遍历  <code>equations</code>  数组，将每个不同的变量字符串编号，并通过哈希表建立映射</p>\n<p>然后，建立每个顶点的边集并将其存储到数组  <code>vector&lt;vector&lt;pair&lt;int, double&gt;&gt;&gt; edges</code>  中，其中， <code>edges[i]</code>  表示第 i 个顶点的边集， <code>edges[i][j].first</code>  表示顶点 i 的第 j 个邻居节点， <code>edges[i][j].second</code>  表示顶点 i 到其第 j 个邻居节点的路径长度（两个变量的比值）</p>\n<p>于是，对于任何一个查询，可以从起点出发，通过广度优先搜索的方式，遍历图中的顶点，并更新起点到当前点的路径长度，直到遍历到终点为止</p>\n<blockquote>\n<p>由于每次查询都需要遍历图中的所有顶点，当查询数量较大时，效率就会非常低。因此，可以对图进行预处理，先计算出每个顶点到其他顶点的路径长度，然后再依次处理每一个查询</p>\n</blockquote>\n<h2 id=\"代码实现\"><a class=\"anchor\" href=\"#代码实现\">#</a> 代码实现</h2>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">double</span><span class=\"token operator\">></span> <span class=\"token function\">calcEquation</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> equations<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">double</span><span class=\"token operator\">></span><span class=\"token operator\">&amp;</span> values<span class=\"token punctuation\">,</span> vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span>string<span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> queries<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token comment\">// 给变量字符串编号</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">int</span> varNum <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>                  <span class=\"token comment\">// 变量字符串的数量</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    unordered_map<span class=\"token operator\">&lt;</span>string<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token operator\">></span> vars<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 以变量字符串为 key ，以其编号为 value</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> equations<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>vars<span class=\"token punctuation\">.</span><span class=\"token function\">count</span><span class=\"token punctuation\">(</span>equations<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>            vars<span class=\"token punctuation\">[</span>equations<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> varNum<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            varNum<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>vars<span class=\"token punctuation\">.</span><span class=\"token function\">count</span><span class=\"token punctuation\">(</span>equations<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>            vars<span class=\"token punctuation\">[</span>equations<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> varNum<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>            varNum<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token comment\">// 将变量视为图的顶点，将两个变量的比值视为两顶点之间边的权值</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span>pair<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">double</span><span class=\"token operator\">>></span><span class=\"token operator\">></span> <span class=\"token function\">edges</span><span class=\"token punctuation\">(</span>varNum<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 存储每个点的邻居及其对应的权值</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> equations<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token keyword\">int</span> vertexA <span class=\"token operator\">=</span> vars<span class=\"token punctuation\">[</span>equations<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>        <span class=\"token keyword\">int</span> vertexB <span class=\"token operator\">=</span> vars<span class=\"token punctuation\">[</span>equations<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        edges<span class=\"token punctuation\">[</span>vertexA<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>vertexB<span class=\"token punctuation\">,</span> values<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>        edges<span class=\"token punctuation\">[</span>vertexB<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">&#123;</span>vertexA<span class=\"token punctuation\">,</span> <span class=\"token number\">1.0</span> <span class=\"token operator\">/</span> values<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>    vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">double</span><span class=\"token operator\">></span> res<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">auto</span><span class=\"token operator\">&amp;</span> q <span class=\"token operator\">:</span> queries<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 遍历每一个问题</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>        <span class=\"token comment\">// 已知条件中没有出现字符串 q [0] 或 q [1]</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>vars<span class=\"token punctuation\">.</span><span class=\"token function\">count</span><span class=\"token punctuation\">(</span>q<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span> <span class=\"token operator\">||</span> vars<span class=\"token punctuation\">.</span><span class=\"token function\">count</span><span class=\"token punctuation\">(</span>q<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>            res<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span><span class=\"token operator\">-</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 结果为 -1.0</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre>            <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre></pre></td></tr><tr><td data-num=\"33\"></td><td><pre>        <span class=\"token comment\">//q [0] 与 q [1] 均出现在已知条件中</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre>        <span class=\"token comment\">// 采用广度优先搜索</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre>        <span class=\"token keyword\">int</span> vertexA <span class=\"token operator\">=</span> vars<span class=\"token punctuation\">[</span>q<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 起点的编号</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre>        <span class=\"token keyword\">int</span> vertexB <span class=\"token operator\">=</span> vars<span class=\"token punctuation\">[</span>q<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 终点的编号</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre>        queue<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> que<span class=\"token punctuation\">;</span>             <span class=\"token comment\">// 队列，存放 待访问的顶点</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre>        que<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>vertexA<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>          <span class=\"token comment\">// 将起点入队</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>        vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">double</span><span class=\"token operator\">></span> <span class=\"token function\">ratios</span><span class=\"token punctuation\">(</span>varNum<span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1.0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 存放起点 vertexA 到各顶点的路径长度</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre>        ratios<span class=\"token punctuation\">[</span>vertexA<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">1.0</span><span class=\"token punctuation\">;</span>      <span class=\"token comment\">//vertexA 到其自身的路径长度为 1.0 （自身与自身的比值为 1.0 ）</span></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>        <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>que<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> ratios<span class=\"token punctuation\">[</span>vertexB<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 未访问过终点 vertexB</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre>            <span class=\"token keyword\">int</span> u <span class=\"token operator\">=</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 当前访问的顶点</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>            que<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>              <span class=\"token comment\">// 将当前顶点出队</span></pre></td></tr><tr><td data-num=\"44\"></td><td><pre>            <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">auto</span> <span class=\"token punctuation\">[</span>v<span class=\"token punctuation\">,</span> val<span class=\"token punctuation\">]</span> <span class=\"token operator\">:</span> edges<span class=\"token punctuation\">[</span>u<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span> <span class=\"token comment\">// 处理顶点 u 的每一条边</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ratios<span class=\"token punctuation\">[</span>v<span class=\"token punctuation\">]</span> <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span><span class=\"token comment\">// 未访问过顶点 v </span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre>                    ratios<span class=\"token punctuation\">[</span>v<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> ratios<span class=\"token punctuation\">[</span>u<span class=\"token punctuation\">]</span> <span class=\"token operator\">*</span> val<span class=\"token punctuation\">;</span>   <span class=\"token comment\">// 起点 vertexA 到顶点 v 的路径长度（对应两个变量的比值）</span></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>                    que<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>v<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 将顶点 v 入队</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"50\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre>        <span class=\"token comment\">// 循环结束时，ratios [vertexB] 即为 vertexA 与 vertexB 对应变量的比值</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre>        <span class=\"token comment\">// 若终点 vertexB 不可达（当队列为空时，仍未访问过 vertexB ），则结果为 -1.0</span></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>        res<span class=\"token punctuation\">.</span><span class=\"token function\">push_back</span><span class=\"token punctuation\">(</span>ratios<span class=\"token punctuation\">[</span>vertexB<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre></pre></td></tr><tr><td data-num=\"55\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre></pre></td></tr><tr><td data-num=\"57\"></td><td><pre>    <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>其中， <code>ratios[u]</code>  表示 顶点  <code>vertexA</code>  与顶点  <code>u</code>  对应变量的比值， <code>val</code>  表示 顶点  <code>u</code>  与顶点  <code>v</code>  对应变量的比值，因此，顶点  <code>vertex A</code>  与顶点  <code>v</code>  对应变量的比值为  <code>ratios[u] * val</code>  ，即， <code>ratios[v] = ratios[u] * val</code></p>\n<h2 id=\"复杂度分析\"><a class=\"anchor\" href=\"#复杂度分析\">#</a> 复杂度分析</h2>\n<p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>M</mi><mi>L</mi><mo>+</mo><mi>Q</mi><mo>⋅</mo><mo stretchy=\"false\">(</mo><mi>L</mi><mo>+</mo><mi>M</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(M L + Q \\cdot (L + M))</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">Q</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mclose\">))</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> 为 数组  <code>equations</code>  的长度（边的数量），<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>L</mi></mrow><annotation encoding=\"application/x-tex\">L</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\">L</span></span></span></span> 为字符串的平均长度，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>Q</mi></mrow><annotation encoding=\"application/x-tex\">Q</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8778em;vertical-align:-0.1944em;\"></span><span class=\"mord mathnormal\">Q</span></span></span></span> 为数组  <code>queries</code>  的长度（查询的数量）</p>\n<ul>\n<li>构建图时，需要处理 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>M</mi></mrow><annotation encoding=\"application/x-tex\">M</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span></span></span></span> 条边，每条边都涉及到 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span> 的字符串比较，时间复杂度为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>M</mi><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(M L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span></li>\n<li>处理每次查询时都要进行一次 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span> 的字符串比较、遍历 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>M</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(M)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mclose\">)</span></span></span></span> 条边（最坏情况下），时间复杂度为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mo stretchy=\"false\">(</mo><mi>L</mi><mo>+</mo><mi>M</mi><mo stretchy=\"false\">)</mo><mo>⋅</mo><mi>Q</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O((L + M) \\cdot Q)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">((</span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">Q</span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>N</mi><mi>L</mi><mo>+</mo><mi>M</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(N L + M)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mord mathnormal\">L</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mclose\">)</span></span></span></span>，其中 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>N</mi></mrow><annotation encoding=\"application/x-tex\">N</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.6833em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span></span></span></span> 为数组  <code>equations</code>  中的字符串的种类数（图的顶点个数）</p>\n<ul>\n<li>存储每个变量字符串的编号，需要的空间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>N</mi><mi>L</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(N L)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mord mathnormal\">L</span><span class=\"mclose\">)</span></span></span></span></li>\n<li>存储图中所有的边及其权重，需要的空间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>M</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(M)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">M</span><span class=\"mclose\">)</span></span></span></span></li>\n<li>广度优先搜索过程中，存放待访问的顶点，需要的空间为 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>N</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(N)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.10903em;\">N</span><span class=\"mclose\">)</span></span></span></span></li>\n</ul>\n<h2 id=\"method-2-带权并查集\"><a class=\"anchor\" href=\"#method-2-带权并查集\">#</a> Method 2: 带权并查集</h2>\n<p>参考：<a href=\"https://leetcode.cn/problems/evaluate-division/solution/chu-fa-qiu-zhi-by-leetcode-solution-8nxb/\">leetcode-solution</a></p>\n<h1 id=\"leetcode-695-岛屿的最大面积\"><a class=\"anchor\" href=\"#leetcode-695-岛屿的最大面积\">#</a> LeetCode 695. 岛屿的最大面积</h1>\n<p><a href=\"https://leetcode-cn.com/problems/max-area-of-island/\">LeetCode 695. Max Area of Island</a></p>\n<p>给你一个大小为  <code>m x n</code>  的二进制矩阵  <code>grid</code>  。</p>\n<p>岛屿 是由一些相邻的  <code>1</code>  (代表土地) 构成的组合，这里的「相邻」要求两个  <code>1</code>  必须在 <strong>水平或者竖直的四个方向上</strong> 相邻。你可以假设  <code>grid</code>  的四个边缘都被  <code>0</code> （代表水）包围着。</p>\n<p>岛屿的面积是岛上值为  <code>1</code>  的单元格的数目。</p>\n<p>计算并返回  <code>grid</code>  中最大的岛屿面积。如果没有岛屿，则返回面积为  <code>0</code>  。</p>\n<p><strong>示例 1：</strong></p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%90%9C%E7%B4%A2%E4%B8%93%E9%A2%98/LeetCode695_1.png\" alt=\"\" /></p>\n<pre><code>输入：grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]\n输出：6\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：grid = [[0,0,0,0,0,0,0,0]]\n输出：0\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><code>m == grid.length</code></li>\n<li><code>n == grid[i].length</code></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>m</code> ,  <code>n</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>50</mn></mrow><annotation encoding=\"application/x-tex\">\\le 50</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">50</span></span></span></span></li>\n<li><code>grid[i][j]</code>  为 0 或 1</li>\n</ul>\n<h2 id=\"method-1-深度优先搜索-2\"><a class=\"anchor\" href=\"#method-1-深度优先搜索-2\">#</a> Method 1: 深度优先搜索</h2>\n<p>计算网格中每个连通形状的面积，然后取最大值。</p>\n<p>在一个土地上，向 4 个方向探索与之相连的每一个土地（以及与这些土地相连的土地），那么探索过的土地总数将是该连通形状的面积</p>\n<p><strong>为了确保每个土地访问不超过一次，我们每次经过一块土地时，将这块土地的值置为  <code>0</code> </strong></p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">private</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> <span class=\"token function\">DFS</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> cur_i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> cur_j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span>  <span class=\"token comment\">// 深度优先搜索</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cur_i <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span> <span class=\"token operator\">||</span> cur_i <span class=\"token operator\">==</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> cur_j <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span> <span class=\"token operator\">||</span> cur_j <span class=\"token operator\">==</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> grid<span class=\"token punctuation\">[</span>cur_i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>cur_j<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>                       <span class=\"token comment\">//cur_i cur_j 超出边界或 grid [cur_i][cur_j] 为 0 时，返回 0</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        grid<span class=\"token punctuation\">[</span>cur_i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>cur_j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 已经访问过的位置置 0，以免重复访问</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        <span class=\"token keyword\">int</span> ans <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>            <span class=\"token comment\">// 岛屿面积</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> di<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">0</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>        <span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> dj<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> index <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> index <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> index<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            <span class=\"token keyword\">int</span> next_i <span class=\"token operator\">=</span> cur_i <span class=\"token operator\">+</span> di<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> next_j <span class=\"token operator\">=</span> cur_j <span class=\"token operator\">+</span> dj<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            ans <span class=\"token operator\">+=</span> <span class=\"token function\">DFS</span><span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">,</span>next_i<span class=\"token punctuation\">,</span>next_j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        <span class=\"token keyword\">return</span> ans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">public</span><span class=\"token operator\">:</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">int</span> <span class=\"token function\">maxAreaOfIsland</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>        <span class=\"token keyword\">int</span> ans <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>            <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j<span class=\"token operator\">&lt;</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> j<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>                ans <span class=\"token operator\">=</span> <span class=\"token function\">max</span><span class=\"token punctuation\">(</span>ans<span class=\"token punctuation\">,</span> <span class=\"token function\">DFS</span><span class=\"token punctuation\">(</span>grid<span class=\"token punctuation\">,</span>i<span class=\"token punctuation\">,</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>        <span class=\"token keyword\">return</span> ans<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>R</mi><mo>×</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(R \\times C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span>。其中  <code>R</code>  是给定网格中的行数， <code>C</code>  是列数。访问每个网格最多一次</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>R</mi><mo>×</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(R \\times C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span>，递归的深度最大可能是整个网格的大小，因此最大可能使用 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>R</mi><mo>×</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(R \\times C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span> 的栈空间</p>\n<h2 id=\"method-2-深度优先搜索-栈\"><a class=\"anchor\" href=\"#method-2-深度优先搜索-栈\">#</a> Method 2: 深度优先搜索 + 栈</h2>\n<h2 id=\"method-3-广度优先搜索\"><a class=\"anchor\" href=\"#method-3-广度优先搜索\">#</a> Method 3: 广度优先搜索</h2>\n<p>把方法二中的栈改为队列，每次从队首取出土地，并将接下来想要遍历的土地放在队尾，就实现了广度优先搜索算法</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">maxAreaOfIsland</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> grid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>    <span class=\"token keyword\">int</span> ans <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">!=</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>i<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> j <span class=\"token operator\">!=</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>j<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>            <span class=\"token keyword\">int</span> cur <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>            queue<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> queuei<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>            queue<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> queuej<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            queuei<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>            queuej<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>queuei<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>                <span class=\"token keyword\">int</span> cur_i <span class=\"token operator\">=</span> queuei<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> cur_j <span class=\"token operator\">=</span> queuej<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>                queuei<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>                queuej<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cur_i <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span> <span class=\"token operator\">||</span> cur_j <span class=\"token operator\">&lt;</span> <span class=\"token number\">0</span> <span class=\"token operator\">||</span> cur_i <span class=\"token operator\">==</span> grid<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> cur_j <span class=\"token operator\">==</span> grid<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> grid<span class=\"token punctuation\">[</span>cur_i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>cur_j<span class=\"token punctuation\">]</span> <span class=\"token operator\">!=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>                    <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                <span class=\"token operator\">++</span>cur<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>                grid<span class=\"token punctuation\">[</span>cur_i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>cur_j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>                <span class=\"token keyword\">int</span> di<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>                <span class=\"token keyword\">int</span> dj<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>                <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> index <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> index <span class=\"token operator\">!=</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> <span class=\"token operator\">++</span>index<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre>                    <span class=\"token keyword\">int</span> next_i <span class=\"token operator\">=</span> cur_i <span class=\"token operator\">+</span> di<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> next_j <span class=\"token operator\">=</span> cur_j <span class=\"token operator\">+</span> dj<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre>                    queuei<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>next_i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre>                    queuej<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>next_j<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre>                <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre>            ans <span class=\"token operator\">=</span> <span class=\"token function\">max</span><span class=\"token punctuation\">(</span>ans<span class=\"token punctuation\">,</span> cur<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>R</mi><mo>×</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(R \\times C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span>。其中  <code>R</code>  是给定网格中的行数， <code>C</code>  是列数，访问每个网格最多一次</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>R</mi><mo>×</mo><mi>C</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(R \\times C)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\" style=\"margin-right:0.00773em;\">R</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.07153em;\">C</span><span class=\"mclose\">)</span></span></span></span>，队列中最多会存放所有的土地，土地的数量最多为  <code>R × C</code>  块</p>\n<h1 id=\"leetcode-733-图像渲染\"><a class=\"anchor\" href=\"#leetcode-733-图像渲染\">#</a> LeetCode 733. 图像渲染</h1>\n<p><a href=\"https://leetcode-cn.com/problems/flood-fill/\">LeetCode 733. Flood Fill</a></p>\n<p>有一幅以  <code>m x n</code>  的二维整数数组表示的图画  <code>image</code>  ，其中  <code>image[i][j]</code>  表示该图画的像素值大小（索引  <code>i</code>  和  <code>j</code>  均从 0 开始）。</p>\n<p>你也被给予三个整数  <code>sr</code>  ， <code>sc</code>  和  <code>newColor</code>  。你应该从像素  <code>image[sr][sc]</code>  开始对图像进行 上色填充 。</p>\n<p>为了完成 <strong>上色工作</strong> ，从初始像素开始，记录初始坐标的 <strong>上下左右四个方向上</strong> 像素值与初始坐标相同的相连像素点，接着再记录这四个方向上符合条件的像素点与他们对应 <strong>四个方向上</strong> 像素值与初始坐标相同的相连像素点，……，重复该过程。将所有有记录的像素点的颜色值改为  <code>newColor</code>  。</p>\n<p>最后返回 经过上色渲染后的图像 。</p>\n<p></p>\n<p><strong>示例 1：</strong></p>\n<p><img loading=\"lazy\" data-src=\"LeetCode-%E6%90%9C%E7%B4%A2%E4%B8%93%E9%A2%98/LeetCode733_1.png\" alt=\"\" /></p>\n<pre><code>输入：image = [[1,1,1],[1,1,0],[1,0,1]], sr = 1, sc = 1, newColor = 2\n输出：[[2,2,2],[2,2,0],[2,0,1]]\n解释：在图像的正中间，(坐标(sr,sc)=(1,1)),在路径上所有符合条件的像素点的颜色都被更改成2。注意，右下角的像素没有更改为2，因为它不是在上下左右四个方向上与初始点相连的像素点。\n</code></pre>\n<p><strong>示例 2：</strong></p>\n<pre><code>输入：image = [[0,0,0],[0,0,0]], sr = 0, sc = 0, newColor = 2\n输出：[[2,2,2],[2,2,2]]\n</code></pre>\n<p><strong>提示：</strong></p>\n<ul>\n<li><code>m == image.length</code></li>\n<li><code>n == image[i].length</code></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">1 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>m</code>  ,  <code>n</code>  <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mo>≤</mo><mn>50</mn></mrow><annotation encoding=\"application/x-tex\">\\le 50</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7719em;vertical-align:-0.136em;\"></span><span class=\"mrel\">≤</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em;\"></span><span class=\"mord\">50</span></span></span></span></li>\n<li><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding=\"application/x-tex\">0 \\le</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.7804em;vertical-align:-0.136em;\"></span><span class=\"mord\">0</span><span class=\"mspace\" style=\"margin-right:0.2778em;\"></span><span class=\"mrel\">≤</span></span></span></span>  <code>image[i][j]</code>  ,  <code>newColor</code>  &lt; <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msup><mn>2</mn><mn>16</mn></msup></mrow><annotation encoding=\"application/x-tex\">2^{16}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.8141em;\"></span><span class=\"mord\"><span class=\"mord\">2</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8141em;\"><span style=\"top:-3.063em;margin-right:0.05em;\"><span class=\"pstrut\" style=\"height:2.7em;\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">16</span></span></span></span></span></span></span></span></span></span></span></span></li>\n</ul>\n<h2 id=\"method-1-广度优先搜索-2\"><a class=\"anchor\" href=\"#method-1-广度优先搜索-2\">#</a> Method 1: 广度优先搜索</h2>\n<p>每次搜索到一个方格时，如果其与初始位置的方格颜色相同，就将该方格加入队列，并<strong>将该方格的颜色更新，以防止重复入队</strong>。</p>\n<p>注意：因为初始位置的颜色会被修改，所以我们需要保存初始位置的颜色，以便于之后的更新操作。</p>\n<p>注意：<strong>当目标颜色和初始颜色相同时，我们无需对原数组进行修改</strong>。</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> dx<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span>                <span class=\"token comment\">// 四个方向</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> dy<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> <span class=\"token function\">floodFill</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> image<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> sr<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> sc<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">int</span> currColor <span class=\"token operator\">=</span> image<span class=\"token punctuation\">[</span>sr<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>sc<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>currColor <span class=\"token operator\">==</span> newColor<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> image<span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 目标颜色和初始颜色相同</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>    <span class=\"token keyword\">int</span> n <span class=\"token operator\">=</span> image<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> m <span class=\"token operator\">=</span> image<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>    queue<span class=\"token operator\">&lt;</span>pair<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token operator\">>></span> que<span class=\"token punctuation\">;</span>                  <span class=\"token comment\">// 待搜索位置的队列</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>    que<span class=\"token punctuation\">.</span><span class=\"token function\">emplace</span><span class=\"token punctuation\">(</span>sr<span class=\"token punctuation\">,</span> sc<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>                        <span class=\"token comment\">// 初始化</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>    image<span class=\"token punctuation\">[</span>sr<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>sc<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> newColor<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>    <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>que<span class=\"token punctuation\">.</span><span class=\"token function\">empty</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token keyword\">int</span> x <span class=\"token operator\">=</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>first<span class=\"token punctuation\">,</span> y <span class=\"token operator\">=</span> que<span class=\"token punctuation\">.</span><span class=\"token function\">front</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>second<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>        que<span class=\"token punctuation\">.</span><span class=\"token function\">pop</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre>            <span class=\"token keyword\">int</span> mx <span class=\"token operator\">=</span> x <span class=\"token operator\">+</span> dx<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> my <span class=\"token operator\">=</span> y <span class=\"token operator\">+</span> dy<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>mx <span class=\"token operator\">>=</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> mx <span class=\"token operator\">&lt;</span> n <span class=\"token operator\">&amp;&amp;</span> my <span class=\"token operator\">>=</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> my <span class=\"token operator\">&lt;</span> m <span class=\"token operator\">&amp;&amp;</span> image<span class=\"token punctuation\">[</span>mx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>my<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> currColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>                que<span class=\"token punctuation\">.</span><span class=\"token function\">emplace</span><span class=\"token punctuation\">(</span>mx<span class=\"token punctuation\">,</span> my<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>                image<span class=\"token punctuation\">[</span>mx<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>my<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> newColor<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>    <span class=\"token keyword\">return</span> image<span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>×</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\times m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，其中  <code>n</code>  和  <code>m</code>  分别是二维数组的行数和列数。最坏情况下需要遍历所有的方格一次。</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>×</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\times m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，主要为队列的开销。</p>\n<h2 id=\"method-2-深度优先搜索-2\"><a class=\"anchor\" href=\"#method-2-深度优先搜索-2\">#</a> Method 2: 深度优先搜索</h2>\n<p>从给定的起点开始，进行深度优先搜索。每次搜索到一个方格时，如果其与初始位置的方格颜色相同，就将该方格的颜色更新，以防止重复搜索；如果不相同，则进行回溯。</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> dx<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">const</span> <span class=\"token keyword\">int</span> dy<span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">&#123;</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">&#125;</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">dfs</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> image<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> x<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> y<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> color<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>y<span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> color<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>        image<span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>y<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> newColor<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>        <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> <span class=\"token number\">4</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>            <span class=\"token keyword\">int</span> mx <span class=\"token operator\">=</span> x <span class=\"token operator\">+</span> dx<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> my <span class=\"token operator\">=</span> y <span class=\"token operator\">+</span> dy<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>mx <span class=\"token operator\">>=</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> mx <span class=\"token operator\">&lt;</span> image<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> my <span class=\"token operator\">>=</span> <span class=\"token number\">0</span> <span class=\"token operator\">&amp;&amp;</span> my <span class=\"token operator\">&lt;</span> image<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>                <span class=\"token function\">dfs</span><span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">,</span> mx<span class=\"token punctuation\">,</span> my<span class=\"token punctuation\">,</span> color<span class=\"token punctuation\">,</span> newColor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>    <span class=\"token comment\">// 递归，深度优先搜索</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>            <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>        <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre></pre></td></tr><tr><td data-num=\"15\"></td><td><pre>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span> <span class=\"token function\">floodFill</span><span class=\"token punctuation\">(</span>vector<span class=\"token operator\">&lt;</span>vector<span class=\"token operator\">&lt;</span><span class=\"token keyword\">int</span><span class=\"token operator\">>></span><span class=\"token operator\">&amp;</span> image<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> sr<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> sc<span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span> newColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre>    <span class=\"token keyword\">int</span> currColor <span class=\"token operator\">=</span> image<span class=\"token punctuation\">[</span>sr<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>sc<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre>    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>currColor <span class=\"token operator\">!=</span> newColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">&#123;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>        <span class=\"token function\">dfs</span><span class=\"token punctuation\">(</span>image<span class=\"token punctuation\">,</span> sr<span class=\"token punctuation\">,</span> sc<span class=\"token punctuation\">,</span> currColor<span class=\"token punctuation\">,</span> newColor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>    <span class=\"token punctuation\">&#125;</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>    <span class=\"token keyword\">return</span> image<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token punctuation\">&#125;</span></pre></td></tr></table></figure><p>时间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>×</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\times m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，最坏情况下需要遍历所有的方格一次。</p>\n<p>空间复杂度：<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>O</mi><mo stretchy=\"false\">(</mo><mi>n</mi><mo>×</mo><mi>m</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">O(n \\times m)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.02778em;\">O</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">n</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span><span class=\"mbin\">×</span><span class=\"mspace\" style=\"margin-right:0.2222em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mord mathnormal\">m</span><span class=\"mclose\">)</span></span></span></span>，主要为栈空间的开销。</p>\n",
            "tags": [
                "Coding",
                "广度优先搜索",
                "深度优先搜索"
            ]
        }
    ]
}