<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Wpz&#39;s Blog</title>
  
  <subtitle>闻道有先后，术业有专攻。</subtitle>
  <link href="https://blog.wpz.homes/atom.xml" rel="self"/>
  
  <link href="https://blog.wpz.homes/"/>
  <updated>2026-09-20T09:12:05.372Z</updated>
  <id>https://blog.wpz.homes/</id>
  
  <author>
    <name>wpz</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Mathjax 与 LaTex 公式</title>
    <link href="https://blog.wpz.homes/posts/e8b7be43/"/>
    <id>https://blog.wpz.homes/posts/e8b7be43/</id>
    <published>2024-09-06T10:20:23.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="inline-和-displayed"><a href="#inline-和-displayed" class="headerlink" title="inline 和 displayed"></a>inline 和 displayed</h2><p><code>MathJax</code>中的公式排版有两种方式，<code>inline</code>和<code>displayed</code>。<br><code>inline</code>表示公式嵌入到文本段中，使用<code>$...$</code>作为分隔符。<br><code>displayed</code>表示公式独自成为一个段落，使用<code>$$...$$</code>作为分隔符。</p><h2 id="希腊字母"><a href="#希腊字母" class="headerlink" title="希腊字母"></a>希腊字母</h2><div class="table-container"><table><thead><tr><th>名称</th><th style="text-align:center">大写符号</th><th>命令</th><th style="text-align:center">小写符号</th><th>命令</th></tr></thead><tbody><tr><td>alpha</td><td style="text-align:center">$A$</td><td>A</td><td style="text-align:center">$\alpha$</td><td>\alpha</td></tr><tr><td>beta</td><td style="text-align:center">$B$</td><td>B</td><td style="text-align:center">$\beta$</td><td>\beta</td></tr><tr><td>gamma</td><td style="text-align:center">$\Gamma$</td><td>\Gamma</td><td style="text-align:center">$\gamma$</td><td>\gamma</td></tr><tr><td>delta</td><td style="text-align:center">$\Delta$</td><td>\Delta</td><td style="text-align:center">$\delta$</td><td>\delta</td></tr><tr><td>epsilon</td><td style="text-align:center">$E$</td><td>E</td><td style="text-align:center">$\epsilon$</td><td>\epsilon</td></tr><tr><td>zeta</td><td style="text-align:center">$Z$</td><td>Z</td><td style="text-align:center">$\zeta$</td><td>\zeta</td></tr><tr><td>eta</td><td style="text-align:center">$H$</td><td>H</td><td style="text-align:center">$\eta$</td><td>\eta</td></tr><tr><td>theta</td><td style="text-align:center">$\Theta$</td><td>\Theta</td><td style="text-align:center">$\theta$</td><td>\theta</td></tr><tr><td>iota</td><td style="text-align:center">$I$</td><td>I</td><td style="text-align:center">$\iota$</td><td>\iota</td></tr><tr><td>kappa</td><td style="text-align:center">$K$</td><td>K</td><td style="text-align:center">$\kappa$</td><td>\kappa</td></tr><tr><td>lambda</td><td style="text-align:center">$\Lambda$</td><td>\Lambda</td><td style="text-align:center">$\lambda$</td><td>\lambda</td></tr><tr><td>mu</td><td style="text-align:center">$M$</td><td>M</td><td style="text-align:center">$\mu$</td><td>\mu</td></tr><tr><td>nu</td><td style="text-align:center">$N$</td><td>N</td><td style="text-align:center">$\nu$</td><td>\nu</td></tr><tr><td>xi</td><td style="text-align:center">$\Xi$</td><td>\Xi</td><td style="text-align:center">$\xi$</td><td>\xi</td></tr><tr><td>omicron</td><td style="text-align:center">$O$</td><td>O</td><td style="text-align:center">$\omicron$</td><td>\omicron</td></tr><tr><td>pi</td><td style="text-align:center">$\Pi$</td><td>\Pi</td><td style="text-align:center">$\pi$</td><td>\pi</td></tr><tr><td>rho</td><td style="text-align:center">$P$</td><td>P</td><td style="text-align:center">$\rho$</td><td>\rho</td></tr><tr><td>sigma</td><td style="text-align:center">$\Sigma$</td><td>\Sigma</td><td style="text-align:center">$\sigma$</td><td>\sigma</td></tr><tr><td>tau</td><td style="text-align:center">$T$</td><td>T</td><td style="text-align:center">$\tau$</td><td>\tau</td></tr><tr><td>upsilon</td><td style="text-align:center">$\Upsilon$</td><td>\Upsilon</td><td style="text-align:center">$\upsilon$</td><td>\upsilon</td></tr><tr><td>phi</td><td style="text-align:center">$\Phi$</td><td>\Phi</td><td style="text-align:center">$\phi$</td><td>\phi</td></tr><tr><td>chi</td><td style="text-align:center">$X$</td><td>X</td><td style="text-align:center">$\chi$</td><td>\chi</td></tr><tr><td>psi</td><td style="text-align:center">$\Psi$</td><td>\Psi</td><td style="text-align:center">$\psi$</td><td>\psi</td></tr><tr><td>omega</td><td style="text-align:center">$\Omega$</td><td>\Omega</td><td style="text-align:center">$\omega$</td><td>\omega</td></tr></tbody></table></div><p>如果需要<code>斜体</code>希腊字母，将命令前加上<code>var</code>即可，比如<code>\varGamma</code>呈现为$\varGamma$。</p><h2 id="关系运算符"><a href="#关系运算符" class="headerlink" title="关系运算符"></a>关系运算符</h2><div class="table-container"><table><thead><tr><th style="text-align:center">符号</th><th>命令</th><th>名称</th><th style="text-align:center">符号</th><th>命令</th><th>名称</th></tr></thead><tbody><tr><td style="text-align:center">$\gt$</td><td>\gt</td><td>大于</td><td style="text-align:center">$\ngtr$</td><td>\ngtr</td><td>不大于</td></tr><tr><td style="text-align:center">$\lt$</td><td>\lt</td><td>小于</td><td style="text-align:center">$\nless$</td><td>\nless</td><td>不小于</td></tr><tr><td style="text-align:center">$\ge$</td><td>\ge</td><td>大于等于</td><td style="text-align:center">$\ngeqslant$</td><td>\ngeqslant</td><td>不大于等于</td></tr><tr><td style="text-align:center">$\le$</td><td>\le</td><td>小于等于</td><td style="text-align:center">$\nleqslant$</td><td>\nleqslant</td><td>不小于等于</td></tr><tr><td style="text-align:center">$\gg$</td><td>\gg</td><td>远大于</td></tr><tr><td style="text-align:center">$\ll$</td><td>\ll</td><td>远小于</td></tr><tr><td style="text-align:center">$\neq$</td><td>\neq</td><td>不等于</td></tr><tr><td style="text-align:center">$\doteq$</td><td>\doteq</td><td>点等于</td></tr><tr><td style="text-align:center">$\sim$</td><td>\sim</td><td>相似于</td><td style="text-align:center">$\not\sim$</td><td>\not\sim</td><td>不相似于</td></tr><tr><td style="text-align:center">$\simeq$</td><td>\simeq</td><td>近似等于</td><td style="text-align:center">$\not\simeq$</td><td>\not\simeq</td><td>不近似等于</td></tr><tr><td style="text-align:center">$\approx$</td><td>\approx</td><td>约等于</td><td style="text-align:center">$\not\approx$</td><td>\not\approx</td><td>不约等于</td></tr><tr><td style="text-align:center">$\asymp$</td><td>\asymp</td><td>趋于</td><td style="text-align:center">$\not\asymp$</td><td>\not\asymp</td><td>不趋于</td></tr><tr><td style="text-align:center">$\cong$</td><td>\cong</td><td>全等于</td><td style="text-align:center">$\not\cong$</td><td>\not\cong</td><td>不全等于</td></tr><tr><td style="text-align:center">$\equiv$</td><td>\equiv</td><td>恒等于</td><td style="text-align:center">$\not\equiv$</td><td>\not\equiv</td><td>不恒等于</td></tr><tr><td style="text-align:center">$\subset$</td><td>\subset</td><td>子集</td></tr><tr><td style="text-align:center">$\supset$</td><td>\supset</td><td>超集</td></tr><tr><td style="text-align:center">$\subseteq$</td><td>\subseteq</td><td>子集或等于</td></tr><tr><td style="text-align:center">$\supseteq$</td><td>\supseteq</td><td>超集或等于</td></tr><tr><td style="text-align:center">$\sqsubseteq$</td><td>\sqsubseteq</td><td>方形子集或等于</td></tr><tr><td style="text-align:center">$\sqsupseteq$</td><td>\sqsupseteq</td><td>方形超集或等于</td></tr><tr><td style="text-align:center">$\in$</td><td>\in</td><td>包含于</td></tr><tr><td style="text-align:center">$\ni$</td><td>\ni</td><td>包含</td></tr><tr><td style="text-align:center">$\notin$</td><td>\notin</td><td>不包含于</td></tr><tr><td style="text-align:center">$\models$</td><td>\models</td><td>Models</td></tr><tr><td style="text-align:center">$\vdash$</td><td>\vdash</td><td>竖线短横</td></tr><tr><td style="text-align:center">$\dashv$</td><td>\dashv</td><td>短横竖线</td></tr><tr><td style="text-align:center">$\perp$</td><td>\perp</td><td>垂直</td></tr><tr><td style="text-align:center">$\mid$</td><td>\mid</td><td>中线</td></tr><tr><td style="text-align:center">$\parallel$</td><td>\parallel</td><td>平行</td></tr><tr><td style="text-align:center">$\propto$</td><td>\propto</td><td>成比例</td></tr><tr><td style="text-align:center">$\bowtie$</td><td>\bowtie</td><td>领结</td></tr><tr><td style="text-align:center">$\prec$</td><td>\prec</td><td>先于</td></tr><tr><td style="text-align:center">$\preceq$</td><td>\preceq</td><td>先于等于</td></tr><tr><td style="text-align:center">$\succ$</td><td>\succ</td><td>后于</td></tr><tr><td style="text-align:center">$\succeq$</td><td>\succeq</td><td>后于等于</td></tr></tbody></table></div><h2 id="括号"><a href="#括号" class="headerlink" title="括号"></a>括号</h2><div class="table-container"><table><thead><tr><th style="text-align:center">符号</th><th>命令</th><th>名称</th><th style="text-align:center">符号</th><th>命令</th><th>名称</th></tr></thead><tbody><tr><td style="text-align:center">$\lbrace$</td><td>\lbrace</td><td>左花括号</td><td style="text-align:center">$\rbrace$</td><td>\rbrace</td><td>右花括号</td></tr><tr><td style="text-align:center">$\lbrack$</td><td>\lbrack</td><td>左方括号</td><td style="text-align:center">$\rbrack$</td><td>\rbrack</td><td>右方括号</td></tr><tr><td style="text-align:center">$\langle$</td><td>\langle</td><td>左尖括号</td><td style="text-align:center">$\rangle$</td><td>\rangle</td><td>右尖括号</td></tr><tr><td style="text-align:center">$\lceil$</td><td>\lceil</td><td>左上半框括号</td><td style="text-align:center">$\rceil$</td><td>\rceil</td><td>右上半框括号</td></tr><tr><td style="text-align:center">$\lfloor$</td><td>\lfloor</td><td>左下半框括号</td><td style="text-align:center">$\rfloor$</td><td>\rfloor</td><td>右下半框括号</td></tr><tr><td style="text-align:center"></td><td>.</td><td>不可见括号</td><td style="text-align:center"></td><td></td></tr></tbody></table></div><p>小括号使用原始的<code>()</code>，方括号可以使用原始的<code>[]</code>，也可以使用<code>\lbrack</code>和<code>\rbrack</code>。</p><div class="table-container"><table><thead><tr><th style="text-align:center">未自适应括号</th><th>命令</th><th style="text-align:center">自适应括号</th><th>命令</th></tr></thead><tbody><tr><td style="text-align:center">$(\frac{x}{y})$</td><td>(\frac{x}{y})</td><td style="text-align:center">$\left(\frac{x}{y}\right)$</td><td>\left(\frac{x}{y}\right)</td></tr><tr><td style="text-align:center">$[\frac{x}{y}]$</td><td>[\frac{x}{y}]</td><td style="text-align:center">$\left[\frac{x}{y}\right]$</td><td>\left[\frac{x}{y}\right]</td></tr><tr><td style="text-align:center">$\lbrace\frac{x}{y}\rbrace$</td><td>\lbrace\frac{x}{y}\rbrace</td><td style="text-align:center">$\left\lbrace\frac{x}{y}\right\rbrace$</td><td>\left\lbrace\frac{x}{y}\right\rbrace</td></tr></tbody></table></div><p>自适应括号使用<code>\left</code>和<code>\right</code>。小括号自适应为<code>\left(</code>和<code>\right)</code>，中括号自适应为<code>\left[</code>和<code>\right]</code>，大括号自适应为<code>\left\lbrace</code>和<code>\right\rbrace</code>。</p><h2 id="箭头符号"><a href="#箭头符号" class="headerlink" title="箭头符号"></a>箭头符号</h2><div class="table-container"><table><thead><tr><th style="text-align:center">符号</th><th>命令</th><th>名称</th><th style="text-align:center">符号</th><th>命令</th><th>名称</th></tr></thead><tbody><tr><td style="text-align:center">$\leftarrow$</td><td>\leftarrow</td><td>左箭头</td><td style="text-align:center">$\rightarrow$</td><td>\rightarrow</td><td>右箭头</td></tr><tr><td style="text-align:center">$\Leftarrow$</td><td>\Leftarrow</td><td>左双线箭头</td><td style="text-align:center">$\Rightarrow$</td><td>\Rightarrow</td><td>右双线箭头</td></tr><tr><td style="text-align:center">$\longleftarrow$</td><td>\longleftarrow</td><td>长左箭头</td><td style="text-align:center">$\longrightarrow$</td><td>\longrightarrow</td><td>长右箭头</td></tr><tr><td style="text-align:center">$\Longleftarrow$</td><td>\Longleftarrow</td><td>长双线左箭头</td><td style="text-align:center">$\Longrightarrow$</td><td>\Longrightarrow</td><td>长双线右箭头</td></tr><tr><td style="text-align:center">$\leftrightarrow$</td><td>\leftrightarrow</td><td>左右双向箭头</td><td style="text-align:center">$\Leftrightarrow$</td><td>\Leftrightarrow</td><td>左右双向双线箭头</td></tr><tr><td style="text-align:center">$\longleftrightarrow$</td><td>\longleftrightarrow</td><td>长左右双向箭头</td><td style="text-align:center">$\Longleftrightarrow$</td><td>\Longleftrightarrow</td><td>长左右双向双线箭头</td></tr><tr><td style="text-align:center">$\hookleftarrow$</td><td>\hookleftarrow</td><td>弯钩左箭头</td><td style="text-align:center">$\hookrightarrow$</td><td>\hookrightarrow</td><td>弯钩右箭头</td></tr><tr><td style="text-align:center">$\leftharpoonup$</td><td>\leftharpoonup</td><td>上半钩左箭头</td><td style="text-align:center">$\rightharpoonup$</td><td>\rightharpoonup</td><td>上半钩右箭头</td></tr><tr><td style="text-align:center">$\leftharpoondown$</td><td>\leftharpoondown</td><td>下半钩左箭头</td><td style="text-align:center">$\rightharpoondown$</td><td>\rightharpoondown</td><td>下半钩右箭头</td></tr><tr><td style="text-align:center">$\uparrow$</td><td>\uparrow</td><td>上箭头</td><td style="text-align:center">$\downarrow$</td><td>\downarrow</td><td>下箭头</td></tr><tr><td style="text-align:center">$\Uparrow$</td><td>\Uparrow</td><td>上双线箭头</td><td style="text-align:center">$\Downarrow$</td><td>\Downarrow</td><td>下双线箭头</td></tr><tr><td style="text-align:center">$\updownarrow$</td><td>\updownarrow</td><td>上下双向箭头</td><td style="text-align:center">$\Updownarrow$</td><td>\Updownarrow</td><td>上下双向双线箭头</td></tr><tr><td style="text-align:center">$\nwarrow$</td><td>\nwarrow</td><td>左斜上箭头</td><td style="text-align:center">$\nearrow$</td><td>\nearrow</td><td>右斜上箭头</td></tr><tr><td style="text-align:center">$\swarrow$</td><td>\swarrow</td><td>左斜下箭头</td><td style="text-align:center">$\searrow$</td><td>\searrow</td><td>右斜下箭头</td></tr><tr><td style="text-align:center">$\mapsto$</td><td>\mapsto</td><td>映射箭头</td><td style="text-align:center">$\longmapsto$</td><td>\longmapsto</td><td>长映射箭头</td></tr></tbody></table></div><h2 id="表格"><a href="#表格" class="headerlink" title="表格"></a>表格</h2><p>使用<code>$$\begin{array}{列样式}...\end{array}$$</code>来表示表格。</p><p>列样式可以是<code>clr|</code>。<code>c</code>表示居中对齐，<code>l</code>表示左对齐，<code>r</code>表示右对齐，<code>|</code>表示一条竖线。</p><p>表格中各行使用<code>\\</code>分隔，各列使用<code>&amp;</code>分隔，<code>\hline</code>表示一条横线。</p><pre><code>$$\begin{array}{c|lcr}    n &amp; \text{Left} &amp; \text{Center} &amp; \text{Right} \\    \hline 1 &amp; 0.24 &amp; 1 &amp; 125 \\    2 &amp; -1 &amp; 189 &amp; -8 \\    3 &amp; -20 &amp; 2000 &amp; 1+10i\end{array}$$</code></pre><script type="math/tex; mode=display">\begin{array}{c|lcr}    n & \text{Left} & \text{Center} & \text{Right} \\    \hline 1 & 0.24 & 1 & 125 \\    2 & -1 & 189 & -8 \\    3 & -20 & 2000 & 1+10i\end{array}</script><h2 id="矩阵"><a href="#矩阵" class="headerlink" title="矩阵"></a>矩阵</h2><h3 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h3><p>使用<code>$$\begin{matrix}...\end{matrix}$$</code>来表示矩阵。</p><pre><code>$$\begin{matrix}    1 &amp; x &amp; x^2 \\    1 &amp; y &amp; y^2 \\    1 &amp; z &amp; z^2\end{matrix}$$</code></pre><script type="math/tex; mode=display">\begin{matrix}    1 & x & x^2 \\    1 & y & y^2 \\    1 & z & z^2\end{matrix}</script><h3 id="加括号"><a href="#加括号" class="headerlink" title="加括号"></a>加括号</h3><p>如果要对矩阵加括号，可以像上文中提到的那样，使用<code>\left</code>与<code>\right</code>配合表示括号符号。也可以使用特殊的<code>matrix</code>，即替换<code>$$\begin{matrix}...\end{matrix}$$</code>中的<code>matrix</code>为<code>pmatrix</code>，<code>bmatrix</code>，<code>Bmatrix</code>，<code>vmatrix</code>，<code>Vmatrix</code>。</p><p>pmatrix：<script type="math/tex">\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}</script>，bmatrix：<script type="math/tex">\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}</script>，Bmatrix：<script type="math/tex">\begin{Bmatrix} 1 & 2 \\ 3 & 4 \end{Bmatrix}</script>，vmatrix：<script type="math/tex">\begin{vmatrix} 1 & 2 \\ 3 & 4 \end{vmatrix}</script>，Vmatrix：<script type="math/tex">\begin{Vmatrix} 1 & 2 \\ 3 & 4 \end{Vmatrix}</script>。</p><h3 id="省略元素"><a href="#省略元素" class="headerlink" title="省略元素"></a>省略元素</h3><p>可以使用<code>\cdots</code>：<code>⋯</code>，<code>\ddots</code>：<code>⋱</code>，<code>\vdots</code>：<code>⋮</code>来省略矩阵中的元素。</p><pre><code>$$\begin{pmatrix}    a_1 &amp; a_1^2 &amp; a_1^3 &amp; \cdots &amp; a_1^n \\    a_2 &amp; a_2^2 &amp; a_2^3 &amp; \cdots &amp; a_2^n \\    \vdots &amp; \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\    a_m &amp; a_m^2 &amp; a_m^3 &amp; \cdots &amp; a_m^n\end{pmatrix}$$</code></pre><script type="math/tex; mode=display">\begin{pmatrix}    a_1 & a_1^2 & a_1^3 & \cdots & a_1^n \\    a_2 & a_2^2 & a_2^3 & \cdots & a_2^n \\    \vdots & \vdots & \vdots & \ddots & \vdots \\    a_m & a_m^2 & a_m^3 & \cdots & a_m^n\end{pmatrix}</script><h3 id="增广矩阵"><a href="#增广矩阵" class="headerlink" title="增广矩阵"></a>增广矩阵</h3><p>增广矩阵需要使用前面的<code>array</code>来实现。</p><pre><code>$$ \left[    \begin{array}{cc|c}        1 &amp; 2 &amp; 3 \\        4 &amp; 5 &amp; 6    \end{array}\right] $$</code></pre><script type="math/tex; mode=display">\left[    \begin{array}{cc|c}        1 & 2 & 3 \\        4 & 5 & 6    \end{array}\right]</script><h2 id="对齐公式"><a href="#对齐公式" class="headerlink" title="对齐公式"></a>对齐公式</h2><p>使用<code>$$\begin{align}...\end{align}$$</code>来对齐公式。其中需要使用<code>&amp;</code>来指示需要对齐的位置。</p><pre><code>$$\begin{align}    \sqrt{37} &amp; = \sqrt{\frac{73^2-1}{12^2}} \\    &amp; = \sqrt{\frac{73^2}{12^2} \cdot \frac{73^2-1}{73^2}} \\    &amp; = \frac{73}{12} \sqrt{1 - \frac{1}{73^2}} \\    &amp; \approx \frac{73}{12} \left( 1 - \frac{1}{2 \cdot 73^2} \right)\end{align}$$</code></pre><script type="math/tex; mode=display">\begin{align}    \sqrt{37} & = \sqrt{\frac{73^2-1}{12^2}} \\    & = \sqrt{\frac{73^2}{12^2} \cdot \frac{73^2-1}{73^2}} \\    & = \frac{73}{12} \sqrt{1 - \frac{1}{73^2}} \\    & \approx \frac{73}{12} \left( 1 - \frac{1}{2 \cdot 73^2} \right)\end{align}</script><h2 id="分类表达式"><a href="#分类表达式" class="headerlink" title="分类表达式"></a>分类表达式</h2><p>使用<code>$$\begin{cases}...\end{cases}$$</code>来分类表达式。其中需要使用<code>&amp;</code>来指示需要对齐的位置。</p><pre><code>$$f(n) =    \begin{cases}        n/2, &amp; \text{if $n$ is even} \\        3n+1, &amp; \text{if $n$ is odd}    \end{cases}$$</code></pre><script type="math/tex; mode=display">f(n) =    \begin{cases}        n/2, & \text{if $n$ is even} \\        3n+1, & \text{if $n$ is odd}    \end{cases}</script><p>上述公式也可以移动到右侧，不过需要使用array来实现，如下：</p><pre><code>$$    \left. \begin{array}{l}        \text{if $n$ is even:} &amp; n/2 \\        \text{if $n$ is odd:} &amp; 3n+1    \end{array} \right\} = f(n)$$</code></pre><script type="math/tex; mode=display">    \left. \begin{array}{l}        \text{if $n$ is even:} & n/2 \\        \text{if $n$ is odd:} & 3n+1    \end{array} \right\} = f(n)</script><h2 id="字体"><a href="#字体" class="headerlink" title="字体"></a>字体</h2><div class="table-container"><table><thead><tr><th>字体</th><th>命令</th><th>显示</th></tr></thead><tbody><tr><td>默认字体</td><td></td><td>$ABCDEFGHIJKLMNOPQRSTUVWXYZ$ <br> $abcdefghijklmnopqrstuvwxyz$ <br> $0123456789$</td></tr><tr><td>数学斜体</td><td>\mit</td><td>$\it{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\mit{abcdefghijklmnopqrstuvwxyz}$ <br> $\mit{0123456789}$</td></tr><tr><td>意大利体</td><td>\it</td><td>$\it{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\it{abcdefghijklmnopqrstuvwxyz}$ <br> $\it{0123456789}$</td></tr><tr><td>罗马体</td><td>\rm</td><td>$\rm{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\rm{abcdefghijklmnopqrstuvwxyz}$ <br> $\rm{0123456789}$</td></tr><tr><td>花体</td><td>\cal</td><td>$\cal{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\cal{abcdefghijklmnopqrstuvwxyz}$ <br> $\cal{0123456789}$</td></tr><tr><td>打字机体</td><td>\tt</td><td>$\tt{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\tt{abcdefghijklmnopqrstuvwxyz}$ <br> $\tt{0123456789}$</td></tr><tr><td>等线体</td><td>\sf</td><td>$\sf{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\sf{abcdefghijklmnopqrstuvwxyz}$ <br> $\sf{0123456789}$</td></tr><tr><td>粗体</td><td>\bf</td><td>$\bf{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\bf{abcdefghijklmnopqrstuvwxyz}$ <br> $\bf{0123456789}$</td></tr><tr><td>黑板粗体</td><td>\Bbb</td><td>$\Bbb{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\Bbb{abcdefghijklmnopqrstuvwxyz}$ <br> $\Bbb{0123456789}$</td></tr><tr><td>手写体</td><td>\scr</td><td>$\scr{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\scr{abcdefghijklmnopqrstuvwxyz}$ <br> $\scr{0123456789}$</td></tr><tr><td>旧德式体</td><td>\frak</td><td>$\frak{ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ <br> $\frak{abcdefghijklmnopqrstuvwxyz}$ <br> $\sf{0123456789}$</td></tr></tbody></table></div><p>字体设置：<code>$\字体种类{文本}$</code>。</p><h2 id="字体大小"><a href="#字体大小" class="headerlink" title="字体大小"></a>字体大小</h2><div class="table-container"><table><thead><tr><th>字体大小</th><th>字宽(pt)</th><th>命名</th><th>显示</th></tr></thead><tbody><tr><td>小初</td><td>36 pts</td><td>\Huge{小初字体(36pts)}</td><td>$\Huge{小初字体(36pts)}$</td></tr><tr><td>一号</td><td>27.5 pts</td><td>\huge{一号字体(27.5pts)}</td><td>$\huge{一号字体(27.5pts)}$</td></tr><tr><td>二号</td><td>21 pts</td><td>\LARGE{二号字体(21pts)}</td><td>$\LARGE{二号字体(21pts)}$</td></tr><tr><td>三号</td><td>15.75 pts</td><td>\Large{三号字体(15.75pts)}</td><td>$\Large{三号字体(15.75pts)}$</td></tr><tr><td>四号</td><td>13.75 pts</td><td>\large{四号字体(13.75pts)}</td><td>$\large{四号字体(13.75pts)}$</td></tr><tr><td>小四</td><td>12 pts</td><td>\normalsize{小四字体(12pts)}</td><td>$\normalsize{小四字体(12pts)}$</td></tr><tr><td>默认</td><td>12 pts</td><td>默认字体(12pts)</td><td>$默认字体(12pts)$</td></tr><tr><td>五号</td><td>10.5 pts</td><td>\small{五号字体(10.5pts)}</td><td>$\small{五号字体(10.5pts)}$</td></tr><tr><td>六号</td><td>7.875 pts</td><td>\scriptsize{六号字体(7.875pts)}</td><td>$\scriptsize{六号字体(7.875pts)}$</td></tr><tr><td>七号</td><td>5.25 pts</td><td>\tiny{七号字体(5.25pts)}</td><td>$\tiny{七号字体(5.25pts)}$</td></tr></tbody></table></div><p>字体大小设置：<code>$\字体大小{文本}$</code>。</p><h2 id="字体特效"><a href="#字体特效" class="headerlink" title="字体特效"></a>字体特效</h2><div class="table-container"><table><thead><tr><th>字体特效</th><th>命令</th><th>显示</th></tr></thead><tbody><tr><td>下划线</td><td>\underline{下划线}​</td><td>$\underline{下划线}​$</td></tr><tr><td>水平删除线</td><td>\enclose{horizontalstrike}{水平删除线}​</td><td>$\enclose{horizontalstrike}{水平删除线}​$</td></tr><tr><td>垂直删除线</td><td>\enclose{verticalstrike}{垂直删除线}​</td><td>$\enclose{verticalstrike}{垂直删除线}​$</td></tr><tr><td>上对角删除线</td><td>\enclose{updiagonalstrike}{上对角删除线}​</td><td>$\enclose{updiagonalstrike}{上对角删除线}​$</td></tr><tr><td>下对角删除线</td><td>\enclose{downdiagonalstrike}{下对角删除线}​</td><td>$\enclose{downdiagonalstrike}{下对角删除线}​$</td></tr><tr><td>组合多种删除线</td><td>\enclose{horizontalstrike,verticalstrike,updiagonalstrike,downdiagonalstrike}{组合多种删除线}​</td><td>$\enclose{horizontalstrike,verticalstrike,updiagonalstrike,downdiagonalstrike}{组合多种删除线}​$</td></tr></tbody></table></div><h2 id="字体颜色"><a href="#字体颜色" class="headerlink" title="字体颜色"></a>字体颜色</h2><div class="table-container"><table><thead><tr><th>字体颜色</th><th>命令</th><th>显示</th></tr></thead><tbody><tr><td>黑色(black)</td><td>\color{black}{黑色(\text{black})}​</td><td>$\color{black}{黑色(\text{black})}​$</td></tr><tr><td>灰色(grey)</td><td>\color{grey}{灰色(\text{grey})}​</td><td>$\color{grey}{灰色(\text{grey})}​$</td></tr><tr><td>银色(silver)</td><td>\color{silver}{银色(\text{silver})}​</td><td>$\color{silver}{银色(\text{silver})}$</td></tr><tr><td>白色(white)</td><td>\color{white}{白色(\text{white})}​</td><td>$\color{white}{白色(\text{white})}​$</td></tr><tr><td>紫红色(maroon)</td><td>\color{maroon}{紫红色(\text{maroon})}​</td><td>$\color{maroon}{紫红色(\text{maroon})}$</td></tr><tr><td>红色(red)</td><td>\color{red}{红色(\text{red})}​</td><td>$\color{red}{红色(\text{red})}​$</td></tr><tr><td>紫色(purple)</td><td>\color{purple}{紫色(\text{purple})}​</td><td>$\color{purple}{紫色(\text{purple})}​$</td></tr><tr><td>黄色(yellow)</td><td>\color{yellow}{黄色(\text{yellow})}​</td><td>$\color{yellow}{黄色(\text{yellow})}​$</td></tr><tr><td>橄榄绿(olive)</td><td>\color{olive}{橄榄绿(\text{olive})}​</td><td>$\color{olive}{橄榄绿(\text{olive})}$</td></tr><tr><td>浅绿色(lime)</td><td>\color{lime}{浅绿色(\text{lime})}​</td><td>$\color{lime}{浅绿色(\text{lime})}$</td></tr><tr><td>绿色(green)</td><td>\color{green}{绿色(\text{green})}​</td><td>$\color{green}{绿色(\text{green})}​$</td></tr><tr><td>藏青色(navy)</td><td>\color{navy}{藏青色(\text{navy})}​</td><td>$\color{navy}{藏青色(\text{navy})}$</td></tr><tr><td>蓝色(blue)</td><td>\color{blue}{蓝色(\text{blue})}​</td><td>$\color{blue}{蓝色(\text{blue})}​$</td></tr><tr><td>蓝绿色(teal)</td><td>\color{teal}{蓝绿色(\text{teal})}​</td><td>$\color{teal}{蓝绿色(\text{teal})}$</td></tr></tbody></table></div><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>（一）PyTorch 张量</title>
    <link href="https://blog.wpz.homes/posts/668e89ae/"/>
    <id>https://blog.wpz.homes/posts/668e89ae/</id>
    <published>2024-08-26T08:17:41.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="Tensor-数据类型"><a href="#Tensor-数据类型" class="headerlink" title="Tensor 数据类型"></a>Tensor 数据类型</h2><div class="table-container"><table><thead><tr><th>Data type</th><th>dtype</th><th>CPU Tensor</th><th>GPU Tensor</th></tr></thead><tbody><tr><td>Boolean</td><td>torch.bool</td><td>torch.BoolTensor</td><td>torch.cuda.BoolTensor</td></tr><tr><td>8-bit integer (unsigned)</td><td>torch.uint8</td><td>torch.ByteTensor</td><td>torch.cuda.ByteTensor</td></tr><tr><td>8-bit integer (signed)</td><td>torch.int8</td><td>torch.CharTensor</td><td>torch.cuda.CharTensor</td></tr><tr><td>16-bit integer (signed)</td><td>torch.int16 or torch.short</td><td>torch.ShortTensor</td><td>torch.cuda.ShortTensor</td></tr><tr><td>32-bit integer (signed)</td><td>torch.int32 or torch.int</td><td>torch.IntTensor</td><td>torch.cuda.IntTensor</td></tr><tr><td>64-bit integer (signed)</td><td>torch.int64 or torch.long</td><td>torch.LongTensor</td><td>torch.cuda.LongTensor</td></tr><tr><td>16-bit floating point</td><td>torch.float16 or torch.half</td><td>torch.HalfTensor</td><td>torch.cuda.HalfTensor</td></tr><tr><td>16-bit floating point</td><td>torch.bfloat16</td><td>torch.BFloat16Tensor</td><td>torch.cuda.BFloat16Tensor</td></tr><tr><td>32-bit floating point</td><td>torch.float32 or torch.float</td><td>torch.FloatTensor</td><td>torch.cuda.FloatTensor</td></tr><tr><td>64-bit floating point</td><td>torch.float64 or torch.double</td><td>torch.DoubleTensor</td><td>torch.cuda.DoubleTensor</td></tr></tbody></table></div><h2 id="设置-Tensor-默认类型"><a href="#设置-Tensor-默认类型" class="headerlink" title="设置 Tensor 默认类型"></a>设置 Tensor 默认类型</h2><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="literal">True</span>).dtype)  <span class="comment"># torch.bool</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="literal">True</span>).<span class="built_in">type</span>())  <span class="comment"># torch.BoolTensor</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1</span>).dtype)  <span class="comment"># torch.int64</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1</span>).<span class="built_in">type</span>())  <span class="comment"># torch.LongTensor</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1.</span>).dtype)  <span class="comment"># torch.float32</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1.</span>).<span class="built_in">type</span>())  <span class="comment"># torch.FloatTensor</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">3j</span>).dtype)  <span class="comment"># torch.complex64</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">3j</span>).<span class="built_in">type</span>())  <span class="comment"># torch.ComplexFloatTensor</span></span><br><span class="line"></span><br><span class="line">torch.set_default_dtype(torch.double)  <span class="comment"># 设置默认类型为 double</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="literal">True</span>).dtype)  <span class="comment"># torch.bool</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="literal">True</span>).<span class="built_in">type</span>())  <span class="comment"># torch.BoolTensor</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1</span>).dtype)  <span class="comment"># torch.int64</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1</span>).<span class="built_in">type</span>())  <span class="comment"># torch.LongTensor</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1.</span>).dtype)  <span class="comment"># torch.float64</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1.</span>).<span class="built_in">type</span>())  <span class="comment"># torch.DoubleTensor</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">3j</span>).dtype)  <span class="comment"># torch.complex128</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">3j</span>).<span class="built_in">type</span>())  <span class="comment"># torch.ComplexDoubleTensor</span></span><br></pre></td></tr></tbody></table></figure><p><code>set_default_dtype()</code>只能设置<code>floating-point</code>类型，否则会报<code>TypeError: only floating-point types are supported as the default type</code>错误。</p><h2 id="标量与张量"><a href="#标量与张量" class="headerlink" title="标量与张量"></a>标量与张量</h2><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 标量</span></span><br><span class="line">a = torch.tensor(<span class="number">1</span>)</span><br><span class="line"><span class="built_in">print</span>(a.shape)  <span class="comment"># torch.Size([])</span></span><br><span class="line"><span class="built_in">print</span>(a.size())  <span class="comment"># torch.Size([])</span></span><br><span class="line"><span class="built_in">print</span>(a.ndim)  <span class="comment"># 0</span></span><br><span class="line"><span class="built_in">print</span>(a.dim())  <span class="comment"># 0</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 一维张量</span></span><br><span class="line">b = torch.tensor([<span class="number">1</span>, <span class="number">2</span>])</span><br><span class="line"><span class="built_in">print</span>(b.shape)  <span class="comment"># torch.Size([2])</span></span><br><span class="line"><span class="built_in">print</span>(b.size())  <span class="comment"># torch.Size([2])</span></span><br><span class="line"><span class="built_in">print</span>(b.ndim)  <span class="comment"># 1</span></span><br><span class="line"><span class="built_in">print</span>(b.dim())  <span class="comment"># 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 二维张量</span></span><br><span class="line">c = torch.tensor([[<span class="number">1</span>, <span class="number">2</span>]])</span><br><span class="line"><span class="built_in">print</span>(c.shape)  <span class="comment"># torch.Size([1, 2])</span></span><br><span class="line"><span class="built_in">print</span>(c.size())  <span class="comment"># torch.Size([1, 2])</span></span><br><span class="line"><span class="built_in">print</span>(c.ndim)  <span class="comment"># 2</span></span><br><span class="line"><span class="built_in">print</span>(c.dim())  <span class="comment"># 2</span></span><br></pre></td></tr></tbody></table></figure><p>标量是一个单独的数，<code>ndim</code>为<code>0</code>。</p><h2 id="创建-Tensor"><a href="#创建-Tensor" class="headerlink" title="创建 Tensor"></a>创建 Tensor</h2><h3 id="tensor"><a href="#tensor" class="headerlink" title=".tensor"></a>.tensor</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 标量</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1</span>))  <span class="comment"># tensor(1)</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor(<span class="number">1</span>, dtype=torch.float64))  <span class="comment"># tensor(1., dtype=torch.float64)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 张量</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor([<span class="number">1</span>, <span class="number">2</span>]))  <span class="comment"># tensor([1, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor([<span class="number">1</span>, <span class="number">2</span>], dtype=torch.float64))  <span class="comment"># tensor([1., 2.], dtype=torch.float64)</span></span><br></pre></td></tr></tbody></table></figure><h3 id="from-numpy"><a href="#from-numpy" class="headerlink" title=".from_numpy"></a>.from_numpy</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = np.array([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>])</span><br><span class="line"><span class="built_in">print</span>(torch.from_numpy(data))  <span class="comment"># tensor([1, 2, 3], dtype=torch.int32)</span></span><br><span class="line">data = np.array([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>], dtype=np.float64)</span><br><span class="line"><span class="built_in">print</span>(torch.from_numpy(data))  <span class="comment"># tensor([1., 2., 3.], dtype=torch.float64)</span></span><br></pre></td></tr></tbody></table></figure><h3 id="Tensor"><a href="#Tensor" class="headerlink" title="Tensor"></a>Tensor</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 参数为 shape 大小</span></span><br><span class="line"><span class="built_in">print</span>(torch.Tensor(<span class="number">1</span>))  <span class="comment"># tensor([-3.0434e+31])</span></span><br><span class="line"><span class="built_in">print</span>(torch.Tensor(<span class="number">1</span>, <span class="number">2</span>))  <span class="comment"># tensor([[0., 0.]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.Tensor(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[[-3.0741e+31,  1.6031e-42,  0.0000e+00],</span></span><br><span class="line"><span class="string">         [ 0.0000e+00,  0.0000e+00,  0.0000e+00]]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 参数为列表</span></span><br><span class="line"><span class="built_in">print</span>(torch.Tensor([<span class="number">1</span>]))  <span class="comment"># tensor([1.])</span></span><br><span class="line"><span class="built_in">print</span>(torch.Tensor([<span class="number">1</span>, <span class="number">2</span>]))  <span class="comment"># tensor([1., 2.])</span></span><br><span class="line"><span class="built_in">print</span>(torch.Tensor([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]))  <span class="comment"># tensor([1., 2., 3.])</span></span><br></pre></td></tr></tbody></table></figure><p><code>Tensor</code>支持两种传参方式：</p><ol><li>当参数为列表时，创建列表对应维度的<code>Tensor</code>并初始化数据为列表数据。</li><li>当参数不为列表时，与<code>.empty()</code>类似，创建参数指定的<code>shape</code>的空的<code>Tensor</code>。</li></ol><p><code>BoolTensor</code>、<code>ByteTensor</code>、<code>CharTensor</code>、<code>ShortTensor</code>、<code>IntTensor</code>、<code>LongTensor</code>、<code>HalfTensor</code>、<code>FloatTensor</code>、<code>DoubleTensor</code>也是一样。</p><h3 id="empty-zeros-ones-full-eye"><a href="#empty-zeros-ones-full-eye" class="headerlink" title=".empty/.zeros/.ones/.full/.eye"></a>.empty/.zeros/.ones/.full/.eye</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">input</span> = torch.tensor([<span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>])</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.empty(()))  <span class="comment"># tensor(-6.5391e-19)</span></span><br><span class="line"><span class="built_in">print</span>(torch.empty((<span class="number">1</span>, <span class="number">5</span>)))  <span class="comment"># tensor([[-6.6069e-19,  1.3943e-42,  0.0000e+00,  0.0000e+00,  0.0000e+00]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.empty_like((<span class="built_in">input</span>)))  <span class="comment"># tensor([0, 0, 0, 0, 0])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.zeros(()))  <span class="comment"># tensor(0.)</span></span><br><span class="line"><span class="built_in">print</span>(torch.zeros((<span class="number">1</span>, <span class="number">5</span>)))  <span class="comment"># tensor([[0., 0., 0., 0., 0.]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.zeros_like((<span class="built_in">input</span>)))  <span class="comment"># tensor([0, 0, 0, 0, 0])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.ones(()))  <span class="comment"># tensor(1.)</span></span><br><span class="line"><span class="built_in">print</span>(torch.ones((<span class="number">1</span>, <span class="number">5</span>)))  <span class="comment"># tensor([[1., 1., 1., 1., 1.]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.ones_like((<span class="built_in">input</span>)))  <span class="comment"># tensor([1, 1, 1, 1, 1])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.full((), <span class="number">100</span>))  <span class="comment"># tensor(100)</span></span><br><span class="line"><span class="built_in">print</span>(torch.full((<span class="number">1</span>, <span class="number">5</span>), <span class="number">100</span>))  <span class="comment"># tensor([[100, 100, 100, 100, 100]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.full_like((<span class="built_in">input</span>), <span class="number">100</span>))  <span class="comment"># tensor([100, 100, 100, 100, 100])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.eye(<span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1., 0., 0.],</span></span><br><span class="line"><span class="string">        [0., 1., 0.],</span></span><br><span class="line"><span class="string">        [0., 0., 1.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.eye(<span class="number">3</span>, <span class="number">5</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1., 0., 0., 0., 0.],</span></span><br><span class="line"><span class="string">        [0., 1., 0., 0., 0.],</span></span><br><span class="line"><span class="string">        [0., 0., 1., 0., 0.]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="arange-linspace-logspace"><a href="#arange-linspace-logspace" class="headerlink" title=".arange/.linspace/.logspace"></a>.arange/.linspace/.logspace</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.arange(<span class="number">0</span>, <span class="number">10</span>))  <span class="comment"># tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])</span></span><br><span class="line"><span class="built_in">print</span>(torch.arange(<span class="number">0</span>, <span class="number">10</span>, step=<span class="number">3</span>))  <span class="comment"># tensor([0, 3, 6, 9])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># [0, 1] 等分成 5 份</span></span><br><span class="line"><span class="built_in">print</span>(torch.linspace(<span class="number">0</span>, <span class="number">1</span>, steps=<span class="number">5</span>))  <span class="comment"># tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 默认以 10 为底数，[0, 1] 等分成 5 份做为指数</span></span><br><span class="line"><span class="built_in">print</span>(torch.logspace(<span class="number">0</span>, <span class="number">1</span>, steps=<span class="number">5</span>))  <span class="comment"># tensor([ 1.0000,  1.7783,  3.1623,  5.6234, 10.0000])</span></span><br><span class="line"><span class="comment"># 以 2 为底数，[0, 1] 等分成 5 份做为指数</span></span><br><span class="line"><span class="built_in">print</span>(torch.logspace(<span class="number">0</span>, <span class="number">1</span>, steps=<span class="number">5</span>, base=<span class="number">2</span>))  <span class="comment"># tensor([1.0000, 1.1892, 1.4142, 1.6818, 2.0000])</span></span><br></pre></td></tr></tbody></table></figure><h2 id="随机采样"><a href="#随机采样" class="headerlink" title="随机采样"></a>随机采样</h2><h3 id="随机种子"><a href="#随机种子" class="headerlink" title="随机种子"></a>随机种子</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置 CPU 随机种子</span></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置 GPU 随机种子</span></span><br><span class="line">torch.cuda.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看设置的随机种子</span></span><br><span class="line"><span class="built_in">print</span>(torch.initial_seed())  <span class="comment"># 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 随机设置随机种子</span></span><br><span class="line">torch.seed()</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.initial_seed())  <span class="comment"># 22287915889500</span></span><br></pre></td></tr></tbody></table></figure><h3 id="随机函数"><a href="#随机函数" class="headerlink" title="随机函数"></a>随机函数</h3><h4 id="rand-rand-like"><a href="#rand-rand-like" class="headerlink" title=".rand/.rand_like"></a>.rand/.rand_like</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 固定随机种子</span></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">input</span> = torch.empty(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.rand(<span class="number">3</span>, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031],</span></span><br><span class="line"><span class="string">        [0.7347, 0.0293, 0.7999],</span></span><br><span class="line"><span class="string">        [0.3971, 0.7544, 0.5695]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.rand_like(<span class="built_in">input</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.4388, 0.6387, 0.5247],</span></span><br><span class="line"><span class="string">        [0.6826, 0.3051, 0.4635],</span></span><br><span class="line"><span class="string">        [0.4550, 0.5725, 0.4980]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.rand()</code>返回在区间<code>[0, 1)</code>均匀分布的随机数填充的张量。</p><h4 id="randint-randint-like"><a href="#randint-randint-like" class="headerlink" title=".randint/.randint_like"></a>.randint/.randint_like</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 固定随机种子</span></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">input</span> = torch.empty(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.randint(low=<span class="number">0</span>, high=<span class="number">10</span>, size=(<span class="number">3</span>, <span class="number">3</span>)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[5, 9, 4],</span></span><br><span class="line"><span class="string">        [8, 3, 3],</span></span><br><span class="line"><span class="string">        [1, 1, 9]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.randint_like(<span class="built_in">input</span>, high=<span class="number">10</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[2., 8., 9.],</span></span><br><span class="line"><span class="string">        [6., 3., 3.],</span></span><br><span class="line"><span class="string">        [0., 2., 1.]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.randint(low, high)</code>返回在区间<code>[low, high)</code>的随机数填充的张量。</p><h4 id="randperm"><a href="#randperm" class="headerlink" title=".randperm"></a>.randperm</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 固定随机种子</span></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.randperm(<span class="number">10</span>))  <span class="comment"># tensor([5, 6, 1, 2, 0, 8, 9, 3, 7, 4])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.randperm(n)</code>返回在区间<code>[0, n)</code>的随机排列整数。</p><h4 id="randn-randn-like"><a href="#randn-randn-like" class="headerlink" title=".randn/.randn_like"></a>.randn/.randn_like</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 固定随机种子</span></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">input</span> = torch.empty(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 标准正态分布 N(0, 1)，均值为 0，方差为 1</span></span><br><span class="line"><span class="built_in">print</span>(torch.randn(<span class="number">3</span>, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 0.6614,  0.2669,  0.0617],</span></span><br><span class="line"><span class="string">        [ 0.6213, -0.4519, -0.1661],</span></span><br><span class="line"><span class="string">        [-1.5228,  0.3817, -1.0276]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.randn_like(<span class="built_in">input</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-0.5631, -0.8923, -0.0583],</span></span><br><span class="line"><span class="string">        [-0.1955, -0.9656,  0.4224],</span></span><br><span class="line"><span class="string">        [ 0.2673, -0.4212, -0.5107]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.randn()</code>从<code>标准正态分布</code>中随机采样。</p><h4 id="normal"><a href="#normal" class="headerlink" title=".normal"></a>.normal</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 固定随机种子</span></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 离散正态分布 N(mean, std)</span></span><br><span class="line"><span class="built_in">print</span>(torch.normal(mean=torch.full((<span class="number">5</span>,), <span class="number">0.</span>), std=torch.arange(<span class="number">0</span>, <span class="number">1</span>, <span class="number">0.2</span>)))  <span class="comment"># tensor([ 0.0000,  0.0534,  0.0247,  0.3728, -0.3615])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.normal(mean, std)</code>从给定参数<code>mean</code>、<code>std</code>的<code>离散正态分布</code>中随机采样。</p><h4 id="bernoulli"><a href="#bernoulli" class="headerlink" title=".bernoulli"></a>.bernoulli</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">input</span> = torch.empty(<span class="number">3</span>, <span class="number">3</span>).uniform_(<span class="number">0</span>, <span class="number">1</span>)  <span class="comment"># generate a uniform random matrix with range [0, 1]</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.bernoulli(<span class="built_in">input</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1., 0., 0.],</span></span><br><span class="line"><span class="string">        [1., 0., 1.],</span></span><br><span class="line"><span class="string">        [0., 1., 1.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.bernoulli(torch.ones(<span class="number">3</span>, <span class="number">3</span>)))  <span class="comment"># probability of drawing "1" is 1</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1., 1., 1.],</span></span><br><span class="line"><span class="string">        [1., 1., 1.],</span></span><br><span class="line"><span class="string">        [1., 1., 1.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.bernoulli(torch.zeros(<span class="number">3</span>, <span class="number">3</span>)))  <span class="comment"># probability of drawing "1" is 0</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0., 0., 0.],</span></span><br><span class="line"><span class="string">        [0., 0., 0.],</span></span><br><span class="line"><span class="string">        [0., 0., 0.]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.bernoulli()</code>从<code>伯努利分布</code>中抽取二进制随机数（0 或 1）。输入的值必须在<code>[0, 1]</code>范围内。</p><h4 id="poisson"><a href="#poisson" class="headerlink" title=".poisson"></a>.poisson</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">rates = torch.rand(<span class="number">3</span>, <span class="number">3</span>) * <span class="number">5</span>  <span class="comment"># rate parameter between 0 and 5</span></span><br><span class="line"><span class="built_in">print</span>(torch.poisson(rates))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[5., 1., 1.],</span></span><br><span class="line"><span class="string">        [3., 0., 2.],</span></span><br><span class="line"><span class="string">        [0., 2., 0.]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.poisson()</code>从<code>泊松分布</code>中随机采样。</p><h4 id="multinomial"><a href="#multinomial" class="headerlink" title=".multinomial"></a>.multinomial</h4><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">weights = torch.tensor([[<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">9</span>], [<span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">8</span>, <span class="number">10</span>]], dtype=torch.<span class="built_in">float</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.multinomial(weights, <span class="number">5</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[2, 3, 4, 1, 0],</span></span><br><span class="line"><span class="string">        [3, 2, 1, 4, 0]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># replacement 默认为 False，表示不允许重复抽查，所以采样次数不能大于抽查个数</span></span><br><span class="line"><span class="comment"># print(torch.multinomial(weights, 6))  # RuntimeError: cannot sample n_sample &gt; prob_dist.size(-1) samples without replacement</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># replacement=True 允许重复抽查</span></span><br><span class="line"><span class="built_in">print</span>(torch.multinomial(weights, <span class="number">6</span>, replacement=<span class="literal">True</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[3, 0, 3, 3, 4, 2],</span></span><br><span class="line"><span class="string">        [0, 1, 4, 4, 2, 4]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.multinomial(input, num_samples, replacement)</code>对<code>input</code>的每一行做从<code>多项式分布</code>中采样<code>num_samples</code>次，输出的张量是每一次取值时<code>input</code>张量对应行的下标。</p><h2 id="索引与切片"><a href="#索引与切片" class="headerlink" title="索引与切片"></a>索引与切片</h2><h3 id="Python-语法"><a href="#Python-语法" class="headerlink" title="Python 语法"></a>Python 语法</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4 张 3 通道，高 28，宽 28 的图片</span></span><br><span class="line">images = torch.rand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">28</span>, <span class="number">28</span>)</span><br><span class="line"><span class="built_in">print</span>(images.shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取第一张图片</span></span><br><span class="line"><span class="built_in">print</span>(images[<span class="number">0</span>].shape)  <span class="comment"># torch.Size([3, 28, 28])</span></span><br><span class="line"><span class="comment"># 获取第一张图片的第一个通道数据</span></span><br><span class="line"><span class="built_in">print</span>(images[<span class="number">0</span>, <span class="number">0</span>].shape)  <span class="comment"># torch.Size([28, 28])</span></span><br><span class="line"><span class="comment"># 获取前两张图片</span></span><br><span class="line"><span class="built_in">print</span>(images[:<span class="number">2</span>].shape)  <span class="comment"># torch.Size([2, 3, 28, 28])</span></span><br><span class="line"><span class="comment"># 获取前两张图片前两个通道数据</span></span><br><span class="line"><span class="built_in">print</span>(images[:<span class="number">2</span>, :<span class="number">2</span>].shape)  <span class="comment"># torch.Size([2, 2, 28, 28])</span></span><br><span class="line"><span class="comment"># 获取前两张图片最后一个通道数据</span></span><br><span class="line"><span class="built_in">print</span>(images[:<span class="number">2</span>, -<span class="number">1</span>].shape)  <span class="comment"># torch.Size([2, 28, 28])</span></span><br><span class="line"><span class="comment"># 间隔获取图片数据</span></span><br><span class="line"><span class="built_in">print</span>(images[:, :, ::<span class="number">2</span>, ::<span class="number">2</span>].shape)  <span class="comment"># torch.Size([4, 3, 14, 14])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取所有图片</span></span><br><span class="line"><span class="built_in">print</span>(images[...].shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br><span class="line"><span class="comment"># 获取第一张图片</span></span><br><span class="line"><span class="built_in">print</span>(images[<span class="number">0</span>, ...].shape)  <span class="comment"># torch.Size([3, 28, 28])</span></span><br><span class="line"><span class="comment"># 间隔获取图片宽数据</span></span><br><span class="line"><span class="built_in">print</span>(images[..., ::<span class="number">2</span>].shape)  <span class="comment"># torch.Size([4, 3, 28, 14])</span></span><br></pre></td></tr></tbody></table></figure><h3 id="narrow-narrow-copy"><a href="#narrow-narrow-copy" class="headerlink" title=".narrow/.narrow_copy"></a>.narrow/.narrow_copy</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor([[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>], [<span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span> ,<span class="number">10</span>], [<span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>, <span class="number">14</span>, <span class="number">15</span>]])</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 1,  2,  3,  4,  5],</span></span><br><span class="line"><span class="string">        [ 6,  7,  8,  9, 10],</span></span><br><span class="line"><span class="string">        [11, 12, 13, 14, 15]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.narrow(data, dim=<span class="number">0</span>, start=<span class="number">1</span>, length=<span class="number">2</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 6,  7,  8,  9, 10],</span></span><br><span class="line"><span class="string">        [11, 12, 13, 14, 15]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.narrow(data, dim=<span class="number">1</span>, start=<span class="number">1</span>, length=<span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 2,  3,  4],</span></span><br><span class="line"><span class="string">        [ 7,  8,  9],</span></span><br><span class="line"><span class="string">        [12, 13, 14]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.narrow_copy(data, dim=<span class="number">0</span>, start=<span class="number">1</span>, length=<span class="number">2</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 6,  7,  8,  9, 10],</span></span><br><span class="line"><span class="string">        [11, 12, 13, 14, 15]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.narrow_copy(data, dim=<span class="number">1</span>, start=<span class="number">1</span>, length=<span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 2,  3,  4],</span></span><br><span class="line"><span class="string">        [ 7,  8,  9],</span></span><br><span class="line"><span class="string">        [12, 13, 14]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.narrow()</code>在指定维度缩小张量，可以简单理解为类似切片，<code>tensor[start: start + length]</code></p><p><code>torch.narrow_copy()</code>与<code>torch.narrow()</code>相同，但返回的是副本而不是共享存储。</p><h3 id="select-index-select"><a href="#select-index-select" class="headerlink" title=".select/.index_select"></a>.select/.index_select</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4 张 3 通道，高 28，宽 28 的图片</span></span><br><span class="line">images = torch.rand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">28</span>, <span class="number">28</span>)</span><br><span class="line"><span class="built_in">print</span>(images.shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取第一张图片</span></span><br><span class="line"><span class="built_in">print</span>(torch.select(images, dim=<span class="number">0</span>, index=<span class="number">0</span>).shape)  <span class="comment"># torch.Size([3, 28, 28])</span></span><br><span class="line"><span class="comment"># 获取所有图片的第一个通道</span></span><br><span class="line"><span class="built_in">print</span>(torch.select(images, dim=<span class="number">1</span>, index=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 28, 28])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取第二张和第四张图片</span></span><br><span class="line"><span class="built_in">print</span>(torch.index_select(images, dim=<span class="number">0</span>, index=torch.tensor([<span class="number">1</span>, <span class="number">3</span>])).shape)  <span class="comment"># torch.Size([2, 3, 28, 28])</span></span><br><span class="line"><span class="comment"># 获取所有图片二三通道数据</span></span><br><span class="line"><span class="built_in">print</span>(torch.index_select(images, dim=<span class="number">1</span>, index=torch.tensor([<span class="number">1</span>, <span class="number">2</span>])).shape)  <span class="comment"># torch.Size([4, 2, 28, 28])</span></span><br><span class="line"><span class="comment"># 间隔获取所有图片高数据</span></span><br><span class="line"><span class="built_in">print</span>(torch.index_select(images, dim=<span class="number">2</span>, index=torch.arange(<span class="number">0</span>, <span class="number">28</span>, <span class="number">2</span>)).shape)  <span class="comment"># torch.Size([4, 3, 14, 28])</span></span><br><span class="line"><span class="comment"># 间隔获取所有图片宽数据</span></span><br><span class="line"><span class="built_in">print</span>(torch.index_select(images, dim=<span class="number">3</span>, index=torch.arange(<span class="number">0</span>, <span class="number">28</span>, <span class="number">2</span>)).shape)  <span class="comment"># torch.Size([4, 3, 28, 14])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.select()</code>沿着维度<code>dim</code>，在给定索引<code>index</code>对<code>input</code>张量进行切片，等价于切片。比如：<br><code>tensor.select(0, index)</code>等于<code>tensor[index]</code>。<br><code>tensor.select(2, index)</code>等于<code>tensor[:,:,index]</code>。</p><p><code>torch.index_select()</code>沿着维度<code>dim</code>对<code>input</code>张量进行索引。</p><h3 id="masked-select"><a href="#masked-select" class="headerlink" title=".masked_select"></a>.masked_select</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.randn(<span class="number">3</span>, <span class="number">4</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 0.6614,  0.2669,  0.0617,  0.6213],</span></span><br><span class="line"><span class="string">        [-0.4519, -0.1661, -1.5228,  0.3817],</span></span><br><span class="line"><span class="string">        [-1.0276, -0.5631, -0.8923, -0.0583]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">mask = data.ge(<span class="number">0</span>)</span><br><span class="line"><span class="built_in">print</span>(mask)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ True,  True,  True,  True],</span></span><br><span class="line"><span class="string">        [False, False, False,  True],</span></span><br><span class="line"><span class="string">        [False, False, False, False]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.masked_select(data, mask))  <span class="comment"># tensor([0.6614, 0.2669, 0.0617, 0.6213, 0.3817])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.masked_select()</code>根据布尔掩码选择数据，返回的是一维数据。</p><h3 id="gather"><a href="#gather" class="headerlink" title=".gather"></a>.gather</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.randperm(<span class="number">16</span>).view(<span class="number">4</span>,<span class="number">4</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 5, 15,  6,  4],</span></span><br><span class="line"><span class="string">        [11,  2,  7, 12],</span></span><br><span class="line"><span class="string">        [ 1,  0,  9,  8],</span></span><br><span class="line"><span class="string">        [10,  3, 13, 14]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">index = torch.tensor([[<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>, <span class="number">2</span>]])</span><br><span class="line"><span class="built_in">print</span>(index)  <span class="comment"># tensor([[1, 0, 3, 2]])</span></span><br><span class="line"><span class="built_in">print</span>(index.t())</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1],</span></span><br><span class="line"><span class="string">        [0],</span></span><br><span class="line"><span class="string">        [3],</span></span><br><span class="line"><span class="string">        [2]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.gather(data, <span class="number">0</span>, index))  <span class="comment"># tensor([[11, 15, 13,  8]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.gather(data, <span class="number">0</span>, index.t()))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[11],</span></span><br><span class="line"><span class="string">        [ 5],</span></span><br><span class="line"><span class="string">        [10],</span></span><br><span class="line"><span class="string">        [ 1]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.gather(data, <span class="number">1</span>, index))  <span class="comment"># tensor([[15,  5,  4,  6]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.gather(data, <span class="number">1</span>, index.t()))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15],</span></span><br><span class="line"><span class="string">        [11],</span></span><br><span class="line"><span class="string">        [ 8],</span></span><br><span class="line"><span class="string">        [13]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><ul><li><p><code>torch.gather(data, 0, index)</code>对<code>0</code>维(行)进行</p><pre><code>  tensor([[1, 0, 3, 2]])        第 0  1  2  3 列</code></pre><p>索引：<br>[<b>1</b>][0] == 11<br>[<b>0</b>][1] == 15<br>[<b>3</b>][2] == 13<br>[<b>2</b>][3] == 8<br>加粗的是<code>行索引</code>的值<code>1, 0, 3, 2</code>，没加粗的为什么是<code>0, 1, 2, 3</code>呢？因为索引<code>1</code>是第<code>0</code>列，索引<code>0</code>是第<code>1</code>列，索引<code>3</code>是第<code>2</code>列，索引<code>2</code>是第<code>3</code>列。</p></li><li><p><code>torch.gather(data, 0, index.t())</code>对<code>0</code>维(行)进行</p><pre><code>  tensor([[1],   第0列          [0],   第0列          [3],   第0列          [2]])  第0列</code></pre><p>索引：<br>[<b>1</b>][0] == 11<br>[<b>0</b>][0] == 5<br>[<b>3</b>][0] == 10<br>[<b>2</b>][0] == 1<br>加粗的是<code>行索引</code>的值<code>1, 0, 3, 2</code>，没加粗的都是<code>0</code>，因为索引<code>1, 0, 3, 2</code>都是第<code>0</code>列。</p></li><li><p><code>torch.gather(data, 1, index.t())</code>对<code>1</code>维(列)进行</p><pre><code>  tensor([[1],   第0行          [0],   第1行          [3],   第2行          [2]])  第3行</code></pre><p>索引：<br>[0][<b>1</b>] == 15<br>[1][<b>0</b>] == 11<br>[2][<b>3</b>] == 8<br>[3][<b>2</b>] == 13<br>加粗的是<code>列索引</code>的值<code>1, 0, 3, 2</code>，没加粗的<code>0, 1, 2, 3</code>则是因为索引<code>1</code>是第<code>0</code>行，索引<code>0</code>是第<code>1</code>行，索引<code>3</code>是第<code>2</code>行，索引<code>2</code>是第<code>3</code>行。</p></li></ul><h3 id="take-take-along-dim"><a href="#take-take-along-dim" class="headerlink" title=".take/.take_along_dim"></a>.take/.take_along_dim</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.randperm(<span class="number">16</span>).view(<span class="number">4</span>,<span class="number">4</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 5, 15,  6,  4],</span></span><br><span class="line"><span class="string">        [11,  2,  7, 12],</span></span><br><span class="line"><span class="string">        [ 1,  0,  9,  8],</span></span><br><span class="line"><span class="string">        [10,  3, 13, 14]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">index1 = torch.tensor([<span class="number">0</span>, <span class="number">5</span>, <span class="number">10</span>, <span class="number">15</span>])</span><br><span class="line">index2 = torch.tensor([[<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>, <span class="number">2</span>]])</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.take(data, index1))  <span class="comment"># tensor([ 5,  2,  9, 14])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.take_along_dim(data, index1))  <span class="comment"># tensor([ 5,  2,  9, 14])</span></span><br><span class="line"><span class="built_in">print</span>(torch.take_along_dim(data, index2, dim=<span class="number">0</span>))  <span class="comment"># tensor([[11, 15, 13,  8]])</span></span><br><span class="line"><span class="built_in">print</span>(torch.take_along_dim(data, index2.t(), dim=<span class="number">0</span>))  <span class="comment"># 这里与torch.gather不同</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[11,  2,  7, 12],</span></span><br><span class="line"><span class="string">        [ 5, 15,  6,  4],</span></span><br><span class="line"><span class="string">        [10,  3, 13, 14],</span></span><br><span class="line"><span class="string">        [ 1,  0,  9,  8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.take_along_dim(data, index2, dim=<span class="number">1</span>))  <span class="comment"># 这里与torch.gather不同</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15,  5,  4,  6],</span></span><br><span class="line"><span class="string">        [ 2, 11, 12,  7],</span></span><br><span class="line"><span class="string">        [ 0,  1,  8,  9],</span></span><br><span class="line"><span class="string">        [ 3, 10, 14, 13]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.take_along_dim(data, index2.t(), dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15],</span></span><br><span class="line"><span class="string">        [11],</span></span><br><span class="line"><span class="string">        [ 8],</span></span><br><span class="line"><span class="string">        [13]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.take_along_dim()</code>当<code>dim=None</code>时，等价于<code>torch.take()</code>，先把张量打平转成<code>1</code>维在根据索引获取元素。</p><p>当<code>dim</code>不等于<code>None</code>时，则与<code>data.gather()</code>相似。</p><h3 id="argwhere-nonzero"><a href="#argwhere-nonzero" class="headerlink" title=".argwhere/.nonzero"></a>.argwhere/.nonzero</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data1 = torch.tensor([<span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>])</span><br><span class="line">data2 = torch.tensor([[<span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>], [<span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>]])</span><br><span class="line"><span class="built_in">print</span>(data1)  <span class="comment"># tensor([1, 0, 1, 0, 1, 0])</span></span><br><span class="line"><span class="built_in">print</span>(data2)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1, 0, 1],</span></span><br><span class="line"><span class="string">        [0, 1, 0]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.argwhere(data1))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0],</span></span><br><span class="line"><span class="string">        [2],</span></span><br><span class="line"><span class="string">        [4]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.argwhere(data2))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 0],</span></span><br><span class="line"><span class="string">        [0, 2],</span></span><br><span class="line"><span class="string">        [1, 1]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.nonzero(data1))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0],</span></span><br><span class="line"><span class="string">        [2],</span></span><br><span class="line"><span class="string">        [4]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.nonzero(data1, as_tuple=<span class="literal">True</span>))  <span class="comment"># (tensor([0, 2, 4]),)</span></span><br><span class="line"><span class="built_in">print</span>(torch.nonzero(data2))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 0],</span></span><br><span class="line"><span class="string">        [0, 2],</span></span><br><span class="line"><span class="string">        [1, 1]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.nonzero(data2, as_tuple=<span class="literal">True</span>))  <span class="comment"># (tensor([0, 0, 1]), tensor([0, 2, 1]))</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.argwhere()</code>和<code>torch.nonzero()</code>都是返回非<code>0</code>元素的索引。</p><p>当<code>torch.nonzero()</code>参数<code>as_tuple=False</code>时，效果与<code>torch.argwhere()</code>相同。</p><h3 id="where"><a href="#where" class="headerlink" title=".where"></a>.where</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">condition = torch.randn(<span class="number">3</span>, <span class="number">5</span>) &gt; <span class="number">0</span></span><br><span class="line"><span class="built_in">print</span>(condition)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ True,  True,  True,  True, False],</span></span><br><span class="line"><span class="string">        [False, False,  True, False, False],</span></span><br><span class="line"><span class="string">        [False, False, False, False,  True]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">data1 = torch.ones(<span class="number">3</span>, <span class="number">5</span>)</span><br><span class="line"><span class="built_in">print</span>(data1)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1., 1., 1., 1., 1.],</span></span><br><span class="line"><span class="string">        [1., 1., 1., 1., 1.],</span></span><br><span class="line"><span class="string">        [1., 1., 1., 1., 1.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">data2 = torch.full_like(data1, <span class="number">100</span>)</span><br><span class="line"><span class="built_in">print</span>(data2)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[100., 100., 100., 100., 100.],</span></span><br><span class="line"><span class="string">        [100., 100., 100., 100., 100.],</span></span><br><span class="line"><span class="string">        [100., 100., 100., 100., 100.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 满足条件返回 data1, 不满足条件返回 data2</span></span><br><span class="line"><span class="built_in">print</span>(torch.where(condition, data1, data2))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[  1.,   1.,   1.,   1., 100.],</span></span><br><span class="line"><span class="string">        [100., 100.,   1., 100., 100.],</span></span><br><span class="line"><span class="string">        [100., 100., 100., 100.,   1.]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="unravel-index"><a href="#unravel-index" class="headerlink" title=".unravel_index"></a>.unravel_index</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.arange(<span class="number">9</span>).view(<span class="number">3</span>, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.arange(<span class="number">9</span>, <span class="number">18</span>).view(<span class="number">3</span>, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 9, 10, 11],</span></span><br><span class="line"><span class="string">        [12, 13, 14],</span></span><br><span class="line"><span class="string">        [15, 16, 17]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.unravel_index(torch.tensor(<span class="number">2</span>), shape=(<span class="number">3</span>, <span class="number">3</span>)))  <span class="comment"># (tensor(0), tensor(2))</span></span><br><span class="line"><span class="built_in">print</span>(torch.unravel_index(torch.tensor([<span class="number">4</span>, <span class="number">6</span>, <span class="number">9</span>, <span class="number">17</span>]), shape=(<span class="number">3</span>, <span class="number">3</span>)))  <span class="comment"># (tensor([1, 2, 0, 2]), tensor([1, 0, 0, 2]))</span></span><br></pre></td></tr></tbody></table></figure><p>索引<code>2</code>在<code>shape</code>为<code>(3, 3)</code>的<code>0</code>行<code>2</code>列。<br>索引<code>9</code>可以理解为<code>9 / prod(shape) == 9 % 9 == 0</code>，所以在<code>0</code>行<code>0</code>列。<br>索引<code>17</code>可以理解为<code>17 / prod(shape) == 17 % 9 == 8</code>，所以在<code>2</code>行<code>2</code>列。</p><h2 id="维度变换"><a href="#维度变换" class="headerlink" title="维度变换"></a>维度变换</h2><h3 id="t-transpose-movedim-permute"><a href="#t-transpose-movedim-permute" class="headerlink" title=".t/.transpose/.movedim/.permute"></a>.t/.transpose/.movedim/.permute</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.arange(<span class="number">9</span>)</span><br><span class="line"><span class="built_in">print</span>(data)  <span class="comment"># tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])</span></span><br><span class="line"><span class="built_in">print</span>(torch.t(data))  <span class="comment"># tensor([0, 1, 2, 3, 4, 5, 6, 7, 8])</span></span><br><span class="line"></span><br><span class="line">data = torch.arange(<span class="number">9</span>).view(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.t(data))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 3, 6],</span></span><br><span class="line"><span class="string">        [1, 4, 7],</span></span><br><span class="line"><span class="string">        [2, 5, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4 张 3 通道，高 1080，宽 1920 的图片</span></span><br><span class="line">images = torch.rand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">1080</span>, <span class="number">1920</span>)</span><br><span class="line"><span class="comment"># BCHW</span></span><br><span class="line"><span class="built_in">print</span>(images.shape)  <span class="comment"># torch.Size([4, 3, 1080, 1920])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># BCHW --&gt; BWHC --&gt; BHWC</span></span><br><span class="line"><span class="built_in">print</span>(images.transpose(<span class="number">1</span>, <span class="number">3</span>).transpose(<span class="number">1</span>, <span class="number">2</span>).shape)  <span class="comment"># torch.Size([4, 1080, 1920, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># BCHW --&gt; BHWC</span></span><br><span class="line"><span class="built_in">print</span>(images.movedim(<span class="number">1</span>, <span class="number">3</span>).shape)  <span class="comment"># torch.Size([4, 1080, 1920, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># BCHW --&gt; BHWC</span></span><br><span class="line"><span class="built_in">print</span>(images.permute(<span class="number">0</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 1080, 1920, 3])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.t(input)</code>只能处理维度小于等于<code>2</code>的，否则会报错。当维度是<code>0</code>或<code>1</code>维时，返回相同的结果，当维度为<code>2</code>时，等价于<code>torch.transpose(input, 0, 1)</code></p><p><code>torch.transpose(input, dim0, dim1)</code>一次只能操作两个维度，对调两个维度的位置。</p><p><code>torch.movedim(input, source, destination)</code>将<code>source</code>维度移动到<code>destination</code>维度。</p><p><code>torch.permute(input, dims)</code>一次可以操作多个维度，<code>dims</code>指定所有维度的顺序。在多维度操作上使用<code>torch.permute()</code>更直观。</p><p><code>torch.swapaxes()</code>是<code>torch.transpose()</code>的别名。<br><code>torch.swapdims()</code>是<code>torch.transpose()</code>的别名。<br><code>torch.moveaxis()</code>是<code>torch.movedim()</code>的别名。</p><h3 id="view-reshape"><a href="#view-reshape" class="headerlink" title=".view/.reshape"></a>.view/.reshape</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4 张 3 通道，高 28，宽 28 的图片</span></span><br><span class="line">images = torch.rand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">28</span>, <span class="number">28</span>)</span><br><span class="line"><span class="built_in">print</span>(images.shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(images.view(<span class="number">4</span>, <span class="number">3</span> * <span class="number">28</span> * <span class="number">28</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"><span class="comment"># -1 会自动计算出数值</span></span><br><span class="line"><span class="built_in">print</span>(images.view(<span class="number">4</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"><span class="comment"># print(images.transpose(1, 3).transpose(1, 2).view(4, -1).shape)  # 报错</span></span><br><span class="line"><span class="built_in">print</span>(images.transpose(<span class="number">1</span>, <span class="number">3</span>).transpose(<span class="number">1</span>, <span class="number">2</span>).contiguous().view(<span class="number">4</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"><span class="comment"># print(images.permute(0, 2, 3, 1).view(4, -1).shape)  # 报错</span></span><br><span class="line"><span class="built_in">print</span>(images.permute(<span class="number">0</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">1</span>).contiguous().view(<span class="number">4</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(images.reshape(<span class="number">4</span>, <span class="number">3</span> * <span class="number">28</span> * <span class="number">28</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"><span class="comment"># -1 会自动计算出数值</span></span><br><span class="line"><span class="built_in">print</span>(images.reshape(<span class="number">4</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"><span class="built_in">print</span>(images.transpose(<span class="number">1</span>, <span class="number">3</span>).transpose(<span class="number">1</span>, <span class="number">2</span>).reshape(<span class="number">4</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br><span class="line"><span class="built_in">print</span>(images.permute(<span class="number">0</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">1</span>).reshape(<span class="number">4</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 2352])</span></span><br></pre></td></tr></tbody></table></figure><p><code>view()</code>和<code>reshape()</code>都可以改变<code>Tensor</code>的维度，区别是：</p><p><code>view()</code>只能对满足连续性的张量进行转换，当对不满足连续性的张量进行操作时会报<code>RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.</code>错误。<code>transpose()</code>和<code>permute()</code>会改变张量连续性，使用<code>view()</code>前需要先执行<code>contiguous()</code>。</p><p><code>reshape()</code>则没有上述要求，可以直接使用，无需先执行<code>contiguous()</code>。</p><h3 id="squeeze-unsqueeze"><a href="#squeeze-unsqueeze" class="headerlink" title=".squeeze/.unsqueeze"></a>.squeeze/.unsqueeze</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.rand(<span class="number">2</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">1</span>)</span><br><span class="line"><span class="built_in">print</span>(data.shape)  <span class="comment"># torch.Size([2, 1, 2, 1])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># dim=None，会把能挤压的维度挤压</span></span><br><span class="line"><span class="built_in">print</span>(torch.squeeze(data).shape)  <span class="comment"># torch.Size([2, 2])</span></span><br><span class="line"><span class="comment"># 第一维度是 2 没法挤压，所以保持不变</span></span><br><span class="line"><span class="built_in">print</span>(torch.squeeze(data, dim=<span class="number">0</span>).shape)  <span class="comment"># torch.Size([2, 1, 2, 1])</span></span><br><span class="line"><span class="comment"># 第二维度挤压</span></span><br><span class="line"><span class="built_in">print</span>(torch.squeeze(data, dim=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([2, 2, 1])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在第一维增加维度</span></span><br><span class="line"><span class="built_in">print</span>(torch.unsqueeze(data, dim=<span class="number">0</span>).shape)  <span class="comment"># torch.Size([1, 2, 1, 2, 1])</span></span><br><span class="line"><span class="comment"># 在最后一维增加维度</span></span><br><span class="line"><span class="built_in">print</span>(torch.unsqueeze(data, dim=-<span class="number">1</span>).shape)  <span class="comment"># torch.Size([2, 1, 2, 1, 1])</span></span><br></pre></td></tr></tbody></table></figure><h3 id="expand-repeat"><a href="#expand-repeat" class="headerlink" title=".expand/.repeat"></a>.expand/.repeat</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4 张单通道，高 28，宽 28 的图片</span></span><br><span class="line">images = torch.rand(<span class="number">4</span>, <span class="number">1</span>, <span class="number">28</span>, <span class="number">28</span>)</span><br><span class="line">data = torch.empty(<span class="number">4</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 第二维度扩展到 3 通道，-1 表示不扩展保持原样</span></span><br><span class="line"><span class="built_in">print</span>(images.expand(-<span class="number">1</span>, <span class="number">3</span>, -<span class="number">1</span>, -<span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br><span class="line"><span class="built_in">print</span>(images.expand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">28</span>, <span class="number">28</span>).shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br><span class="line"><span class="comment"># 扩展到和 images 相同的 shape</span></span><br><span class="line"><span class="built_in">print</span>(data.expand_as(images).shape)  <span class="comment"># torch.Size([4, 1, 28, 28])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 各维度重复指定次数的数据</span></span><br><span class="line"><span class="built_in">print</span>(images.repeat(<span class="number">1</span>, <span class="number">3</span>, <span class="number">1</span>, <span class="number">1</span>).shape)  <span class="comment"># torch.Size([4, 3, 28, 28])</span></span><br></pre></td></tr></tbody></table></figure><h3 id="tile"><a href="#tile" class="headerlink" title=".tile"></a>.tile</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.arange(<span class="number">9</span>).view(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果 dims 指定的维度小于 input 的维度，会扩展到相同的维度，比如 (2,) 会扩展到 (1, 2)</span></span><br><span class="line"><span class="built_in">print</span>(torch.tile(data, dims=(<span class="number">2</span>,)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8, 6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.tile(data, dims=(<span class="number">1</span>, <span class="number">2</span>)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8, 6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.tile(data, dims=(<span class="number">3</span>, <span class="number">2</span>)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8, 6, 7, 8],</span></span><br><span class="line"><span class="string">        [0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8, 6, 7, 8],</span></span><br><span class="line"><span class="string">        [0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8, 6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 如果 dims 指定的维度大于 input 的维度，input 会扩展到相同的维度，比如 input 是 (3, 3) 会扩展到 (1, 3, 3)</span></span><br><span class="line"><span class="built_in">print</span>(torch.tile(data, dims=(<span class="number">1</span>, <span class="number">3</span>, <span class="number">2</span>)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[[0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">         [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">         [6, 7, 8, 6, 7, 8],</span></span><br><span class="line"><span class="string">         [0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">         [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">         [6, 7, 8, 6, 7, 8],</span></span><br><span class="line"><span class="string">         [0, 1, 2, 0, 1, 2],</span></span><br><span class="line"><span class="string">         [3, 4, 5, 3, 4, 5],</span></span><br><span class="line"><span class="string">         [6, 7, 8, 6, 7, 8]]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h2 id="合并与拆分"><a href="#合并与拆分" class="headerlink" title="合并与拆分"></a>合并与拆分</h2><h3 id="cat"><a href="#cat" class="headerlink" title=".cat"></a>.cat</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data1 = torch.rand(<span class="number">2</span>, <span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(data1)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031],</span></span><br><span class="line"><span class="string">        [0.7347, 0.0293, 0.7999]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">data2 = torch.rand(<span class="number">2</span>, <span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(data1)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031],</span></span><br><span class="line"><span class="string">        [0.7347, 0.0293, 0.7999]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 行合并</span></span><br><span class="line"><span class="built_in">print</span>(torch.cat([data1, data1]))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031],</span></span><br><span class="line"><span class="string">        [0.7347, 0.0293, 0.7999],</span></span><br><span class="line"><span class="string">        [0.7576, 0.2793, 0.4031],</span></span><br><span class="line"><span class="string">        [0.7347, 0.0293, 0.7999]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 列合并</span></span><br><span class="line"><span class="built_in">print</span>(torch.cat([data1, data1], dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031, 0.7576, 0.2793, 0.4031],</span></span><br><span class="line"><span class="string">        [0.7347, 0.0293, 0.7999, 0.7347, 0.0293, 0.7999]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.concat()</code>是<code>torch.cat()</code>的别名。<br><code>torch.concatenate()</code>是<code>torch.cat()</code>的别名。</p><h3 id="stack-hstack-vstack-column-stack-dstack"><a href="#stack-hstack-vstack-column-stack-dstack" class="headerlink" title=".stack/.hstack/.vstack/.column_stack/.dstack"></a>.stack/.hstack/.vstack/.column_stack/.dstack</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor(<span class="number">9</span>)</span><br><span class="line">data1 = torch.arange(<span class="number">9</span>)</span><br><span class="line">data2 = torch.arange(<span class="number">9</span>).view(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line">data3 = torch.arange(<span class="number">9</span>).view(<span class="number">1</span>, <span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line">data4 = torch.arange(<span class="number">9</span>).view(<span class="number">1</span>, <span class="number">1</span>, <span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line">data5 = torch.arange(<span class="number">9</span>).view(<span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(data.shape)  <span class="comment"># torch.Size([])</span></span><br><span class="line"><span class="built_in">print</span>(data1.shape)  <span class="comment"># torch.Size([9])</span></span><br><span class="line"><span class="built_in">print</span>(data2.shape)  <span class="comment"># torch.Size([3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(data3.shape)  <span class="comment"># torch.Size([1, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(data4.shape)  <span class="comment"># torch.Size([1, 1, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(data5.shape)  <span class="comment"># torch.Size([1, 1, 1, 3, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># dim 默认为 0，在第一维度堆叠</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data, data]).shape)  <span class="comment"># torch.Size([2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data1, data1]).shape)  <span class="comment"># torch.Size([2, 9])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data2, data2]).shape)  <span class="comment"># torch.Size([2, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data3, data3]).shape)  <span class="comment"># torch.Size([2, 1, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data4, data4]).shape)  <span class="comment"># torch.Size([2, 1, 1, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data5, data5]).shape)  <span class="comment"># torch.Size([2, 1, 1, 1, 3, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># dim=1，在第二维度堆叠</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data1, data1], dim=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([9, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data2, data2], dim=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([3, 2, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data3, data3], dim=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([1, 2, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data4, data4], dim=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([1, 2, 1, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.stack([data5, data5], dim=<span class="number">1</span>).shape)  <span class="comment"># torch.Size([1, 2, 1, 1, 3, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 水平堆叠</span></span><br><span class="line"><span class="built_in">print</span>(torch.hstack([data, data]).shape)  <span class="comment"># torch.Size([2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.hstack([data1, data1]).shape)  <span class="comment"># torch.Size([18])</span></span><br><span class="line"><span class="built_in">print</span>(torch.hstack([data2, data2]).shape)  <span class="comment"># torch.Size([3, 6])</span></span><br><span class="line"><span class="built_in">print</span>(torch.hstack([data3, data3]).shape)  <span class="comment"># torch.Size([1, 6, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.hstack([data4, data4]).shape)  <span class="comment"># torch.Size([1, 2, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.hstack([data5, data5]).shape)  <span class="comment"># torch.Size([1, 2, 1, 3, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 垂直堆叠</span></span><br><span class="line"><span class="built_in">print</span>(torch.vstack([data, data]).shape)  <span class="comment"># torch.Size([2, 1])</span></span><br><span class="line"><span class="built_in">print</span>(torch.vstack([data1, data1]).shape)  <span class="comment"># torch.Size([2, 9])</span></span><br><span class="line"><span class="built_in">print</span>(torch.vstack([data2, data2]).shape)  <span class="comment"># torch.Size([6, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.vstack([data3, data3]).shape)  <span class="comment"># torch.Size([2, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.vstack([data4, data4]).shape)  <span class="comment"># torch.Size([2, 1, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.vstack([data5, data5]).shape)  <span class="comment"># torch.Size([2, 1, 1, 3, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 列堆叠</span></span><br><span class="line"><span class="built_in">print</span>(torch.column_stack([data, data]).shape)  <span class="comment"># torch.Size([1, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.column_stack([data1, data1]).shape)  <span class="comment"># torch.Size([9, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.column_stack([data2, data2]).shape)  <span class="comment"># torch.Size([3, 6])</span></span><br><span class="line"><span class="built_in">print</span>(torch.column_stack([data3, data3]).shape)  <span class="comment"># torch.Size([1, 6, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.column_stack([data4, data4]).shape)  <span class="comment"># torch.Size([1, 2, 3, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.column_stack([data5, data5]).shape)  <span class="comment"># torch.Size([1, 2, 1, 3, 3])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 深度堆叠，在第 3 维度堆叠</span></span><br><span class="line"><span class="built_in">print</span>(torch.dstack((data, data)).shape)  <span class="comment"># torch.Size([1, 1, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.dstack((data1, data1)).shape)  <span class="comment"># torch.Size([1, 9, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.dstack((data2, data2)).shape)  <span class="comment"># torch.Size([3, 3, 2])</span></span><br><span class="line"><span class="built_in">print</span>(torch.dstack((data3, data3)).shape)  <span class="comment"># torch.Size([1, 3, 6])</span></span><br><span class="line"><span class="built_in">print</span>(torch.dstack((data4, data4)).shape)  <span class="comment"># torch.Size([1, 1, 6, 3])</span></span><br><span class="line"><span class="built_in">print</span>(torch.dstack((data5, data5)).shape)  <span class="comment"># torch.Size([1, 1, 2, 3, 3])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.hstack)</code>按水平方向（列方向）依次堆叠张量。</p><p><code>torch.vstack)</code>按垂直方向（行方向）依次堆叠张量。</p><p><code>torch.column_stack()</code>除了张量是<code>0</code>维和<code>1</code>维外，等价于<code>torch.hstack()</code>。当张量<code>t</code>是<code>0</code>维或<code>1</code>维时，先<code>reshape</code>重塑为<code>(t.numel(), 1)</code>再水平堆叠。</p><p><code>torch.row_stack()</code>是<code>torch.vstack()</code>的别名。</p><p><code>torch.dstack()</code>在第<code>3</code>维度进行堆叠。</p><p><code>torch.stack()</code>是一个更通用的函数，通过<code>dim</code>指定在任意维度进行堆叠，<code>dim</code>默认等于<code>0</code>。它总是增加一个新的维度来堆叠张量。</p><h3 id="chunk"><a href="#chunk" class="headerlink" title=".chunk"></a>.chunk</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.arange(<span class="number">20</span>).view(<span class="number">4</span>, <span class="number">5</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 0,  1,  2,  3,  4],</span></span><br><span class="line"><span class="string">        [ 5,  6,  7,  8,  9],</span></span><br><span class="line"><span class="string">        [10, 11, 12, 13, 14],</span></span><br><span class="line"><span class="string">        [15, 16, 17, 18, 19]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按行分成 3 块（PS: 这里实际只分成两块，因为每块大小是 2，4 行只能分成两块）</span></span><br><span class="line"><span class="built_in">print</span>(torch.chunk(data, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0, 1, 2, 3, 4],</span></span><br><span class="line"><span class="string">        [5, 6, 7, 8, 9]]), tensor([[10, 11, 12, 13, 14],</span></span><br><span class="line"><span class="string">        [15, 16, 17, 18, 19]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 按列分成 2 块</span></span><br><span class="line"><span class="built_in">print</span>(torch.chunk(data, <span class="number">2</span>, dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[ 0,  1,  2],</span></span><br><span class="line"><span class="string">        [ 5,  6,  7],</span></span><br><span class="line"><span class="string">        [10, 11, 12],</span></span><br><span class="line"><span class="string">        [15, 16, 17]]), tensor([[ 3,  4],</span></span><br><span class="line"><span class="string">        [ 8,  9],</span></span><br><span class="line"><span class="string">        [13, 14],</span></span><br><span class="line"><span class="string">        [18, 19]]))</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="split-hsplit-vsplit-dsplit-tensor-split"><a href="#split-hsplit-vsplit-dsplit-tensor-split" class="headerlink" title=".split/.hsplit/.vsplit/.dsplit/.tensor_split"></a>.split/.hsplit/.vsplit/.dsplit/.tensor_split</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data1 = torch.arange(<span class="number">9</span>)</span><br><span class="line">data2 = torch.arange(<span class="number">9</span>).view(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line">data3 = torch.arange(<span class="number">9</span>).view(<span class="number">1</span>, <span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 按每两个一组分割</span></span><br><span class="line"><span class="built_in">print</span>(torch.split(data1, <span class="number">2</span>))  <span class="comment"># (tensor([0, 1]), tensor([2, 3]), tensor([4, 5]), tensor([6, 7]), tensor([8]))</span></span><br><span class="line"><span class="comment"># 分割成 3 组，第一组 1 份，第二组 3 份，第三组 5 份</span></span><br><span class="line"><span class="built_in">print</span>(torch.split(data1, [<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>]))  <span class="comment"># (tensor([0]), tensor([1, 2, 3]), tensor([4, 5, 6, 7, 8]))</span></span><br><span class="line"><span class="comment"># 按每两个一组分割</span></span><br><span class="line"><span class="built_in">print</span>(torch.split(data2, <span class="number">2</span>, dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0, 1],</span></span><br><span class="line"><span class="string">        [3, 4],</span></span><br><span class="line"><span class="string">        [6, 7]]), tensor([[2],</span></span><br><span class="line"><span class="string">        [5],</span></span><br><span class="line"><span class="string">        [8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 分割成 2 组，第一组 1 份，第二组 2 份</span></span><br><span class="line"><span class="built_in">print</span>(torch.split(data2, [<span class="number">1</span>, <span class="number">2</span>], dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0],</span></span><br><span class="line"><span class="string">        [3],</span></span><br><span class="line"><span class="string">        [6]]), tensor([[1, 2],</span></span><br><span class="line"><span class="string">        [4, 5],</span></span><br><span class="line"><span class="string">        [7, 8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 将具有一维或多维的张量 input 水平拆分为多个张量</span></span><br><span class="line"><span class="comment"># 平均分成 3 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.hsplit(data1, <span class="number">3</span>))  <span class="comment"># (tensor([0, 1, 2]), tensor([3, 4, 5]), tensor([6, 7, 8]))</span></span><br><span class="line"><span class="comment"># 以索引 3、5、7 分成 4 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.hsplit(data1, [<span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>]))  <span class="comment"># (tensor([0, 1, 2]), tensor([3, 4]), tensor([5, 6]), tensor([7, 8]))</span></span><br><span class="line"><span class="comment"># 平均分成 3 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.hsplit(data2, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0],</span></span><br><span class="line"><span class="string">        [3],</span></span><br><span class="line"><span class="string">        [6]]), tensor([[1],</span></span><br><span class="line"><span class="string">        [4],</span></span><br><span class="line"><span class="string">        [7]]), tensor([[2],</span></span><br><span class="line"><span class="string">        [5],</span></span><br><span class="line"><span class="string">        [8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 以索引 1 分成 2 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.hsplit(data2, [<span class="number">1</span>]))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0],</span></span><br><span class="line"><span class="string">        [3],</span></span><br><span class="line"><span class="string">        [6]]), tensor([[1, 2],</span></span><br><span class="line"><span class="string">        [4, 5],</span></span><br><span class="line"><span class="string">        [7, 8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 将具有二维或多维的张量 input 垂直拆分为多个张量</span></span><br><span class="line"><span class="comment"># 平均分成 3 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.vsplit(data2, <span class="number">3</span>))  <span class="comment"># (tensor([[0, 1, 2]]), tensor([[3, 4, 5]]), tensor([[6, 7, 8]]))</span></span><br><span class="line"><span class="comment"># 以索引 2 分成 2 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.vsplit(data2, [<span class="number">2</span>]))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5]]), tensor([[6, 7, 8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 将具有三个或更多维度的张量 input 在深度方向上拆分为多个张量</span></span><br><span class="line"><span class="comment"># 平均分成 3 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.dsplit(data3, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[[0],</span></span><br><span class="line"><span class="string">         [3],</span></span><br><span class="line"><span class="string">         [6]]]), tensor([[[1],</span></span><br><span class="line"><span class="string">         [4],</span></span><br><span class="line"><span class="string">         [7]]]), tensor([[[2],</span></span><br><span class="line"><span class="string">         [5],</span></span><br><span class="line"><span class="string">         [8]]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 以索引 1、2 分成 3 段</span></span><br><span class="line"><span class="built_in">print</span>(torch.dsplit(data3, [<span class="number">1</span>, <span class="number">2</span>]))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[[0],</span></span><br><span class="line"><span class="string">         [3],</span></span><br><span class="line"><span class="string">         [6]]]), tensor([[[1],</span></span><br><span class="line"><span class="string">         [4],</span></span><br><span class="line"><span class="string">         [7]]]), tensor([[[2],</span></span><br><span class="line"><span class="string">         [5],</span></span><br><span class="line"><span class="string">         [8]]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.tensor_split(data1, <span class="number">3</span>))  <span class="comment"># (tensor([0, 1, 2]), tensor([3, 4, 5]), tensor([6, 7, 8]))</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor_split(data2, <span class="number">3</span>, dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0],</span></span><br><span class="line"><span class="string">        [3],</span></span><br><span class="line"><span class="string">        [6]]), tensor([[1],</span></span><br><span class="line"><span class="string">        [4],</span></span><br><span class="line"><span class="string">        [7]]), tensor([[2],</span></span><br><span class="line"><span class="string">        [5],</span></span><br><span class="line"><span class="string">        [8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.tensor_split(data3, <span class="number">3</span>, dim=<span class="number">2</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">(tensor([[0],</span></span><br><span class="line"><span class="string">        [3],</span></span><br><span class="line"><span class="string">        [6]]), tensor([[1],</span></span><br><span class="line"><span class="string">        [4],</span></span><br><span class="line"><span class="string">        [7]]), tensor([[2],</span></span><br><span class="line"><span class="string">        [5],</span></span><br><span class="line"><span class="string">        [8]]))</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.hsplit(input, indices_or_sections)</code>当<code>input</code>是<code>1</code>维时，等价于<code>torch.tensor_split(input, indices_or_sections, dim=0)</code>，当<code>input</code>是大于等于<code>2</code>维时，等价于<code>torch.tensor_split(input, indices_or_sections, dim=1)</code>。<code>indices_or_sections</code>如果是数字，必须能被整除，否则会抛出异常。</p><p><code>torch.vsplit(input, indices_or_sections)</code>等价于<code>torch.tensor_split(input, indices_or_sections, dim=0)</code>。<code>input</code>必须大于等于<code>2</code>维。<code>indices_or_sections</code>如果是数字，必须能被整除，否则会抛出异常。</p><p><code>torch.dsplit(input, indices_or_sections)</code>等价于<code>torch.tensor_split(input, indices_or_sections, dim=2)</code>。<code>input</code>必须大于等于<code>3</code>维。<code>indices_or_sections</code>如果是数字，必须能被整除，否则会抛出异常。</p><h3 id="unbind"><a href="#unbind" class="headerlink" title=".unbind"></a>.unbind</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.arange(<span class="number">9</span>).view(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 1, 2],</span></span><br><span class="line"><span class="string">        [3, 4, 5],</span></span><br><span class="line"><span class="string">        [6, 7, 8]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按行解绑</span></span><br><span class="line"><span class="built_in">print</span>(torch.unbind(data))  <span class="comment"># (tensor([0, 1, 2]), tensor([3, 4, 5]), tensor([6, 7, 8]))</span></span><br><span class="line"><span class="comment"># 按列解绑</span></span><br><span class="line"><span class="built_in">print</span>(torch.unbind(data, dim=<span class="number">1</span>))  <span class="comment"># (tensor([0, 3, 6]), tensor([1, 4, 7]), tensor([2, 5, 8]))</span></span><br></pre></td></tr></tbody></table></figure><h2 id="逐点运算"><a href="#逐点运算" class="headerlink" title="逐点运算"></a>逐点运算</h2><h3 id="add-sub-mul-div-remainder-fmod-positive-neg-abs"><a href="#add-sub-mul-div-remainder-fmod-positive-neg-abs" class="headerlink" title=".add/.sub/.mul/.div/.remainder/.fmod/.positive/.neg/.abs"></a>.add/.sub/.mul/.div/.remainder/.fmod/.positive/.neg/.abs</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.randint(-<span class="number">10</span>, <span class="number">10</span>, (<span class="number">2</span>, <span class="number">5</span>))</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-5,  9, -6, -2, -7],</span></span><br><span class="line"><span class="string">        [ 3,  1, -9,  9,  2]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 加</span></span><br><span class="line"><span class="built_in">print</span>(torch.add(data, <span class="number">2</span>))  <span class="comment"># 等价于 data + 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-3, 11, -4,  0, -5],</span></span><br><span class="line"><span class="string">        [ 5,  3, -7, 11,  4]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 减</span></span><br><span class="line"><span class="built_in">print</span>(torch.sub(data, <span class="number">2</span>))  <span class="comment"># 等价于 data - 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ -7,   7,  -8,  -4,  -9],</span></span><br><span class="line"><span class="string">        [  1,  -1, -11,   7,   0]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 乘</span></span><br><span class="line"><span class="built_in">print</span>(torch.mul(data, <span class="number">2</span>))  <span class="comment"># 等价于 data * 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-10,  18, -12,  -4, -14],</span></span><br><span class="line"><span class="string">        [  6,   2, -18,  18,   4]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 除</span></span><br><span class="line"><span class="built_in">print</span>(torch.div(data, <span class="number">2</span>))  <span class="comment"># 等价于 data / 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-2.5000,  4.5000, -3.0000, -1.0000, -3.5000],</span></span><br><span class="line"><span class="string">        [ 1.5000,  0.5000, -4.5000,  4.5000,  1.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 除完向下取整</span></span><br><span class="line"><span class="built_in">print</span>(torch.div(data, <span class="number">2</span>, rounding_mode=<span class="string">'floor'</span>))  <span class="comment"># 等价于 data // 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-3,  4, -3, -1, -4],</span></span><br><span class="line"><span class="string">        [ 1,  0, -5,  4,  1]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 除完只保留整数</span></span><br><span class="line"><span class="built_in">print</span>(torch.div(data, <span class="number">2</span>, rounding_mode=<span class="string">'trunc'</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-2,  4, -3, -1, -3],</span></span><br><span class="line"><span class="string">        [ 1,  0, -4,  4,  1]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 取余不保留负数</span></span><br><span class="line"><span class="built_in">print</span>(torch.remainder(data, <span class="number">2</span>))  <span class="comment"># 等价于 data % 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1, 1, 0, 0, 1],</span></span><br><span class="line"><span class="string">        [1, 1, 1, 1, 0]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 取余保留负数</span></span><br><span class="line"><span class="built_in">print</span>(torch.fmod(data, <span class="number">2</span>))  <span class="comment"># 等价于 data % -2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-1,  1,  0,  0, -1],</span></span><br><span class="line"><span class="string">        [ 1,  1, -1,  1,  0]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 加号</span></span><br><span class="line"><span class="built_in">print</span>(torch.positive(data))  <span class="comment"># 等价于 +data</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[-5,  9, -6, -2, -7],</span></span><br><span class="line"><span class="string">        [ 3,  1, -9,  9,  2]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 减号</span></span><br><span class="line"><span class="built_in">print</span>(torch.neg(data))  <span class="comment"># 等价于 -data</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 5, -9,  6,  2,  7],</span></span><br><span class="line"><span class="string">        [-3, -1,  9, -9, -2]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 绝对值</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">abs</span>(data))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[5, 9, 6, 2, 7],</span></span><br><span class="line"><span class="string">        [3, 1, 9, 9, 2]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.subtract()</code>是<code>torch.sub()</code>的别名。<br><code>torch.multiply()</code>是<code>torch.mul()</code>的别名。<br><code>torch.divide()</code>是<code>torch.div()</code>的别名。<br><code>torch.true_divide()</code>是<code>torch.div()</code>在<code>rounding_mode=None</code>时的别名。<br><code>torch.negative()</code>是<code>torch.neg()</code>的别名。<br><code>torch.absolute()</code>是<code>torch.abs()</code>的别名。</p><p>在<code>PyTorch 1.13</code>后（含1.13），可以认为<code>torch.floor_divide()</code>是<code>torch.div()</code>在<code>rounding_mode='floor'</code>时的别名，效果是一样的。</p><h3 id="pow-square-sqrt-rsqrt-reciprocal"><a href="#pow-square-sqrt-rsqrt-reciprocal" class="headerlink" title=".pow/.square/.sqrt/.rsqrt/.reciprocal"></a>.pow/.square/.sqrt/.rsqrt/.reciprocal</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.full((<span class="number">2</span>, <span class="number">2</span>), <span class="number">9</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[9, 9],</span></span><br><span class="line"><span class="string">        [9, 9]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 次方</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">pow</span>(data, <span class="number">3</span>))  <span class="comment"># 等价于 data ** 3</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[729, 729],</span></span><br><span class="line"><span class="string">        [729, 729]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 平方</span></span><br><span class="line"><span class="built_in">print</span>(torch.square(data))  <span class="comment"># 等价于 data ** 2</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[81, 81],</span></span><br><span class="line"><span class="string">        [81, 81]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 开方</span></span><br><span class="line"><span class="built_in">print</span>(torch.sqrt(data))  <span class="comment"># 等价于 data ** 0.5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[3., 3.],</span></span><br><span class="line"><span class="string">        [3., 3.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 开方倒数</span></span><br><span class="line"><span class="built_in">print</span>(torch.rsqrt(data))  <span class="comment"># 等价于 data ** -0.5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.3333, 0.3333],</span></span><br><span class="line"><span class="string">        [0.3333, 0.3333]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 倒数</span></span><br><span class="line"><span class="built_in">print</span>(torch.reciprocal(data))  <span class="comment"># 等价于 data ** -1</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.1111, 0.1111],</span></span><br><span class="line"><span class="string">        [0.1111, 0.1111]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="exp-log-log2-log10-log1p"><a href="#exp-log-log2-log10-log1p" class="headerlink" title=".exp/.log/.log2/.log10/.log1p"></a>.exp/.log/.log2/.log10/.log1p</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data1 = torch.exp(torch.tensor([<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]))</span><br><span class="line"><span class="built_in">print</span>(data1)  <span class="comment"># tensor([ 1.0000,  2.7183,  7.3891, 20.0855, 54.5981])</span></span><br><span class="line"></span><br><span class="line">data2 = torch.exp(torch.ones(<span class="number">2</span>, <span class="number">2</span>))</span><br><span class="line"><span class="built_in">print</span>(data2)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[2.7183, 2.7183],</span></span><br><span class="line"><span class="string">        [2.7183, 2.7183]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 以 e 为底</span></span><br><span class="line"><span class="built_in">print</span>(torch.log(data1))  <span class="comment"># tensor([0.0000, 1.0000, 2.0000, 3.0000, 4.0000])</span></span><br><span class="line"><span class="built_in">print</span>(torch.log(data2))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1.0000, 1.0000],</span></span><br><span class="line"><span class="string">        [1.0000, 1.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">data3 = torch.tensor([<span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">8</span>, <span class="number">16</span>])</span><br><span class="line"><span class="comment"># 以 2 为底</span></span><br><span class="line"><span class="built_in">print</span>(torch.log2(data3))  <span class="comment"># tensor([0., 1., 2., 3., 4.])</span></span><br><span class="line"></span><br><span class="line">data4 = torch.tensor([<span class="number">1</span>, <span class="number">10</span>, <span class="number">100</span>, <span class="number">1000</span>, <span class="number">10000</span>])</span><br><span class="line"><span class="comment"># 以 10 为底</span></span><br><span class="line"><span class="built_in">print</span>(torch.log10(data4))  <span class="comment"># tensor([0., 1., 2., 3., 4.])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 以 e 为底，input + 1 做为真数</span></span><br><span class="line"><span class="built_in">print</span>(torch.log1p(data1 - <span class="number">1</span>))  <span class="comment"># tensor([0.0000, 1.0000, 2.0000, 3.0000, 4.0000])</span></span><br><span class="line"><span class="built_in">print</span>(torch.log1p(data2 - <span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1.0000, 1.0000],</span></span><br><span class="line"><span class="string">        [1.0000, 1.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.log1p()</code>计算<code>input + 1</code>的自然对数：<script type="math/tex">y_i = ln(x_i+1)</script>。</p><h3 id="sin-cos-tan-asin-acos-atan-atan2-sinh-cosh-tanh"><a href="#sin-cos-tan-asin-acos-atan-atan2-sinh-cosh-tanh" class="headerlink" title=".sin/.cos/.tan/.asin/.acos/.atan/.atan2/.sinh/.cosh/.tanh"></a>.sin/.cos/.tan/.asin/.acos/.atan/.atan2/.sinh/.cosh/.tanh</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.deg2rad(torch.arange(<span class="number">0</span>, <span class="number">361</span>, <span class="number">30</span>))  <span class="comment"># 角度转弧度</span></span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 正弦</span></span><br><span class="line"><span class="built_in">print</span>(torch.sin(data))</span><br><span class="line"><span class="comment"># 余弦</span></span><br><span class="line"><span class="built_in">print</span>(torch.cos(data))</span><br><span class="line"><span class="comment"># 正切</span></span><br><span class="line"><span class="built_in">print</span>(torch.tan(data))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 反正弦</span></span><br><span class="line"><span class="built_in">print</span>(torch.asin(data))</span><br><span class="line"><span class="comment"># 反余弦</span></span><br><span class="line"><span class="built_in">print</span>(torch.acos(data))</span><br><span class="line"><span class="comment"># 反正切</span></span><br><span class="line"><span class="built_in">print</span>(torch.atan(data))</span><br><span class="line"><span class="built_in">print</span>(torch.atan2(data, data))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 双曲正弦</span></span><br><span class="line"><span class="built_in">print</span>(torch.sinh(data))</span><br><span class="line"><span class="comment"># 双曲余弦</span></span><br><span class="line"><span class="built_in">print</span>(torch.cosh(data))</span><br><span class="line"><span class="comment"># 双曲正切</span></span><br><span class="line"><span class="built_in">print</span>(torch.tanh(data))</span><br></pre></td></tr></tbody></table></figure><p><code>torch.arcsin()</code>是<code>torch.asin()</code>的别名。<br><code>torch.arccos()</code>是<code>torch.acos()</code>的别名。<br><code>torch.arctan()</code>是<code>torch.atan()</code>的别名。<br><code>torch.arctan2()</code>是<code>torch.atan2()</code>的别名。<br><code>torch.arcsinh()</code>是<code>torch.asinh()</code>的别名。<br><code>torch.arccosh()</code>是<code>torch.acosh()</code>的别名。<br><code>torch.arctanh()</code>是<code>torch.atanh()</code>的别名。</p><h3 id="angle-deg2rad"><a href="#angle-deg2rad" class="headerlink" title=".angle/.deg2rad"></a>.angle/.deg2rad</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 复数转弧度，结果在（π, -π）之间</span></span><br><span class="line"><span class="built_in">print</span>(torch.angle(torch.tensor([[<span class="number">1</span>, <span class="number">1</span> + <span class="number">1j</span>, <span class="number">1j</span>, -<span class="number">1</span> + <span class="number">1j</span>, -<span class="number">1</span>, -<span class="number">1</span> -<span class="number">1j</span>, -<span class="number">1j</span>, <span class="number">1</span> -<span class="number">1j</span>]])))  <span class="comment"># tensor([[ 0.0000,  0.7854,  1.5708,  2.3562,  3.1416, -2.3562, -1.5708, -0.7854]])</span></span><br><span class="line"><span class="comment"># 弧度转角度</span></span><br><span class="line"><span class="built_in">print</span>(torch.angle(torch.tensor([[<span class="number">1</span>, <span class="number">1</span> + <span class="number">1j</span>, <span class="number">1j</span>, -<span class="number">1</span> + <span class="number">1j</span>, -<span class="number">1</span>, -<span class="number">1</span> -<span class="number">1j</span>, -<span class="number">1j</span>, <span class="number">1</span> -<span class="number">1j</span>]])) * <span class="number">180</span> / np.pi)  <span class="comment"># tensor([[   0.0000,   45.0000,   90.0000,  135.0000,  180.0000, -135.0000, -90.0000,  -45.0000]])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 角度转弧度</span></span><br><span class="line"><span class="built_in">print</span>(torch.deg2rad(torch.tensor([[<span class="number">0</span>, <span class="number">45</span>, <span class="number">90</span>, <span class="number">135</span>, <span class="number">180</span>, <span class="number">360</span>], [-<span class="number">360</span>, -<span class="number">180</span>, -<span class="number">135</span>, -<span class="number">90</span>, -<span class="number">45</span>, <span class="number">0</span>]])))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ 0.0000,  0.7854,  1.5708,  2.3562,  3.1416,  6.2832],</span></span><br><span class="line"><span class="string">        [-6.2832, -3.1416, -2.3562, -1.5708, -0.7854,  0.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="bitwise-and-bitwise-or-bitwise-not-bitwise-xor-bitwise-left-shift-bitwise-right-shift"><a href="#bitwise-and-bitwise-or-bitwise-not-bitwise-xor-bitwise-left-shift-bitwise-right-shift" class="headerlink" title=".bitwise_and/.bitwise_or/.bitwise_not/.bitwise_xor/.bitwise_left_shift/.bitwise_right_shift"></a>.bitwise_and/.bitwise_or/.bitwise_not/.bitwise_xor/.bitwise_left_shift/.bitwise_right_shift</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 按位与</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_and(torch.tensor([-<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>], dtype=torch.int8), torch.tensor([<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>], dtype=torch.int8)))  <span class="comment"># tensor([1, 0, 3], dtype=torch.int8)</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_and(torch.tensor([<span class="literal">True</span>, <span class="literal">True</span>, <span class="literal">False</span>]), torch.tensor([<span class="literal">False</span>, <span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor([False,  True, False])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按位或</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_or(torch.tensor([-<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>], dtype=torch.int8), torch.tensor([<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>], dtype=torch.int8)))  <span class="comment"># tensor([-1, -2,  3], dtype=torch.int8)</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_or(torch.tensor([<span class="literal">True</span>, <span class="literal">True</span>, <span class="literal">False</span>]), torch.tensor([<span class="literal">False</span>, <span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor([ True,  True, False])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按位非</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_not(torch.tensor([-<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>], dtype=torch.int8)))  <span class="comment"># tensor([ 0,  1, -4], dtype=torch.int8)</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_not(torch.tensor([<span class="literal">True</span>, <span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor([False, False,  True])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按位异或</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_xor(torch.tensor([-<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>], dtype=torch.int8), torch.tensor([<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>], dtype=torch.int8)))  <span class="comment"># tensor([-2, -2,  0], dtype=torch.int8)</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_xor(torch.tensor([<span class="literal">True</span>, <span class="literal">True</span>, <span class="literal">False</span>]), torch.tensor([<span class="literal">False</span>, <span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor([ True, False, False])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 左移</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_left_shift(torch.tensor([-<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>], dtype=torch.int8), torch.tensor([<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>], dtype=torch.int8)))  <span class="comment"># tensor([-2, -2, 24], dtype=torch.int8)</span></span><br><span class="line"><span class="comment"># 右移</span></span><br><span class="line"><span class="built_in">print</span>(torch.bitwise_right_shift(torch.tensor([-<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>], dtype=torch.int8), torch.tensor([<span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>], dtype=torch.int8)))  <span class="comment"># tensor([-1, -2,  0], dtype=torch.int8)</span></span><br></pre></td></tr></tbody></table></figure><h3 id="floor-ceil-round"><a href="#floor-ceil-round" class="headerlink" title=".floor/.ceil/.round"></a>.floor/.ceil/.round</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.rand(<span class="number">1</span>, <span class="number">5</span>) * <span class="number">10</span></span><br><span class="line"><span class="built_in">print</span>(data)  <span class="comment"># tensor([[7.5763, 2.7931, 4.0307, 7.3468, 0.2928]])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 向下取整</span></span><br><span class="line"><span class="built_in">print</span>(torch.floor(data))  <span class="comment"># tensor([[7., 2., 4., 7., 0.]])</span></span><br><span class="line"><span class="comment"># 向上取整</span></span><br><span class="line"><span class="built_in">print</span>(torch.ceil(data))  <span class="comment"># tensor([[8., 3., 5., 8., 1.]])</span></span><br><span class="line"><span class="comment"># 四舍五入</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">round</span>(data))  <span class="comment"># tensor([[8., 3., 4., 7., 0.]])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.floor()</code>向下取整，<code>torch.ceil()</code>向上取整，<code>torch.round()</code>四舍五入。</p><h3 id="trunc-frac"><a href="#trunc-frac" class="headerlink" title=".trunc/.frac"></a>.trunc/.frac</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.rand(<span class="number">1</span>, <span class="number">5</span>) * <span class="number">10</span></span><br><span class="line"><span class="built_in">print</span>(data)  <span class="comment"># tensor([[7.5763, 2.7931, 4.0307, 7.3468, 0.2928]])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 取整数</span></span><br><span class="line"><span class="built_in">print</span>(torch.trunc(data))  <span class="comment"># tensor([[7., 2., 4., 7., 0.]])</span></span><br><span class="line"><span class="comment"># 取小数</span></span><br><span class="line"><span class="built_in">print</span>(torch.frac(data))  <span class="comment"># tensor([[0.5763, 0.7931, 0.0307, 0.3468, 0.2928]])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.trunc()</code>取整数，<code>torch.frac()</code>取小数。</p><p><code>torch.fix()</code>是<code>torch.trunc()</code>的别名。</p><h3 id="clamp-clamp-min-clamp-max"><a href="#clamp-clamp-min-clamp-max" class="headerlink" title=".clamp/.clamp_min/.clamp_max"></a>.clamp/.clamp_min/.clamp_max</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.rand((<span class="number">2</span>, <span class="number">5</span>)) * <span class="number">20</span></span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15.1526,  5.5862,  8.0614, 14.6937,  0.5856],</span></span><br><span class="line"><span class="string">        [15.9972,  7.9427, 15.0874, 11.3902,  8.7756]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 小于 10 的数变为 10</span></span><br><span class="line"><span class="built_in">print</span>(torch.clamp(data, <span class="number">10</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15.1526, 10.0000, 10.0000, 14.6937, 10.0000],</span></span><br><span class="line"><span class="string">        [15.9972, 10.0000, 15.0874, 11.3902, 10.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 大于 15 的数变为 15</span></span><br><span class="line"><span class="built_in">print</span>(torch.clamp(data, <span class="built_in">max</span>=<span class="number">15</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15.0000,  5.5862,  8.0614, 14.6937,  0.5856],</span></span><br><span class="line"><span class="string">        [15.0000,  7.9427, 15.0000, 11.3902,  8.7756]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 小于 10 的数变为 10，大于 15 的数变为 15</span></span><br><span class="line"><span class="built_in">print</span>(torch.clamp(data, <span class="number">10</span>, <span class="number">15</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15.0000, 10.0000, 10.0000, 14.6937, 10.0000],</span></span><br><span class="line"><span class="string">        [15.0000, 10.0000, 15.0000, 11.3902, 10.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 小于 10 的数变为 10</span></span><br><span class="line"><span class="built_in">print</span>(torch.clamp_min(data, <span class="number">10</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15.1526, 10.0000, 10.0000, 14.6937, 10.0000],</span></span><br><span class="line"><span class="string">        [15.9972, 10.0000, 15.0874, 11.3902, 10.0000]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 大于 15 的数变为 15</span></span><br><span class="line"><span class="built_in">print</span>(torch.clamp_max(data, <span class="number">15</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[15.0000,  5.5862,  8.0614, 14.6937,  0.5856],</span></span><br><span class="line"><span class="string">        [15.0000,  7.9427, 15.0000, 11.3902,  8.7756]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.clamp()</code>用于将输入的张量夹紧到区间<code>[min, max]</code>。</p><p><code>torch.clip()</code>是<code>torch.clamp()</code>的别名。</p><h3 id="dot-mm-bmm-matmul"><a href="#dot-mm-bmm-matmul" class="headerlink" title=".dot/.mm/.bmm/.matmul"></a>.dot/.mm/.bmm/.matmul</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 一维矩阵相乘</span></span><br><span class="line"><span class="built_in">print</span>(torch.dot(torch.tensor([<span class="number">1</span>, <span class="number">2</span>]), torch.tensor([<span class="number">3</span>, <span class="number">4</span>])))  <span class="comment"># tensor(11)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 二维矩阵相乘</span></span><br><span class="line"><span class="built_in">print</span>(torch.mm(torch.full((<span class="number">2</span>, <span class="number">3</span>), <span class="number">2</span>), torch.full((<span class="number">3</span>, <span class="number">2</span>), <span class="number">3</span>)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[18, 18],</span></span><br><span class="line"><span class="string">        [18, 18]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 三维矩阵相乘</span></span><br><span class="line"><span class="built_in">print</span>(torch.bmm(torch.full((<span class="number">2</span>, <span class="number">2</span>, <span class="number">3</span>), <span class="number">2</span>), torch.full((<span class="number">2</span>, <span class="number">3</span>, <span class="number">2</span>), <span class="number">3</span>)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[[18, 18],</span></span><br><span class="line"><span class="string">         [18, 18]],</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        [[18, 18],</span></span><br><span class="line"><span class="string">         [18, 18]]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line">data1 = torch.rand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">800</span>, <span class="number">600</span>)</span><br><span class="line"><span class="built_in">print</span>(data1.shape)  <span class="comment"># torch.Size([4, 3, 800, 600])</span></span><br><span class="line">data2 = torch.rand(<span class="number">4</span>, <span class="number">3</span>, <span class="number">600</span>, <span class="number">400</span>)</span><br><span class="line"><span class="built_in">print</span>(data2.shape)  <span class="comment"># torch.Size([4, 3, 600, 400])</span></span><br><span class="line"><span class="comment"># data1 @ data2 等价于 data1.matmul(data2)</span></span><br><span class="line"><span class="built_in">print</span>(data1.matmul(data2).shape)  <span class="comment"># torch.Size([4, 3, 800, 400])</span></span><br></pre></td></tr></tbody></table></figure><p><code>dot()</code>只支持一维矩阵相乘，<code>mm()</code>只支持二维矩阵相乘，<code>bmm()</code>只支持三维矩阵相乘，<code>matmul()</code>支持任意维度矩阵相乘。</p><h2 id="比较运算"><a href="#比较运算" class="headerlink" title="比较运算"></a>比较运算</h2><h3 id="eq-ne-gt-ge-lt-le-equal"><a href="#eq-ne-gt-ge-lt-le-equal" class="headerlink" title=".eq/.ne/.gt/.ge/.lt/.le/.equal"></a>.eq/.ne/.gt/.ge/.lt/.le/.equal</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.randperm(<span class="number">10</span>).view(<span class="number">2</span>, <span class="number">5</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[5, 6, 1, 2, 0],</span></span><br><span class="line"><span class="string">        [8, 9, 3, 7, 4]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 等于</span></span><br><span class="line"><span class="built_in">print</span>(torch.eq(data, <span class="number">5</span>))  <span class="comment"># 等价于 data == 5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ True, False, False, False, False],</span></span><br><span class="line"><span class="string">        [False, False, False, False, False]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 不等于</span></span><br><span class="line"><span class="built_in">print</span>(torch.ne(data, <span class="number">5</span>))  <span class="comment"># 等价于 data != 5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[False,  True,  True,  True,  True],</span></span><br><span class="line"><span class="string">        [ True,  True,  True,  True,  True]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 大于</span></span><br><span class="line"><span class="built_in">print</span>(torch.gt(data, <span class="number">5</span>))  <span class="comment"># 等价于 data &gt; 5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[False,  True, False, False, False],</span></span><br><span class="line"><span class="string">        [ True,  True, False,  True, False]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 大于等于</span></span><br><span class="line"><span class="built_in">print</span>(torch.ge(data, <span class="number">5</span>))  <span class="comment"># 等价于 data &gt;= 5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ True,  True, False, False, False],</span></span><br><span class="line"><span class="string">        [ True,  True, False,  True, False]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 小于</span></span><br><span class="line"><span class="built_in">print</span>(torch.lt(data, <span class="number">5</span>))  <span class="comment"># 等价于 data &lt; 5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[False, False,  True,  True,  True],</span></span><br><span class="line"><span class="string">        [False, False,  True, False,  True]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 小于等于</span></span><br><span class="line"><span class="built_in">print</span>(torch.le(data, <span class="number">5</span>))  <span class="comment"># 等价于 data &lt;= 5</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[ True, False,  True,  True,  True],</span></span><br><span class="line"><span class="string">        [False, False,  True, False,  True]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 比较两个 tensor 是否相同</span></span><br><span class="line"><span class="built_in">print</span>(torch.equal(torch.tensor([<span class="number">1</span>, <span class="number">2</span>]), torch.tensor([<span class="number">1</span>, <span class="number">2</span>])))  <span class="comment"># True</span></span><br><span class="line"><span class="built_in">print</span>(torch.equal(torch.tensor([<span class="number">1</span>, <span class="number">2</span>]), torch.tensor([<span class="number">2</span>, <span class="number">1</span>])))  <span class="comment"># False</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.not_equal()</code>是<code>torch.ne()</code>的别名。<br><code>torch.greater()</code>是<code>torch.gt()</code>的别名。<br><code>torch.greater_equal()</code>是<code>torch.ge()</code>的别名。<br><code>torch.less()</code>是<code>torch.lt()</code>的别名。<br><code>torch.less_equal()</code>是<code>torch.le()</code>的别名。</p><h3 id="isfinite-isinf-isposinf-isneginf-isnan-isreal-isin"><a href="#isfinite-isinf-isposinf-isneginf-isnan-isreal-isin" class="headerlink" title=".isfinite/.isinf/.isposinf/.isneginf/.isnan/.isreal/.isin"></a>.isfinite/.isinf/.isposinf/.isneginf/.isnan/.isreal/.isin</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor([<span class="number">1</span>, <span class="built_in">float</span>(<span class="string">'inf'</span>), torch.inf, <span class="built_in">float</span>(<span class="string">'-inf'</span>), -torch.inf, <span class="built_in">float</span>(<span class="string">'nan'</span>), torch.nan, <span class="literal">True</span>, <span class="literal">False</span>])</span><br><span class="line"><span class="comment"># 是否不是无穷大</span></span><br><span class="line"><span class="built_in">print</span>(torch.isfinite(data))  <span class="comment"># tensor([ True, False, False, False, False, False, False,  True,  True])</span></span><br><span class="line"><span class="comment"># 是否是无穷大</span></span><br><span class="line"><span class="built_in">print</span>(torch.isinf(data))  <span class="comment"># tensor([False,  True,  True,  True,  True, False, False, False, False])</span></span><br><span class="line"><span class="comment"># 是否是正无穷大</span></span><br><span class="line"><span class="built_in">print</span>(torch.isposinf(data))  <span class="comment"># tensor([False,  True,  True, False, False, False, False, False, False])</span></span><br><span class="line"><span class="comment"># 是否是负无穷大</span></span><br><span class="line"><span class="built_in">print</span>(torch.isneginf(data))  <span class="comment"># tensor([False, False, False,  True,  True, False, False, False, False])</span></span><br><span class="line"><span class="comment"># 是否是 NaN</span></span><br><span class="line"><span class="built_in">print</span>(torch.isnan(data))  <span class="comment"># tensor([False, False, False, False, False,  True,  True, False, False])</span></span><br><span class="line"><span class="comment"># 是否是实数</span></span><br><span class="line"><span class="built_in">print</span>(torch.isreal(torch.tensor([<span class="number">1</span>, <span class="number">1</span>+<span class="number">1j</span>, <span class="number">2</span>+<span class="number">0j</span>, <span class="built_in">float</span>(<span class="string">'nan'</span>), <span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor([ True, False,  True,  True,  True,  True])</span></span><br><span class="line"></span><br><span class="line">elements = [[<span class="number">1</span>, <span class="number">2</span>], [<span class="number">3</span>, <span class="number">4</span>]]</span><br><span class="line">test_elements = [<span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="comment"># 对 elements 的每个元素进行判断是否在 test_elements 中</span></span><br><span class="line"><span class="built_in">print</span>(torch.isin(torch.tensor(elements), torch.tensor(test_elements)))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[False,  True],</span></span><br><span class="line"><span class="string">        [ True, False]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="isclose-allclose"><a href="#isclose-allclose" class="headerlink" title=".isclose/.allclose"></a>.isclose/.allclose</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否接近</span></span><br><span class="line"><span class="built_in">print</span>(torch.isclose(torch.tensor((<span class="number">1.</span>, <span class="number">2</span>, <span class="number">3</span>)), torch.tensor((<span class="number">1</span> + <span class="number">1e-10</span>, <span class="number">3</span>, <span class="number">4</span>))))  <span class="comment"># tensor([ True, False, False])</span></span><br><span class="line"><span class="built_in">print</span>(torch.isclose(torch.tensor((<span class="built_in">float</span>(<span class="string">'inf'</span>), <span class="number">4</span>)), torch.tensor((<span class="built_in">float</span>(<span class="string">'inf'</span>), <span class="number">6</span>)), rtol=<span class="number">.5</span>))  <span class="comment"># tensor([True, True])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否都接近</span></span><br><span class="line"><span class="built_in">print</span>(torch.allclose(torch.tensor([<span class="number">10000.</span>, <span class="number">1e-07</span>]), torch.tensor([<span class="number">10000.1</span>, <span class="number">1e-08</span>])))  <span class="comment"># False</span></span><br><span class="line"><span class="built_in">print</span>(torch.allclose(torch.tensor([<span class="number">10000.</span>, <span class="number">1e-08</span>]), torch.tensor([<span class="number">10000.1</span>, <span class="number">1e-09</span>])))  <span class="comment"># True</span></span><br><span class="line"><span class="built_in">print</span>(torch.allclose(torch.tensor([<span class="number">1.0</span>, <span class="built_in">float</span>(<span class="string">'nan'</span>)]), torch.tensor([<span class="number">1.0</span>, <span class="built_in">float</span>(<span class="string">'nan'</span>)])))  <span class="comment"># False</span></span><br><span class="line"><span class="built_in">print</span>(torch.allclose(torch.tensor([<span class="number">1.0</span>, <span class="built_in">float</span>(<span class="string">'nan'</span>)]), torch.tensor([<span class="number">1.0</span>, <span class="built_in">float</span>(<span class="string">'nan'</span>)]), equal_nan=<span class="literal">True</span>))  <span class="comment"># True</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.isclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False)</code></p><p><code>torch.allclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False)</code></p><p>校验是否接近公式：<script type="math/tex">|input - other| \le atol + rtol \times |other|</script></p><h3 id="maximum-minimum-fmax-fmin"><a href="#maximum-minimum-fmax-fmin" class="headerlink" title=".maximum/.minimum/.fmax/.fmin"></a>.maximum/.minimum/.fmax/.fmin</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data1 = torch.tensor([<span class="number">9.7</span>, <span class="built_in">float</span>(<span class="string">'nan'</span>), <span class="number">3.1</span>, torch.nan, <span class="number">11.1</span>])</span><br><span class="line">data2 = torch.tensor([-<span class="number">2.2</span>, <span class="number">0.5</span>, torch.nan, <span class="built_in">float</span>(<span class="string">'nan'</span>), <span class="number">7.8</span>])</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.maximum(data1, data2))  <span class="comment"># tensor([ 9.7000,     nan,     nan,     nan, 11.1000])</span></span><br><span class="line"><span class="built_in">print</span>(torch.minimum(data1, data2))  <span class="comment"># tensor([-2.2000,     nan,     nan,     nan,  7.8000])</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.fmax(data1, data2))  <span class="comment"># tensor([ 9.7000,  0.5000,  3.1000,     nan, 11.1000])</span></span><br><span class="line"><span class="built_in">print</span>(torch.fmin(data1, data2))  <span class="comment"># tensor([-2.2000,  0.5000,  3.1000,     nan,  7.8000])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.maximum()</code>和<code>torch.minimum()</code>用于比较两数的大小，不支持比较<code>NaN</code>。</p><p><code>torch.fmax()</code>和<code>torch.fmin()</code>用于比较两数的大小，支持比较<code>NaN</code>。</p><h3 id="sort-msort-argsort"><a href="#sort-msort-argsort" class="headerlink" title=".sort/.msort/.argsort"></a>.sort/.msort/.argsort</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.rand(<span class="number">2</span>, <span class="number">5</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031, 0.7347, 0.0293],</span></span><br><span class="line"><span class="string">        [0.7999, 0.3971, 0.7544, 0.5695, 0.4388]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment">### dim 默认等于 -1，按列进行排序</span></span><br><span class="line"><span class="built_in">print</span>(torch.sort(data))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.sort(</span></span><br><span class="line"><span class="string">values=tensor([[0.0293, 0.2793, 0.4031, 0.7347, 0.7576],</span></span><br><span class="line"><span class="string">        [0.3971, 0.4388, 0.5695, 0.7544, 0.7999]]),</span></span><br><span class="line"><span class="string">indices=tensor([[4, 1, 2, 3, 0],</span></span><br><span class="line"><span class="string">        [1, 4, 3, 2, 0]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 按行进行排序</span></span><br><span class="line"><span class="built_in">print</span>(torch.sort(data, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.sort(</span></span><br><span class="line"><span class="string">values=tensor([[0.7576, 0.2793, 0.4031, 0.5695, 0.0293],</span></span><br><span class="line"><span class="string">        [0.7999, 0.3971, 0.7544, 0.7347, 0.4388]]),</span></span><br><span class="line"><span class="string">indices=tensor([[0, 0, 0, 1, 0],</span></span><br><span class="line"><span class="string">        [1, 1, 1, 0, 1]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># descending=True 降序排序</span></span><br><span class="line"><span class="built_in">print</span>(torch.sort(data, descending=<span class="literal">True</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.sort(</span></span><br><span class="line"><span class="string">values=tensor([[0.7576, 0.7347, 0.4031, 0.2793, 0.0293],</span></span><br><span class="line"><span class="string">        [0.7999, 0.7544, 0.5695, 0.4388, 0.3971]]),</span></span><br><span class="line"><span class="string">indices=tensor([[0, 3, 2, 1, 4],</span></span><br><span class="line"><span class="string">        [0, 2, 3, 4, 1]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 沿第一维度进行排序</span></span><br><span class="line"><span class="built_in">print</span>(torch.msort(data))  <span class="comment"># 等价于 torch.sort(data, dim=0)[0]</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031, 0.5695, 0.0293],</span></span><br><span class="line"><span class="string">        [0.7999, 0.3971, 0.7544, 0.7347, 0.4388]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment">### dim 默认等于 -1，按列进行排序，返回索引</span></span><br><span class="line"><span class="built_in">print</span>(torch.argsort(data))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[4, 1, 2, 3, 0],</span></span><br><span class="line"><span class="string">        [1, 4, 3, 2, 0]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 按行进行排序，返回索引</span></span><br><span class="line"><span class="built_in">print</span>(torch.argsort(data, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 0, 0, 1, 0],</span></span><br><span class="line"><span class="string">        [1, 1, 1, 0, 1]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># descending=True 降序排序，返回索引</span></span><br><span class="line"><span class="built_in">print</span>(torch.argsort(data, descending=<span class="literal">True</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0, 3, 2, 1, 4],</span></span><br><span class="line"><span class="string">        [0, 2, 3, 4, 1]])</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.sort()</code>排序后返回排序结果和索引。</p><p><code>torch.msort(input))</code>等价于<code>torch.sort()</code>对第一维度进行排序在取排序结果，<code>torch.sort(input, dim=0)[0]</code>，返回结果不包含索引。</p><p><code>torch.argsort()</code>返回排序后的索引。</p><h3 id="topk-kthvalue"><a href="#topk-kthvalue" class="headerlink" title=".topk/.kthvalue"></a>.topk/.kthvalue</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.randperm(<span class="number">30</span>, dtype=torch.double).view(<span class="number">3</span>, <span class="number">10</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[25.,  4.,  6.,  8., 23., 18., 17., 20., 19., 12.],</span></span><br><span class="line"><span class="string">        [ 5., 14., 22.,  3., 27., 15.,  9., 13.,  7., 11.],</span></span><br><span class="line"><span class="string">        [10.,  2., 24., 29., 21., 26., 28.,  1., 16.,  0.]],</span></span><br><span class="line"><span class="string">       dtype=torch.float64)</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取前 k 大的数据</span></span><br><span class="line"><span class="built_in">print</span>(torch.topk(data, <span class="number">3</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.topk(</span></span><br><span class="line"><span class="string">values=tensor([[25., 23., 20.],</span></span><br><span class="line"><span class="string">        [27., 22., 15.],</span></span><br><span class="line"><span class="string">        [29., 28., 26.]], dtype=torch.float64),</span></span><br><span class="line"><span class="string">indices=tensor([[0, 4, 7],</span></span><br><span class="line"><span class="string">        [4, 2, 5],</span></span><br><span class="line"><span class="string">        [3, 6, 5]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="comment"># 获取前 k 小的数据</span></span><br><span class="line"><span class="built_in">print</span>(torch.topk(data, <span class="number">3</span>, largest=<span class="literal">False</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.topk(</span></span><br><span class="line"><span class="string">values=tensor([[4., 6., 8.],</span></span><br><span class="line"><span class="string">        [3., 5., 7.],</span></span><br><span class="line"><span class="string">        [0., 1., 2.]], dtype=torch.float64),</span></span><br><span class="line"><span class="string">indices=tensor([[1, 2, 3],</span></span><br><span class="line"><span class="string">        [3, 0, 8],</span></span><br><span class="line"><span class="string">        [9, 7, 1]]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取第 k 小的数据</span></span><br><span class="line"><span class="built_in">print</span>(torch.kthvalue(data, <span class="number">8</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.kthvalue(</span></span><br><span class="line"><span class="string">values=tensor([20., 15., 26.], dtype=torch.float64),</span></span><br><span class="line"><span class="string">indices=tensor([7, 5, 5]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.kthvalue(data, <span class="number">2</span>, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.kthvalue(</span></span><br><span class="line"><span class="string">values=tensor([10.,  4., 22.,  8., 23., 18., 17., 13., 16., 11.], dtype=torch.float64),</span></span><br><span class="line"><span class="string">indices=tensor([2, 0, 1, 0, 0, 0, 0, 1, 2, 1]))</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.topk()</code>获取前<code>k</code>大的数据，<code>torch.kthvalue()</code>获取第<code>k</code>小的数据。</p><h2 id="归约运算"><a href="#归约运算" class="headerlink" title="归约运算"></a>归约运算</h2><h3 id="max-min-amax-amin-aminmax-argmax-argmin"><a href="#max-min-amax-amin-aminmax-argmax-argmin" class="headerlink" title=".max/.min/.amax/.amin/.aminmax/.argmax/.argmin"></a>.max/.min/.amax/.amin/.aminmax/.argmax/.argmin</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">torch.manual_seed(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">data = torch.rand(<span class="number">4</span>, <span class="number">4</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[0.7576, 0.2793, 0.4031, 0.7347],</span></span><br><span class="line"><span class="string">        [0.0293, 0.7999, 0.3971, 0.7544],</span></span><br><span class="line"><span class="string">        [0.5695, 0.4388, 0.6387, 0.5247],</span></span><br><span class="line"><span class="string">        [0.6826, 0.3051, 0.4635, 0.4550]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最大值</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">max</span>(data))  <span class="comment"># tensor(0.7999)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">max</span>(data, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.max(</span></span><br><span class="line"><span class="string">values=tensor([0.7576, 0.7999, 0.6387, 0.7544]),</span></span><br><span class="line"><span class="string">indices=tensor([0, 1, 2, 1]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最小值</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">min</span>(data))  <span class="comment"># tensor(0.0293)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">min</span>(data, dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.min(</span></span><br><span class="line"><span class="string">values=tensor([0.2793, 0.0293, 0.4388, 0.3051]),</span></span><br><span class="line"><span class="string">indices=tensor([1, 0, 1, 1]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最大值</span></span><br><span class="line"><span class="built_in">print</span>(torch.amax(data))  <span class="comment"># tensor(0.7999)</span></span><br><span class="line"><span class="built_in">print</span>(torch.amax(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([0.7576, 0.7999, 0.6387, 0.7544])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最小值</span></span><br><span class="line"><span class="built_in">print</span>(torch.amin(data))  <span class="comment"># tensor(0.0293)</span></span><br><span class="line"><span class="built_in">print</span>(torch.amin(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([0.2793, 0.0293, 0.4388, 0.3051])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最大值和最小值</span></span><br><span class="line"><span class="built_in">print</span>(torch.aminmax(data))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.aminmax(</span></span><br><span class="line"><span class="string">min=tensor(0.0293),</span></span><br><span class="line"><span class="string">max=tensor(0.7999))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.aminmax(data, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.aminmax(</span></span><br><span class="line"><span class="string">min=tensor([0.0293, 0.2793, 0.3971, 0.4550]),</span></span><br><span class="line"><span class="string">max=tensor([0.7576, 0.7999, 0.6387, 0.7544]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最大值索引</span></span><br><span class="line"><span class="built_in">print</span>(torch.argmax(data))  <span class="comment"># tensor(5)</span></span><br><span class="line"><span class="built_in">print</span>(torch.argmax(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([0, 1, 2, 1])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 最小值索引</span></span><br><span class="line"><span class="built_in">print</span>(torch.argmin(data))  <span class="comment"># tensor(4)</span></span><br><span class="line"><span class="built_in">print</span>(torch.argmin(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([1, 0, 1, 1])</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.max()</code>和<code>torch.min()</code>指定了<code>dim</code>时，返回极值和索引。</p><p><code>torch.amax()</code>和<code>torch.amin()</code>只返回极值，不返回索引。</p><p><code>torch.argmax()</code>和<code>torch.argmin()</code>返回极值对应的索引。不指定<code>dim</code>时，返回的是打平后的索引。</p><h3 id="mean-nanmean"><a href="#mean-nanmean" class="headerlink" title=".mean/.nanmean"></a>.mean/.nanmean</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor([[torch.nan, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>], [<span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>], [<span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>, torch.nan]])</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[nan,  1.,  2.,  3.,  4.],</span></span><br><span class="line"><span class="string">        [ 5.,  6.,  7.,  8.,  9.],</span></span><br><span class="line"><span class="string">        [10., 11., 12., 13., nan]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 平均值</span></span><br><span class="line"><span class="built_in">print</span>(torch.mean(data))  <span class="comment"># tensor(nan)</span></span><br><span class="line"><span class="built_in">print</span>(torch.mean(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([nan, 6., 7., 8., nan])</span></span><br><span class="line"><span class="built_in">print</span>(torch.mean(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([nan, 7., nan])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 平均值（忽略 NaN 值）</span></span><br><span class="line"><span class="built_in">print</span>(torch.nanmean(data))  <span class="comment"># tensor(7.)</span></span><br><span class="line"><span class="built_in">print</span>(torch.nanmean(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([7.5000, 6.0000, 7.0000, 8.0000, 6.5000])</span></span><br><span class="line"><span class="built_in">print</span>(torch.nanmean(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([ 2.5000,  7.0000, 11.5000])</span></span><br></pre></td></tr></tbody></table></figure><h3 id="median-nanmedian"><a href="#median-nanmedian" class="headerlink" title=".median/.nanmedian"></a>.median/.nanmedian</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor([[torch.nan, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>], [<span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>], [<span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>, torch.nan]])</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[nan,  1.,  2.,  3.,  4.],</span></span><br><span class="line"><span class="string">        [ 5.,  6.,  7.,  8.,  9.],</span></span><br><span class="line"><span class="string">        [10., 11., 12., 13., nan]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 中位数</span></span><br><span class="line"><span class="built_in">print</span>(torch.median(data))  <span class="comment"># tensor(nan)</span></span><br><span class="line"><span class="built_in">print</span>(torch.median(data, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.median(</span></span><br><span class="line"><span class="string">values=tensor([nan, 6., 7., 8., nan]),</span></span><br><span class="line"><span class="string">indices=tensor([0, 1, 1, 1, 2]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.median(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([nan, 7., nan])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.median(</span></span><br><span class="line"><span class="string">values=tensor([nan, 7., nan]),</span></span><br><span class="line"><span class="string">indices=tensor([0, 2, 4]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 中位数（忽略 NaN 值）</span></span><br><span class="line"><span class="built_in">print</span>(torch.nanmedian(data))  <span class="comment"># tensor(7.)</span></span><br><span class="line"><span class="built_in">print</span>(torch.nanmedian(data, dim=<span class="number">0</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.nanmedian(</span></span><br><span class="line"><span class="string">values=tensor([5., 6., 7., 8., 4.]),</span></span><br><span class="line"><span class="string">indices=tensor([1, 1, 1, 1, 0]))</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="built_in">print</span>(torch.nanmedian(data, dim=<span class="number">1</span>))</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">torch.return_types.nanmedian(</span></span><br><span class="line"><span class="string">values=tensor([ 2.,  7., 11.]),</span></span><br><span class="line"><span class="string">indices=tensor([2, 2, 1]))</span></span><br><span class="line"><span class="string">"""</span></span><br></pre></td></tr></tbody></table></figure><h3 id="sum-nansum"><a href="#sum-nansum" class="headerlink" title=".sum/.nansum"></a>.sum/.nansum</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor([[torch.nan, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>], [<span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>], [<span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>, torch.nan]])</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[nan,  1.,  2.,  3.,  4.],</span></span><br><span class="line"><span class="string">        [ 5.,  6.,  7.,  8.,  9.],</span></span><br><span class="line"><span class="string">        [10., 11., 12., 13., nan]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 累加</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">sum</span>(data))  <span class="comment"># tensor(nan)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">sum</span>(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([nan, 18., 21., 24., nan])</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">sum</span>(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([nan, 35., nan])</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 累加（忽略 NaN 值）</span></span><br><span class="line"><span class="built_in">print</span>(torch.nansum(data))  <span class="comment"># tensor(91.)</span></span><br><span class="line"><span class="built_in">print</span>(torch.nansum(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([15., 18., 21., 24., 13.])</span></span><br><span class="line"><span class="built_in">print</span>(torch.nansum(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([10., 35., 46.])</span></span><br></pre></td></tr></tbody></table></figure><h3 id="prod"><a href="#prod" class="headerlink" title=".prod"></a>.prod</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.tensor([[torch.nan, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>], [<span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>], [<span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>, torch.nan]])</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[nan,  1.,  2.,  3.,  4.],</span></span><br><span class="line"><span class="string">        [ 5.,  6.,  7.,  8.,  9.],</span></span><br><span class="line"><span class="string">        [10., 11., 12., 13., nan]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 累乘</span></span><br><span class="line"><span class="built_in">print</span>(torch.prod(data))  <span class="comment"># tensor(nan)</span></span><br><span class="line"><span class="built_in">print</span>(torch.prod(data, dim=<span class="number">0</span>))  <span class="comment"># tensor([ nan,  66., 168., 312.,  nan])</span></span><br><span class="line"><span class="built_in">print</span>(torch.prod(data, dim=<span class="number">1</span>))  <span class="comment"># tensor([   nan, 15120.,    nan])</span></span><br></pre></td></tr></tbody></table></figure><h3 id="var-var-mean-std-std-mean"><a href="#var-var-mean-std-std-mean" class="headerlink" title=".var/.var_mean/.std/.std_mean"></a>.var/.var_mean/.std/.std_mean</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.arange(<span class="number">1</span>, <span class="number">10</span>, dtype=torch.double).view(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[1., 2., 3.],</span></span><br><span class="line"><span class="string">        [4., 5., 6.],</span></span><br><span class="line"><span class="string">        [7., 8., 9.]], dtype=torch.float64)</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 样本方差</span></span><br><span class="line"><span class="built_in">print</span>(torch.var(data))  <span class="comment"># tensor(7.5000, dtype=torch.float64)</span></span><br><span class="line"><span class="comment"># 总体方差</span></span><br><span class="line"><span class="built_in">print</span>(torch.var(data, unbiased=<span class="literal">False</span>))  <span class="comment"># tensor(6.6667, dtype=torch.float64)</span></span><br><span class="line"><span class="comment"># 同时计算方差和平均值</span></span><br><span class="line"><span class="built_in">print</span>(torch.var_mean(data))  <span class="comment"># (tensor(7.5000, dtype=torch.float64), tensor(5., dtype=torch.float64))</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 样本标准差</span></span><br><span class="line"><span class="built_in">print</span>(torch.std(data))  <span class="comment"># tensor(2.7386, dtype=torch.float64)</span></span><br><span class="line"><span class="comment"># 总体标准差</span></span><br><span class="line"><span class="built_in">print</span>(torch.std(data, unbiased=<span class="literal">False</span>))  <span class="comment"># tensor(2.5820, dtype=torch.float64)</span></span><br><span class="line"><span class="comment"># 同时计算标准差和平均值</span></span><br><span class="line"><span class="built_in">print</span>(torch.std_mean(data))  <span class="comment"># (tensor(2.7386, dtype=torch.float64), tensor(5., dtype=torch.float64))</span></span><br></pre></td></tr></tbody></table></figure><p>总体方差：<script type="math/tex">\sigma^2 = \frac{1}{N}\sum_{i=1}^{N}(x_i - \mu)^2</script></p><p>样本方差：<script type="math/tex">s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2</script></p><p>总体标准差：<script type="math/tex">\sigma = \sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_i - \mu)^2}</script></p><p>样本标准差：<script type="math/tex">s = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2}</script></p><h3 id="norm"><a href="#norm" class="headerlink" title=".norm"></a>.norm</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line">data = torch.full((<span class="number">2</span>, <span class="number">2</span>), <span class="number">2.</span>)</span><br><span class="line"><span class="built_in">print</span>(data)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[2., 2.],</span></span><br><span class="line"><span class="string">        [2., 2.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 一范数</span></span><br><span class="line"><span class="built_in">print</span>(torch.norm(data, p=<span class="number">1</span>))  <span class="comment"># tensor(8.)</span></span><br><span class="line"><span class="comment"># 二范数</span></span><br><span class="line"><span class="built_in">print</span>(torch.norm(data))  <span class="comment"># tensor(4.)</span></span><br><span class="line"><span class="comment"># 三范数</span></span><br><span class="line"><span class="built_in">print</span>(torch.norm(data, p=<span class="number">3</span>))  <span class="comment"># tensor(3.1748)</span></span><br></pre></td></tr></tbody></table></figure><p>一范数：<script type="math/tex">||x||_1 = \sum_{i=1}^N|x_i|</script></p><p>二范数：<script type="math/tex">||x||_2 = \sqrt{\sum_{i=1}^Nx_i^2}</script></p><p>p范数：<script type="math/tex">||x||_p = (\sum_{i=1}^N|x_i|^p)^\frac{1}{p}</script></p><h3 id="dist"><a href="#dist" class="headerlink" title=".dist"></a>.dist</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">input</span> = torch.full((<span class="number">2</span>, <span class="number">2</span>), <span class="number">4.</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">input</span>)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[4., 4.],</span></span><br><span class="line"><span class="string">        [4., 4.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line">other = torch.full((<span class="number">2</span>, <span class="number">2</span>), <span class="number">2.</span>)</span><br><span class="line"><span class="built_in">print</span>(other)</span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">tensor([[2., 2.],</span></span><br><span class="line"><span class="string">        [2., 2.]])</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 一范数</span></span><br><span class="line"><span class="built_in">print</span>(torch.dist(<span class="built_in">input</span>, other, p=<span class="number">1</span>))  <span class="comment"># tensor(8.)</span></span><br><span class="line"><span class="comment"># 二范数</span></span><br><span class="line"><span class="built_in">print</span>(torch.dist(<span class="built_in">input</span>, other))  <span class="comment"># tensor(4.)</span></span><br><span class="line"><span class="comment"># 三范数</span></span><br><span class="line"><span class="built_in">print</span>(torch.dist(<span class="built_in">input</span>, other, p=<span class="number">3</span>))  <span class="comment"># tensor(3.1748)</span></span><br></pre></td></tr></tbody></table></figure><p><code>torch.dist()</code>返回<code>(input - other)</code>的<code>p</code>范数。</p><h3 id="any-all"><a href="#any-all" class="headerlink" title=".any/.all"></a>.any/.all</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">any</span>(torch.tensor([])))  <span class="comment"># tensor(False)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">any</span>(torch.tensor([<span class="literal">True</span>, <span class="literal">True</span>])))  <span class="comment"># tensor(True)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">any</span>(torch.tensor([<span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor(True)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">any</span>(torch.tensor([<span class="literal">False</span>, <span class="literal">False</span>])))  <span class="comment"># tensor(False)</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">all</span>(torch.tensor([])))  <span class="comment"># tensor(True)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">all</span>(torch.tensor([<span class="literal">True</span>, <span class="literal">True</span>])))  <span class="comment"># tensor(True)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">all</span>(torch.tensor([<span class="literal">True</span>, <span class="literal">False</span>])))  <span class="comment"># tensor(False)</span></span><br><span class="line"><span class="built_in">print</span>(torch.<span class="built_in">all</span>(torch.tensor([<span class="literal">False</span>, <span class="literal">False</span>])))  <span class="comment"># tensor(False)</span></span><br></pre></td></tr></tbody></table></figure><h2 id="序列化"><a href="#序列化" class="headerlink" title="序列化"></a>序列化</h2><h3 id="save"><a href="#save" class="headerlink" title=".save"></a>.save</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> io</span><br><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># Save to file</span></span><br><span class="line">x = torch.tensor([<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>])</span><br><span class="line">torch.save(x, <span class="string">'tensor.pt'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Save to io.BytesIO buffer</span></span><br><span class="line">buffer = io.BytesIO()</span><br><span class="line">torch.save(x, buffer)</span><br></pre></td></tr></tbody></table></figure><h3 id="load"><a href="#load" class="headerlink" title=".load"></a>.load</h3><figure class="highlight py"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> io</span><br><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"></span><br><span class="line"><span class="comment"># Load a module with 'ascii' encoding for unpickling</span></span><br><span class="line">torch.load(<span class="string">'tensors.pt'</span>, encoding=<span class="string">'ascii'</span>)</span><br><span class="line"><span class="comment"># Load all tensors onto the CPU</span></span><br><span class="line">torch.load(<span class="string">'tensors.pt'</span>, map_location=torch.device(<span class="string">'cpu'</span>))</span><br><span class="line"><span class="comment"># Map tensors from GPU 1 to GPU 0</span></span><br><span class="line">torch.load(<span class="string">'tensors.pt'</span>, map_location={<span class="string">'cuda:1'</span>: <span class="string">'cuda:0'</span>})</span><br><span class="line"></span><br><span class="line"><span class="comment"># Load from io.BytesIO buffer</span></span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">'tensor.pt'</span>, <span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line">    buffer = io.BytesIO(f.read())</span><br><span class="line">torch.load(buffer)</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="PyTorch" scheme="https://blog.wpz.homes/categories/PyTorch/"/>
    
    
    <category term="PyTorch" scheme="https://blog.wpz.homes/tags/PyTorch/"/>
    
  </entry>
  
  <entry>
    <title>汉诺塔</title>
    <link href="https://blog.wpz.homes/posts/3d0f623f/"/>
    <id>https://blog.wpz.homes/posts/3d0f623f/</id>
    <published>2019-06-29T06:08:10.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="起源"><a href="#起源" class="headerlink" title="起源"></a>起源</h2><p>汉诺塔（又称河内塔）问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子，在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定，在小圆盘上不能放大圆盘，在三根柱子之间一次只能移动一个圆盘。</p><h2 id="抽象为数学问题"><a href="#抽象为数学问题" class="headerlink" title="抽象为数学问题"></a>抽象为数学问题</h2><p>如下图所示，从左到右有A、B、C三根柱子，其中A柱子上面有从小叠到大的n个圆盘，现要求将A柱子上的圆盘移到C柱子上去，期间只有一个原则：一次只能移到一个盘子且大盘子不能在小盘子上面，求移动的步骤和移动的次数。</p><p><img src="https://lz94wpz.oss-cn-beijing.aliyuncs.com/Blog/20190529145715.jpg" alt=""></p><h2 id="调用方法的栈机制（先进后出）"><a href="#调用方法的栈机制（先进后出）" class="headerlink" title="调用方法的栈机制（先进后出）"></a>调用方法的栈机制（先进后出）</h2><p>从主线程开始调用方法（函数）进行不停的压栈和出栈操作，函数的调用就是将函数压如栈中，函数的结束就是函数出栈的过程，这样就保证了方法调用的顺序流，即当函数出现多层嵌套时，需要从外到内一层层把函数压入栈中，最后栈顶的函数先执行结束（最内层的函数先执行结束）后出栈，再倒数第二层的函数执行结束出栈，到最后，第一个进栈的函数调用结束后从栈中弹出回到主线程，并且结束。</p><h2 id="算法分析（递归算法）"><a href="#算法分析（递归算法）" class="headerlink" title="算法分析（递归算法）"></a>算法分析（递归算法）</h2><p>我们在利用计算机求汉诺塔问题时，必不可少的一步是对整个实现求解进行算法分析。到目前为止，求解汉诺塔问题最简单的算法还是通过递归来求，至于是什么是递归，递归实现的机制是什么，我们说的简单点就是自己是一个方法或者说是函数，但是在自己这个函数里有调用自己这个函数的语句，而这个调用怎么才能调用结束呢？这里还必须有一个结束点，或者具体的说是在调用到某一次后函数能返回一个确定的值，接着倒数第二个就能返回一个确定的值，一直到第一次调用的这个函数能返回一个确定的值。</p><p>实现这个算法可以简单分为三个步骤：</p><ol><li>把 n-1 个盘子由 A 移到 B；</li><li>把第 n 个盘子由 A 移到 C；</li><li>把 n-1 个盘子由 B 移到 C；</li></ol><p>从这里入手，在加上上面数学问题解法的分析，我们不难发现，移到的步数必定为奇数步：</p><ol><li>中间的一步是把最大的一个盘子由 A 移到 C 上去；</li><li>中间一步之上可以看成把 A 上 n-1 个盘子通过借助辅助塔（C塔）移到了 B 上，</li><li>中间一步之下可以看成把 B 上 n-1 个盘子通过借助辅助塔（A塔）移到了 C 上；</li></ol><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Scanner;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Hannota</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">hannota</span><span class="params">(<span class="type">int</span> n, <span class="type">char</span> A, <span class="type">char</span> B, <span class="type">char</span> C)</span> {</span><br><span class="line">        <span class="keyword">if</span> (n == <span class="number">1</span>) {</span><br><span class="line">            move(n, A, C);</span><br><span class="line">        } <span class="keyword">else</span> {</span><br><span class="line">            hannota(n - <span class="number">1</span>, A, C, B);</span><br><span class="line">            move(n, A, C);</span><br><span class="line">            hannota(n - <span class="number">1</span>, B, A, C);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">move</span><span class="params">(<span class="type">int</span> n, <span class="type">char</span> from, <span class="type">char</span> to)</span> {</span><br><span class="line">        System.out.printf(<span class="string">"将编号为%d的盘子从柱子%c移动到柱子%c\n"</span>, n, from, to);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line">        <span class="type">int</span> <span class="variable">n</span> <span class="operator">=</span> scanner.nextInt();</span><br><span class="line">        hannota(n, <span class="string">'A'</span>, <span class="string">'B'</span>, <span class="string">'C'</span>);</span><br><span class="line">        scanner.close();</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">hannota</span>(<span class="params">n, A, B, C</span>):</span><br><span class="line">    <span class="keyword">if</span> n == <span class="number">1</span>:</span><br><span class="line">        move(n, A, C)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        hannota(n - <span class="number">1</span>, A, C, B)</span><br><span class="line">        move(n, A, C)</span><br><span class="line">        hannota(n - <span class="number">1</span>, B, A, C)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">move</span>(<span class="params">n, f, to</span>):</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'将编号为%d的盘子从柱子%c移动到柱子%c'</span> % (n, f, to))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    n = <span class="built_in">input</span>()</span><br><span class="line">    hannota(<span class="built_in">int</span>(n), <span class="string">'A'</span>, <span class="string">'B'</span>, <span class="string">'C'</span>)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Hannota</span><span class="params">(n <span class="type">int</span>, A, B, C <span class="type">byte</span>)</span></span> {</span><br><span class="line">    <span class="keyword">if</span> n == <span class="number">1</span> {</span><br><span class="line">        Move(n, A, C) <span class="comment">// 只有一个盘子，直接从 A 移动到 C</span></span><br><span class="line">    } <span class="keyword">else</span> {</span><br><span class="line">        Hannota(n<span class="number">-1</span>, A, C, B) <span class="comment">// 先将 n-1 这个盘子从 A 借助 C 移动到 B</span></span><br><span class="line">        Move(n, A, C)         <span class="comment">// 经过上面的递归，n-1 这个盘子已经移动到了 B，现在将最后一个盘子 n 直接从 A 移动到 C</span></span><br><span class="line">        Hannota(n<span class="number">-1</span>, B, A, C) <span class="comment">// 最后将 n-1 这个盘子从 B 借助 A 移动到 C</span></span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Move</span><span class="params">(n <span class="type">int</span>, from, to <span class="type">byte</span>)</span></span> {</span><br><span class="line">    fmt.Printf(<span class="string">"将编号为%d的盘子从柱子%c移动到柱子%c\n"</span>, n, from, to)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    <span class="keyword">var</span> n <span class="type">int</span></span><br><span class="line">    fmt.Scanf(<span class="string">"%d"</span>, &amp;n)</span><br><span class="line">    Hannota(n, <span class="string">'A'</span>, <span class="string">'B'</span>, <span class="string">'C'</span>)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h2 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="https://dmego.me/2016/10/16/hanoi.html">汉诺塔的图解递归算法</a></p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="汉诺塔" scheme="https://blog.wpz.homes/tags/%E6%B1%89%E8%AF%BA%E5%A1%94/"/>
    
  </entry>
  
  <entry>
    <title>二叉树前序、中序、后序遍历</title>
    <link href="https://blog.wpz.homes/posts/6ab4a85b/"/>
    <id>https://blog.wpz.homes/posts/6ab4a85b/</id>
    <published>2019-06-29T02:15:28.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="二叉树"><a href="#二叉树" class="headerlink" title="二叉树"></a>二叉树</h2><p>二叉树是一种非常重要的数据结构，非常多其他数据结构都是基于二叉树的基础演变而来的。对于二叉树，有深度遍历和广度遍历，深度遍历有前序、中序以及后序三种遍历方法，广度遍历即我们寻常所说的层次遍历。由于树的定义本身就是递归定义，因此採用递归的方法去实现树的三种遍历不仅简单理解并且代码非常简洁，而对于广度遍历来说，须要其他数据结构的支撑。比方队列。所以。对于一段代码来说，可读性有时候要比代码本身的效率要重要的多。</p><h3 id="遍历方式"><a href="#遍历方式" class="headerlink" title="遍历方式"></a>遍历方式</h3><div class="note danger">    <p>        前序遍历：根结点 ---&gt; 左子树 ---&gt; 右子树<br>        中序遍历：左子树 ---&gt; 根结点 ---&gt; 右子树<br>        后序遍历：左子树 ---&gt; 右子树 ---&gt; 根结点    </p></div><p><img src="https://lz94wpz.oss-cn-beijing.aliyuncs.com/Blog/20190529110938.png" alt=""></p><center>    前序遍历：1  2  4  5  7  8  3  6<br>    中序遍历：4  2  7  5  8  1  3  6<br>    后序遍历：4  7  8  5  2  6  3  1</center><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BinaryTree</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> data;</span><br><span class="line">    <span class="keyword">public</span> BinaryTree left;</span><br><span class="line">    <span class="keyword">public</span> BinaryTree right;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">BinaryTree</span><span class="params">(<span class="type">int</span> data)</span> {</span><br><span class="line">        <span class="built_in">this</span>.data = data;</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">PreorderTraversal</span><span class="params">(BinaryTree node)</span> { <span class="comment">// 先序遍历</span></span><br><span class="line">        <span class="keyword">if</span> (node == <span class="literal">null</span>) {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line">        System.out.print(node.data);</span><br><span class="line">        PreorderTraversal(node.left);</span><br><span class="line">        PreorderTraversal(node.right);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">InorderTraversal</span><span class="params">(BinaryTree node)</span> { <span class="comment">// 中序遍历</span></span><br><span class="line">        <span class="keyword">if</span> (node == <span class="literal">null</span>) {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line">        InorderTraversal(node.left);</span><br><span class="line">        System.out.print(node.data);</span><br><span class="line">        InorderTraversal(node.right);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">PostorderTraversal</span><span class="params">(BinaryTree node)</span> { <span class="comment">// 后序遍历</span></span><br><span class="line">        <span class="keyword">if</span> (node == <span class="literal">null</span>) {</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        }</span><br><span class="line">        PostorderTraversal(node.left);</span><br><span class="line">        PostorderTraversal(node.right);</span><br><span class="line">        System.out.print(node.data);</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">root</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">1</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">2</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">3</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node4</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">4</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node5</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">5</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node6</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">6</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node7</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">7</span>);</span><br><span class="line">        <span class="type">BinaryTree</span> <span class="variable">node8</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BinaryTree</span>(<span class="number">8</span>);</span><br><span class="line">        root.left = node2;</span><br><span class="line">        root.right = node3;</span><br><span class="line">        node2.left = node4;</span><br><span class="line">        node2.right = node5;</span><br><span class="line">        node3.right = node6;</span><br><span class="line">        node5.left = node7;</span><br><span class="line">        node5.right = node8;</span><br><span class="line"></span><br><span class="line">        PreorderTraversal(root); <span class="comment">// 12457836</span></span><br><span class="line">        System.out.println();</span><br><span class="line">        InorderTraversal(root); <span class="comment">// 42758136</span></span><br><span class="line">        System.out.println();</span><br><span class="line">        PostorderTraversal(root); <span class="comment">// 47852631</span></span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">BinaryTree</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, data, left=<span class="literal">None</span>, right=<span class="literal">None</span></span>):</span><br><span class="line">        self.data = data</span><br><span class="line">        self.left = left</span><br><span class="line">        self.right = right</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">PreorderTraversal</span>(<span class="params">node</span>):  <span class="comment"># 先序遍历</span></span><br><span class="line">    <span class="keyword">if</span> node <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    <span class="built_in">print</span>(node.data, end=<span class="string">''</span>)</span><br><span class="line">    PreorderTraversal(node.left)</span><br><span class="line">    PreorderTraversal(node.right)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">InorderTraversal</span>(<span class="params">node</span>):  <span class="comment"># 中序遍历</span></span><br><span class="line">    <span class="keyword">if</span> node <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    InorderTraversal(node.left)</span><br><span class="line">    <span class="built_in">print</span>(node.data, end=<span class="string">''</span>)</span><br><span class="line">    InorderTraversal(node.right)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">PostorderTraversal</span>(<span class="params">node</span>):  <span class="comment"># 后序遍历</span></span><br><span class="line">    <span class="keyword">if</span> node <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    PostorderTraversal(node.left)</span><br><span class="line">    PostorderTraversal(node.right)</span><br><span class="line">    <span class="built_in">print</span>(node.data, end=<span class="string">''</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    root = BinaryTree(<span class="number">1</span>)</span><br><span class="line">    node2 = BinaryTree(<span class="number">2</span>)</span><br><span class="line">    node3 = BinaryTree(<span class="number">3</span>)</span><br><span class="line">    node4 = BinaryTree(<span class="number">4</span>)</span><br><span class="line">    node5 = BinaryTree(<span class="number">5</span>)</span><br><span class="line">    node6 = BinaryTree(<span class="number">6</span>)</span><br><span class="line">    node7 = BinaryTree(<span class="number">7</span>)</span><br><span class="line">    node8 = BinaryTree(<span class="number">8</span>)</span><br><span class="line">    root.left = node2</span><br><span class="line">    root.right = node3</span><br><span class="line">    node2.left = node4</span><br><span class="line">    node2.right = node5</span><br><span class="line">    node3.right = node6</span><br><span class="line">    node5.left = node7</span><br><span class="line">    node5.right = node8</span><br><span class="line"></span><br><span class="line">    PreorderTraversal(root)  <span class="comment"># 12457836</span></span><br><span class="line">    <span class="built_in">print</span>()</span><br><span class="line">    InorderTraversal(root)  <span class="comment"># 42758136</span></span><br><span class="line">    <span class="built_in">print</span>()</span><br><span class="line">    PostorderTraversal(root)  <span class="comment"># 47852631</span></span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> BinaryTree <span class="keyword">struct</span> {</span><br><span class="line">    data  <span class="type">int</span></span><br><span class="line">    left  *BinaryTree</span><br><span class="line">    right *BinaryTree</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">PreorderTraversal</span><span class="params">(node *BinaryTree)</span></span> { <span class="comment">// 先序遍历</span></span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> {</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    }</span><br><span class="line">    fmt.Print(node.data)</span><br><span class="line">    PreorderTraversal(node.left)</span><br><span class="line">    PreorderTraversal(node.right)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">InorderTraversal</span><span class="params">(node *BinaryTree)</span></span> { <span class="comment">// 中序遍历</span></span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> {</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    }</span><br><span class="line">    InorderTraversal(node.left)</span><br><span class="line">    fmt.Print(node.data)</span><br><span class="line">    InorderTraversal(node.right)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">PostorderTraversal</span><span class="params">(node *BinaryTree)</span></span> { <span class="comment">// 后序遍历</span></span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> {</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    }</span><br><span class="line">    PostorderTraversal(node.left)</span><br><span class="line">    PostorderTraversal(node.right)</span><br><span class="line">    fmt.Print(node.data)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    root := BinaryTree{data: <span class="number">1</span>}</span><br><span class="line">    node2 := BinaryTree{data: <span class="number">2</span>}</span><br><span class="line">    node3 := BinaryTree{data: <span class="number">3</span>}</span><br><span class="line">    node4 := BinaryTree{data: <span class="number">4</span>}</span><br><span class="line">    node5 := BinaryTree{data: <span class="number">5</span>}</span><br><span class="line">    node6 := BinaryTree{data: <span class="number">6</span>}</span><br><span class="line">    node7 := BinaryTree{data: <span class="number">7</span>}</span><br><span class="line">    node8 := BinaryTree{data: <span class="number">8</span>}</span><br><span class="line">    root.left = &amp;node2</span><br><span class="line">    root.right = &amp;node3</span><br><span class="line">    node2.left = &amp;node4</span><br><span class="line">    node2.right = &amp;node5</span><br><span class="line">    node3.right = &amp;node6</span><br><span class="line">    node5.left = &amp;node7</span><br><span class="line">    node5.right = &amp;node8</span><br><span class="line"></span><br><span class="line">    PreorderTraversal(&amp;root) <span class="comment">// 12457836</span></span><br><span class="line">    fmt.Println()</span><br><span class="line">    InorderTraversal(&amp;root) <span class="comment">// 42758136</span></span><br><span class="line">    fmt.Println()</span><br><span class="line">    PostorderTraversal(&amp;root) <span class="comment">// 47852631</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="二叉树" scheme="https://blog.wpz.homes/tags/%E4%BA%8C%E5%8F%89%E6%A0%91/"/>
    
  </entry>
  
  <entry>
    <title>堆排序</title>
    <link href="https://blog.wpz.homes/posts/c2a5fdc5/"/>
    <id>https://blog.wpz.homes/posts/c2a5fdc5/</id>
    <published>2019-05-29T01:08:29.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="堆排序（Heap-Sort）"><a href="#堆排序（Heap-Sort）" class="headerlink" title="堆排序（Heap Sort）"></a>堆排序（Heap Sort）</h2><p>堆排序（Heapsort）是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构，并同时满足堆积的性质：即子结点的键值或索引总是小于（或者大于）它的父节点。</p><h3 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h3><ul><li>将初始待排序关键字序列(R<sub>1</sub>,R<sub>2</sub>….R<sub>n</sub>)构建成大顶堆，此堆为初始的无序区；</li><li>将堆顶元素R[1]与最后一个元素R[n]交换，此时得到新的无序区(R<sub>1</sub>,R<sub>2</sub>….R<sub>n-1</sub>)和新的有序区(R<sub>n</sub>),且满足R[1,2…n-1]&lt;=R[n]；</li><li>由于交换后新的堆顶R[1]可能违反堆的性质，因此需要对当前无序区(R<sub>1</sub>,R<sub>2</sub>….R<sub>n-1</sub>)调整为新堆，然后再次将R[1]与无序区最后一个元素R[n-1]交换，得到新的无序区(R<sub>1</sub>,R<sub>2</sub>….R<sub>n-2</sub>)和新的有序区(R<sub>n-1</sub>,R<sub>n</sub>)。不断重复此过程直到有序区的元素个数为n-1，则整个排序过程完成。</li></ul><h3 id="算法分析"><a href="#算法分析" class="headerlink" title="算法分析"></a>算法分析</h3><p>最佳情况：T(n) = O(nlogn)<br>最差情况：T(n) = O(nlogn)<br>平均情况：T(n) = O(nlogn)</p><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HeapSort</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">maxHeapDown</span><span class="params">(<span class="type">int</span>[] arr, <span class="type">int</span> current, <span class="type">int</span> size)</span> {</span><br><span class="line">        <span class="type">int</span> <span class="variable">max</span> <span class="operator">=</span> current;</span><br><span class="line">        <span class="type">int</span> <span class="variable">left</span> <span class="operator">=</span> current * <span class="number">2</span> + <span class="number">1</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">right</span> <span class="operator">=</span> left + <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">if</span> (left &lt;= size &amp;&amp; arr[max] &lt; arr[left]) {</span><br><span class="line">            max = left;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (right &lt;= size &amp;&amp; arr[max] &lt; arr[right]) {</span><br><span class="line">            max = right;</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> (max != current) {</span><br><span class="line">            <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> arr[max];</span><br><span class="line">            arr[max] = arr[current];</span><br><span class="line">            arr[current] = temp;</span><br><span class="line">            maxHeapDown(arr, max, size);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">heapSortAsc</span><span class="params">(<span class="type">int</span>[] arr, <span class="type">int</span> size)</span> {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> size / <span class="number">2</span> - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) {</span><br><span class="line">            maxHeapDown(arr, i, size - <span class="number">1</span>);</span><br><span class="line">        }</span><br><span class="line">        System.out.println(Arrays.toString(arr));</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> size - <span class="number">1</span>; i &gt; <span class="number">0</span>; i--) {</span><br><span class="line">            <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> arr[<span class="number">0</span>];</span><br><span class="line">            arr[<span class="number">0</span>] = arr[i];</span><br><span class="line">            arr[i] = temp;</span><br><span class="line">            maxHeapDown(arr, <span class="number">0</span>, i - <span class="number">1</span>);</span><br><span class="line">            System.out.println(Arrays.toString(arr));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">int</span>[] arr = { <span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span> };</span><br><span class="line">        System.out.printf(<span class="string">"原始数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">        heapSortAsc(arr, arr.length);</span><br><span class="line">        System.out.printf(<span class="string">"排序后数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">max_heap_down</span>(<span class="params">arr, current, size</span>):</span><br><span class="line">    <span class="built_in">max</span> = current</span><br><span class="line">    left = current * <span class="number">2</span> + <span class="number">1</span></span><br><span class="line">    right = left + <span class="number">1</span></span><br><span class="line">    <span class="keyword">if</span> left &lt;= size <span class="keyword">and</span> arr[<span class="built_in">max</span>] &lt; arr[left]:</span><br><span class="line">        <span class="built_in">max</span> = left</span><br><span class="line">    <span class="keyword">if</span> right &lt;= size <span class="keyword">and</span> arr[<span class="built_in">max</span>] &lt; arr[right]:</span><br><span class="line">        <span class="built_in">max</span> = right</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">max</span> != current:</span><br><span class="line">        arr[<span class="built_in">max</span>], arr[current] = arr[current], arr[<span class="built_in">max</span>]</span><br><span class="line">        max_heap_down(arr, <span class="built_in">max</span>, size)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">heap_sort_asc</span>(<span class="params">arr, size</span>):</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">int</span>(size / <span class="number">2</span> - <span class="number">1</span>), -<span class="number">1</span>, -<span class="number">1</span>):</span><br><span class="line">        max_heap_down(arr, i, size - <span class="number">1</span>)</span><br><span class="line">    <span class="built_in">print</span>(arr)</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(size - <span class="number">1</span>, <span class="number">0</span>, -<span class="number">1</span>):</span><br><span class="line">        arr[<span class="number">0</span>], arr[i] = arr[i], arr[<span class="number">0</span>]</span><br><span class="line">        max_heap_down(arr, <span class="number">0</span>, i - <span class="number">1</span>)</span><br><span class="line">        <span class="built_in">print</span>(arr)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    arr = [<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'原始数组：'</span>, arr)</span><br><span class="line">    heap_sort_asc(arr, <span class="built_in">len</span>(arr))</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'排序后数组：'</span>, arr)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">MaxHeapDown</span><span class="params">(arr []<span class="type">int</span>, current, size <span class="type">int</span>)</span></span> { <span class="comment">// 最大堆</span></span><br><span class="line">    max := current                            <span class="comment">// 假设最大值的索引就是当前的根节点索引</span></span><br><span class="line">    left := current*<span class="number">2</span> + <span class="number">1</span>                     <span class="comment">// 左节点</span></span><br><span class="line">    right := left + <span class="number">1</span>                         <span class="comment">// 右节点</span></span><br><span class="line">    <span class="keyword">if</span> left &lt;= size &amp;&amp; arr[max] &lt; arr[left] { <span class="comment">// 左子节点大于父节点</span></span><br><span class="line">        max = left</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">if</span> right &lt;= size &amp;&amp; arr[max] &lt; arr[left+<span class="number">1</span>] { <span class="comment">// 右子节点大于父节点</span></span><br><span class="line">        max = right</span><br><span class="line">    }</span><br><span class="line">    <span class="keyword">if</span> max != current { <span class="comment">// 经过上面两步 if 判断，找出两个子节点中的最大的并且大于父节点的子节点</span></span><br><span class="line">        arr[max], arr[current] = arr[current], arr[max]</span><br><span class="line">        MaxHeapDown(arr, max, size)</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">HeapSortAsc</span><span class="params">(arr []<span class="type">int</span>, size <span class="type">int</span>)</span></span> {</span><br><span class="line">    <span class="keyword">for</span> i := size/<span class="number">2</span> - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i-- { <span class="comment">// 遍历完得到的数组实际上是一个大根堆</span></span><br><span class="line">        MaxHeapDown(arr, i, size<span class="number">-1</span>)</span><br><span class="line">    }</span><br><span class="line">    fmt.Println(arr)</span><br><span class="line">    <span class="keyword">for</span> i := size - <span class="number">1</span>; i &gt; <span class="number">0</span>; i-- { <span class="comment">// 从最后一个元素开始对序列进行调整，不断的缩小调整的范围直到第一个元素</span></span><br><span class="line">        arr[<span class="number">0</span>], arr[i] = arr[i], arr[<span class="number">0</span>] <span class="comment">// 大根堆，第一个数最大，将其和最后一个数交换，此时最大值在数组的最后面</span></span><br><span class="line">        MaxHeapDown(arr, <span class="number">0</span>, i<span class="number">-1</span>)        <span class="comment">// 经过上面的交换，a[0...i-1]，可能已经不是大根堆，所以需要重新排序成大根堆</span></span><br><span class="line">        fmt.Println(arr)</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := []<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    HeapSortAsc(arr, <span class="built_in">len</span>(arr))</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="排序" scheme="https://blog.wpz.homes/tags/%E6%8E%92%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>希尔排序</title>
    <link href="https://blog.wpz.homes/posts/1ac49179/"/>
    <id>https://blog.wpz.homes/posts/1ac49179/</id>
    <published>2019-05-29T00:55:37.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="希尔排序（Shell-Sort）"><a href="#希尔排序（Shell-Sort）" class="headerlink" title="希尔排序（Shell Sort）"></a>希尔排序（Shell Sort）</h2><p>希尔排序是希尔（Donald Shell）于1959年提出的一种排序算法。希尔排序也是一种插入排序，它是简单插入排序经过改进之后的一个更高效的版本，也称为缩小增量排序，同时该算法是冲破O(n<sup>2</sup>）的第一批算法之一。它与插入排序的不同之处在于，它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。<br>希尔排序是把记录按下表的一定增量分组，对每组使用直接插入排序算法排序；随着增量逐渐减少，每组包含的关键词越来越多，当增量减至1时，整个文件恰被分成一组，算法便终止。</p><h3 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h3><p>我们来看下希尔排序的基本步骤，在此我们选择增量gap=length/2，缩小增量继续以gap = gap/2的方式，这种增量选择我们可以用一个序列来表示，{n/2,(n/2)/2…1}，称为增量序列。希尔排序的增量序列的选择与证明是个数学难题，我们选择的这个增量序列是比较常用的，也是希尔建议的增量，称为希尔增量，但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。<br>先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序，具体算法描述：<br>选择一个增量序列t1，t2，…，tk，其中ti&gt;tj，tk=1；<br>按增量序列个数k，对序列进行k 趟排序；<br>每趟排序，根据对应的增量ti，将待排序列分割成若干长度为m 的子序列，分别对各子表进行直接插入排序。仅增量因子为1 时，整个序列作为一个表来处理，表长度即为整个序列的长度。</p><h3 id="算法分析"><a href="#算法分析" class="headerlink" title="算法分析"></a>算法分析</h3><p>最佳情况：T(n) = O(nlog2 n)<br>最坏情况：T(n) = O(nlog2 n)<br>平均情况：T(n) = O(nlog2 n)</p><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ShellSort</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">shellSort</span><span class="params">(<span class="type">int</span>[] arr)</span> {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">step</span> <span class="operator">=</span> arr.length / <span class="number">2</span>; step &gt; <span class="number">0</span>; step /= <span class="number">2</span>) {</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> step; i &lt; arr.length; i++) {</span><br><span class="line">                <span class="keyword">if</span> (arr[i] &lt; arr[i - step]) {</span><br><span class="line">                    <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> arr[i];</span><br><span class="line">                    <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> i;</span><br><span class="line">                    <span class="keyword">while</span> (index &gt;= step &amp;&amp; temp &lt; arr[index - step]) {</span><br><span class="line">                        arr[index] = arr[index - step];</span><br><span class="line">                        index -= step;</span><br><span class="line">                    }</span><br><span class="line">                    arr[index] = temp;</span><br><span class="line">                }</span><br><span class="line">                System.out.println(Arrays.toString(arr));</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">int</span>[] arr = { <span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span> };</span><br><span class="line">        System.out.printf(<span class="string">"原始数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">        shellSort(arr);</span><br><span class="line">        System.out.printf(<span class="string">"排序后数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">shell_sort</span>(<span class="params">arr</span>):</span><br><span class="line">    step = <span class="built_in">int</span>(<span class="built_in">len</span>(arr) / <span class="number">2</span>)</span><br><span class="line">    <span class="keyword">while</span> step &gt; <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(step, <span class="built_in">len</span>(arr)):</span><br><span class="line">            <span class="keyword">if</span> arr[i] &lt; arr[i - step]:</span><br><span class="line">                temp = arr[i]</span><br><span class="line">                index = i</span><br><span class="line">                <span class="keyword">while</span> index &gt;= step <span class="keyword">and</span> temp &lt; arr[index - step]:</span><br><span class="line">                    arr[index] = arr[index - step]</span><br><span class="line">                    index -= step</span><br><span class="line">                arr[index] = temp</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">'分成%d组第%2d次排序第%d组后数组为：%s'</span> % (step, i / step, (i % step) + <span class="number">1</span>, arr))</span><br><span class="line">        step = <span class="built_in">int</span>(step / <span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    arr = [<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'原始数组：'</span>, arr)</span><br><span class="line">    shell_sort(arr)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'排序后数组：'</span>, arr)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ShellSort</span><span class="params">(arr *[15]<span class="type">int</span>)</span></span> {</span><br><span class="line">    <span class="keyword">for</span> step := <span class="built_in">len</span>(arr) / <span class="number">2</span>; step &gt; <span class="number">0</span>; step /= <span class="number">2</span> {</span><br><span class="line">        <span class="keyword">for</span> i := step; i &lt; <span class="built_in">len</span>(arr); i++ {</span><br><span class="line">            <span class="keyword">if</span> arr[i] &lt; arr[i-step] {</span><br><span class="line">                temp := arr[i] <span class="comment">// 记录要插入的数</span></span><br><span class="line">                index := i     <span class="comment">// 记录要插入的位置</span></span><br><span class="line">                <span class="keyword">for</span> ; index &gt;= step &amp;&amp; temp &lt; arr[index-step]; index -= step {</span><br><span class="line">                    arr[index] = arr[index-step]</span><br><span class="line">                }</span><br><span class="line">                arr[index] = temp</span><br><span class="line">            }</span><br><span class="line">            fmt.Printf(<span class="string">"分成%d组第%2d次排序第%d组后数组为：%v\n"</span>, step, i/step, (i%step)+<span class="number">1</span>, *arr)</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := [<span class="number">15</span>]<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    ShellSort(&amp;arr)</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="排序" scheme="https://blog.wpz.homes/tags/%E6%8E%92%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>快速排序</title>
    <link href="https://blog.wpz.homes/posts/ff8068c0/"/>
    <id>https://blog.wpz.homes/posts/ff8068c0/</id>
    <published>2019-05-28T07:20:48.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="快速排序（Quick-Sort）"><a href="#快速排序（Quick-Sort）" class="headerlink" title="快速排序（Quick Sort）"></a>快速排序（Quick Sort）</h2><p>快速排序的基本思想：通过一趟排序将待排记录分隔成独立的两部分，其中一部分记录的关键字均比另一部分的关键字小，则可分别对这两部分记录继续进行排序，以达到整个序列有序。</p><h3 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h3><p>快速排序使用分治法来把一个串（list）分为两个子串（sub-lists）。具体算法描述如下：</p><ul><li>从数列中挑出一个元素，称为“基准”（pivot）；</li><li>重新排序数列，所有比基准值小的元素都放在基准前面，所有比基准值大的元素都放在基准后面，相同的元素可以到任意一边。在这个分区退出之后，该基准就处于数列的中间位置。这个称为分区（partition）操作；</li><li>递归（recursive）地把小于基准值元素的子数列和大于基准值元素的子数列排序。</li></ul><h3 id="算法分析"><a href="#算法分析" class="headerlink" title="算法分析"></a>算法分析</h3><p>最佳情况：T(n) = O(n log n)<br>最差情况：T(n) = O(n<sup>2</sup>)<br>平均情况：T(n) = O(n log n)　</p><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">QuickSort</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">quickSort</span><span class="params">(<span class="type">int</span>[] arr, <span class="type">int</span> l, <span class="type">int</span> r)</span> {</span><br><span class="line">        <span class="keyword">if</span> (l &lt; r) {</span><br><span class="line">            <span class="type">int</span> <span class="variable">left</span> <span class="operator">=</span> l, right = r;</span><br><span class="line">            <span class="type">int</span> <span class="variable">base</span> <span class="operator">=</span> arr[left];</span><br><span class="line">            <span class="keyword">while</span> (left &lt; right) {</span><br><span class="line">                <span class="keyword">while</span> (left &lt; right &amp;&amp; base &lt;= arr[right]) {</span><br><span class="line">                    right--;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">while</span> (left &lt; right &amp;&amp; base &gt;= arr[left]) {</span><br><span class="line">                    left++;</span><br><span class="line">                }</span><br><span class="line">                <span class="keyword">if</span> (left &lt; right) {</span><br><span class="line">                    <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> arr[left];</span><br><span class="line">                    arr[left] = arr[right];</span><br><span class="line">                    arr[right] = temp;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (l != left) {</span><br><span class="line">                <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> arr[l];</span><br><span class="line">                arr[l] = arr[left];</span><br><span class="line">                arr[left] = temp;</span><br><span class="line">            }</span><br><span class="line">            System.out.printf(<span class="string">"以%2d为基准数排序后数组为：%s\n"</span>, base, Arrays.toString(arr));</span><br><span class="line">            quickSort(arr, l, left - <span class="number">1</span>);</span><br><span class="line">            quickSort(arr, right + <span class="number">1</span>, r);</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">int</span>[] arr = { <span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span> };</span><br><span class="line">        System.out.printf(<span class="string">"原始数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">        quickSort(arr, <span class="number">0</span>, arr.length - <span class="number">1</span>);</span><br><span class="line">        System.out.printf(<span class="string">"排序后数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">quick_sort</span>(<span class="params">arr, l, r</span>):</span><br><span class="line">    <span class="keyword">if</span> l &lt; r:</span><br><span class="line">        left, right = l, r</span><br><span class="line">        base = arr[left]</span><br><span class="line">        <span class="keyword">while</span> left &lt; right:</span><br><span class="line">            <span class="keyword">while</span> left &lt; right <span class="keyword">and</span> base &lt;= arr[right]:</span><br><span class="line">                right -= <span class="number">1</span></span><br><span class="line">            <span class="keyword">while</span> left &lt; right <span class="keyword">and</span> base &gt;= arr[left]:</span><br><span class="line">                left += <span class="number">1</span></span><br><span class="line">            <span class="keyword">if</span> left &lt; right:</span><br><span class="line">                arr[left], arr[right] = arr[right], arr[left]</span><br><span class="line">        <span class="keyword">if</span> l != left:</span><br><span class="line">            arr[l], arr[left] = arr[left], arr[l]</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">'以%2d为基准数排序后数组为：%s'</span> % (base, arr))</span><br><span class="line">        quick_sort(arr, l, left - <span class="number">1</span>)</span><br><span class="line">        quick_sort(arr, right + <span class="number">1</span>, r)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    arr = [<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'原始数组：'</span>, arr)</span><br><span class="line">    quick_sort(arr, <span class="number">0</span>, <span class="built_in">len</span>(arr) - <span class="number">1</span>)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'排序后数组：'</span>, arr)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">QuickSort</span><span class="params">(arr *[15]<span class="type">int</span>, l, r <span class="type">int</span>)</span></span> {</span><br><span class="line">    <span class="keyword">if</span> l &lt; r {</span><br><span class="line">        left, right := l, r</span><br><span class="line">        base := arr[left] <span class="comment">// 以最左边的数作为基准数</span></span><br><span class="line">        <span class="keyword">for</span> left &lt; right {</span><br><span class="line">            <span class="keyword">for</span> left &lt; right &amp;&amp; base &lt;= arr[right] { <span class="comment">// 先从右往左找大于基准数的位置</span></span><br><span class="line">                right--</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">for</span> left &lt; right &amp;&amp; base &gt;= arr[left] { <span class="comment">// 再从左往右找小于基准数的位置</span></span><br><span class="line">                left++</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> left &lt; right {</span><br><span class="line">                arr[left], arr[right] = arr[right], arr[left] <span class="comment">// 交换找到的大于和小于基准数的两个数的位置</span></span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> l != left {</span><br><span class="line">            arr[l], arr[left] = arr[left], arr[l] <span class="comment">// 交换基准数和(left=right)的位置</span></span><br><span class="line">        }</span><br><span class="line">        fmt.Printf(<span class="string">"以%2d为基准数排序后数组为：%v\n"</span>, base, *arr)</span><br><span class="line">        QuickSort(arr, l, left<span class="number">-1</span>)  <span class="comment">// 递归左边</span></span><br><span class="line">        QuickSort(arr, right+<span class="number">1</span>, r) <span class="comment">// 递归右边</span></span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := [<span class="number">15</span>]<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    QuickSort(&amp;arr, <span class="number">0</span>, <span class="built_in">len</span>(arr)<span class="number">-1</span>)</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="排序" scheme="https://blog.wpz.homes/tags/%E6%8E%92%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>插入排序</title>
    <link href="https://blog.wpz.homes/posts/96555fb2/"/>
    <id>https://blog.wpz.homes/posts/96555fb2/</id>
    <published>2019-05-28T06:45:09.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="插入排序（Insertion-Sort）"><a href="#插入排序（Insertion-Sort）" class="headerlink" title="插入排序（Insertion Sort）"></a>插入排序（Insertion Sort）</h2><p>插入排序的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列，对未排序数据，在已排序序列中从后向前扫描，找到相应位置并插入。插入排序在实现上，通常采用<code>in-place</code>排序（即只需用到<code>O(1)</code>的额外空间的排序），因而在从后向前扫描过程中，需要反复把已排序元素逐步向后挪位，为最新元素提供插入空间。</p><h3 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h3><ul><li>从第一个元素开始，该元素可以认为已经被排序；</li><li>取出下一个元素（即要插入的元素），在已经排序的元素序列中从后向前扫描；</li><li>如果已排序的元素大于要插入的元素，将该元素向后移动一位；</li><li>重复步骤3，直到找到已排序的元素小于或者等于要插入的元素的位置；</li><li>将要插入的元素插入到该位置后；</li><li>重复步骤2~5。</li></ul><h3 id="动图演示"><a href="#动图演示" class="headerlink" title="动图演示"></a>动图演示</h3><p><img src="https://lz94wpz.oss-cn-beijing.aliyuncs.com/YoudaoNote/20190419142550.gif" alt=""></p><h3 id="算法分析"><a href="#算法分析" class="headerlink" title="算法分析"></a>算法分析</h3><p>最佳情况：T(n) = O(n)<br>最坏情况：T(n) = O(n<sup>2</sup>)<br>平均情况：T(n) = O(n<sup>2</sup>)</p><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InsertionSort</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">insertionSort</span><span class="params">(<span class="type">int</span>[] arr)</span> {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt; arr.length; i++) {</span><br><span class="line">            <span class="keyword">if</span> (arr[i] &lt; arr[i - <span class="number">1</span>]) {</span><br><span class="line">                <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> arr[i];</span><br><span class="line">                <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> i;</span><br><span class="line">                <span class="keyword">while</span> (index &gt; <span class="number">0</span> &amp;&amp; temp &lt; arr[index - <span class="number">1</span>]) {</span><br><span class="line">                    arr[index] = arr[index - <span class="number">1</span>];</span><br><span class="line">                    index--;</span><br><span class="line">                }</span><br><span class="line">                arr[index] = temp;</span><br><span class="line">            }</span><br><span class="line">            System.out.printf(<span class="string">"排序第%2d次后数组为：%s\n"</span>, i + <span class="number">1</span>, Arrays.toString(arr));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">int</span>[] arr = { <span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span> };</span><br><span class="line">        System.out.printf(<span class="string">"原始数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">        insertionSort(arr);</span><br><span class="line">        System.out.printf(<span class="string">"排序后数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Ptyhon"><a href="#Ptyhon" class="headerlink" title="Ptyhon"></a>Ptyhon</h3><figure class="highlight py"><figcaption><span>Ptyhon 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">insertion_sort</span>(<span class="params">arr</span>):</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="built_in">len</span>(arr)):</span><br><span class="line">        <span class="keyword">if</span> arr[i] &lt; arr[i - <span class="number">1</span>]:</span><br><span class="line">            temp = arr[i]</span><br><span class="line">            index = i</span><br><span class="line">            <span class="keyword">while</span> index &gt; <span class="number">0</span> <span class="keyword">and</span> temp &lt; arr[index - <span class="number">1</span>]:</span><br><span class="line">                arr[index] = arr[index - <span class="number">1</span>]</span><br><span class="line">                index -= <span class="number">1</span></span><br><span class="line">            arr[index] = temp</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">'排序第%2d次后数组为：%s'</span> % (i + <span class="number">1</span>, arr))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    arr = [<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'原始数组：'</span>, arr)</span><br><span class="line">    insertion_sort(arr)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'排序后数组：'</span>, arr)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">InsertionSort</span><span class="params">(arr *[15]<span class="type">int</span>)</span></span> {</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="built_in">len</span>(arr); i++ {</span><br><span class="line">        <span class="keyword">if</span> arr[i] &lt; arr[i<span class="number">-1</span>] {</span><br><span class="line">            temp := arr[i] <span class="comment">// 记录要插入的数</span></span><br><span class="line">            index := i     <span class="comment">// 记录要插入的位置</span></span><br><span class="line">            <span class="keyword">for</span> ; index &gt; <span class="number">0</span> &amp;&amp; temp &lt; arr[index<span class="number">-1</span>]; index-- {</span><br><span class="line">                arr[index] = arr[index<span class="number">-1</span>]</span><br><span class="line">            }</span><br><span class="line">            arr[index] = temp</span><br><span class="line">        }</span><br><span class="line">        fmt.Printf(<span class="string">"排序第%2d次后数组为：%v\n"</span>, i, *arr)</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := [<span class="number">15</span>]<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    InsertionSort(&amp;arr)</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="排序" scheme="https://blog.wpz.homes/tags/%E6%8E%92%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>选择排序</title>
    <link href="https://blog.wpz.homes/posts/43d00a99/"/>
    <id>https://blog.wpz.homes/posts/43d00a99/</id>
    <published>2019-05-28T03:03:38.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="选择排序（Selection-Sort）"><a href="#选择排序（Selection-Sort）" class="headerlink" title="选择排序（Selection Sort）"></a>选择排序（Selection Sort）</h2><p>选择排序是一种简单直观的排序算法。它的工作原理：首先在未排序序列中找到最小（大）元素，存放到排序序列的起始位置，然后，再从剩余未排序元素中继续寻找最小（大）元素，然后放到已排序序列的末尾。以此类推，直到所有元素均排序完毕。</p><p>选择排序是表现最稳定的排序算法之一，因为无论什么数据进去都是<code>O(n<sup>2</sup>)</code>的时间复杂度，所以用到它的时候，数据规模越小越好。选择排序还有一个好处就是不占用额外的内存空间。</p><h3 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h3><ul><li>初始状态：无序区为<code>R[1..n]</code>，有序区为空；</li><li>第<code>i</code>趟排序<code>(i=1, 2 , 3, …, n-1)</code>开始时，当前有序区和无序区分别为<code>R[1..i-1]</code>和<code>R[i..n]</code>。该趟排序从当前无序区中选出最小元素（按升序排序），将它与无序区的第<code>1</code>个记录交换，交换结束后，当前有序区和无序区分别为<code>R[1..i]</code>和<code>R[i+1..n]</code>；</li><li>重复步骤2，当<code>n-1</code>趟结束后，数组有序化了。</li></ul><h3 id="动图演示"><a href="#动图演示" class="headerlink" title="动图演示"></a>动图演示</h3><p><img src="https://lz94wpz.oss-cn-beijing.aliyuncs.com/YoudaoNote/20190419152506.gif" alt=""></p><h3 id="算法分析"><a href="#算法分析" class="headerlink" title="算法分析"></a>算法分析</h3><p>最佳情况：T(n) = O(n<sup>2</sup>)<br>最差情况：T(n) = O(n<sup>2</sup>)<br>平均情况：T(n) = O(n<sup>2</sup>)</p><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SelectionSort</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">selectionSort</span><span class="params">(<span class="type">int</span>[] arr)</span> {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; arr.length - <span class="number">1</span>; i++) {</span><br><span class="line">            <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> i;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> i + <span class="number">1</span>; j &lt; arr.length; j++) {</span><br><span class="line">                <span class="keyword">if</span> (arr[index] &gt; arr[j]) {</span><br><span class="line">                    index = j;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            <span class="keyword">if</span> (index != i) {</span><br><span class="line">                <span class="type">int</span> <span class="variable">t</span> <span class="operator">=</span> arr[index];</span><br><span class="line">                arr[index] = arr[i];</span><br><span class="line">                arr[i] = t;</span><br><span class="line">            }</span><br><span class="line">            System.out.printf(<span class="string">"排序第%2d次后数组为：%s\n"</span>, i + <span class="number">1</span>, Arrays.toString(arr));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">int</span>[] arr = { <span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span> };</span><br><span class="line">        System.out.printf(<span class="string">"原始数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">        selectionSort(arr);</span><br><span class="line">        System.out.printf(<span class="string">"排序后数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">selection_sort</span>(<span class="params">arr</span>):</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(arr) - <span class="number">1</span>):</span><br><span class="line">        index = i</span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(i + <span class="number">1</span>, <span class="built_in">len</span>(arr)):</span><br><span class="line">            <span class="keyword">if</span> arr[index] &gt; arr[j]:</span><br><span class="line">                index = j</span><br><span class="line">        <span class="keyword">if</span> index != i:</span><br><span class="line">            arr[index], arr[i] = arr[i], arr[index]</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">'排序第%2d次后数组为：%s'</span> % (i + <span class="number">1</span>, arr))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    arr = [<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'原始数组：'</span>, arr)</span><br><span class="line">    selection_sort(arr)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'排序后数组：'</span>, arr)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">SelectionSort</span><span class="params">(arr *[15]<span class="type">int</span>)</span></span> {</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(arr)<span class="number">-1</span>; i++ {</span><br><span class="line">        index := i</span><br><span class="line">        <span class="keyword">for</span> j := i + <span class="number">1</span>; j &lt; <span class="built_in">len</span>(arr); j++ {</span><br><span class="line">            <span class="keyword">if</span> arr[index] &gt; arr[j] {</span><br><span class="line">                index = j</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        <span class="keyword">if</span> index != i {</span><br><span class="line">            arr[index], arr[i] = arr[i], arr[index]</span><br><span class="line">        }</span><br><span class="line">        fmt.Printf(<span class="string">"排序第%2d次后数组为：%v\n"</span>, i+<span class="number">1</span>, *arr)</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := [<span class="number">15</span>]<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    SelectionSort(&amp;arr)</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="排序" scheme="https://blog.wpz.homes/tags/%E6%8E%92%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>冒泡排序</title>
    <link href="https://blog.wpz.homes/posts/14e6f1eb/"/>
    <id>https://blog.wpz.homes/posts/14e6f1eb/</id>
    <published>2019-05-28T01:53:14.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="冒泡排序（Bubble-Sort）"><a href="#冒泡排序（Bubble-Sort）" class="headerlink" title="冒泡排序（Bubble Sort）"></a>冒泡排序（Bubble Sort）</h2><p>冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列，一次比较两个元素，如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换，也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。</p><h3 id="算法描述"><a href="#算法描述" class="headerlink" title="算法描述"></a>算法描述</h3><ul><li>比较相邻的元素。如果前面的数比后面的数大(按升序排序)，就交换它们两个；</li><li>对每一对相邻元素作同样的工作，从开始第一对到结尾的最后一对，这样最大的元素就放在了最后面；</li><li>针对所有的元素重复以上的步骤，除了最后一个；</li><li>重复步骤1~3，直到排序完成。</li></ul><h3 id="动图演示"><a href="#动图演示" class="headerlink" title="动图演示"></a>动图演示</h3><p><img src="https://lz94wpz.oss-cn-beijing.aliyuncs.com/YoudaoNote/20190419150654.gif" alt=""></p><h3 id="算法分析"><a href="#算法分析" class="headerlink" title="算法分析"></a>算法分析</h3><p>最佳情况：T(n) = O(n)<br>最差情况：T(n) = O(n<sup>2</sup>)<br>平均情况：T(n) = O(n<sup>2</sup>)</p><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h3><figure class="highlight java"><figcaption><span>Java 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BubbleSort</span> {</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">bubbleSort</span><span class="params">(<span class="type">int</span>[] arr)</span> {</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; arr.length - <span class="number">1</span>; i++) {</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> <span class="number">0</span>; j &lt; arr.length - <span class="number">1</span> - i; j++) {</span><br><span class="line">                <span class="keyword">if</span> (arr[j] &gt; arr[j + <span class="number">1</span>]) {</span><br><span class="line">                    <span class="type">int</span> <span class="variable">t</span> <span class="operator">=</span> arr[j];</span><br><span class="line">                    arr[j] = arr[j + <span class="number">1</span>];</span><br><span class="line">                    arr[j + <span class="number">1</span>] = t;</span><br><span class="line">                }</span><br><span class="line">            }</span><br><span class="line">            System.out.printf(<span class="string">"排序第%2d次后数组为：%s\n"</span>, i + <span class="number">1</span>, Arrays.toString(arr));</span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line">        <span class="type">int</span>[] arr = { <span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span> };</span><br><span class="line">        System.out.printf(<span class="string">"原始数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">        bubbleSort(arr);</span><br><span class="line">        System.out.printf(<span class="string">"排序后数组：%s\n"</span>, Arrays.toString(arr));</span><br><span class="line">    }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><figure class="highlight py"><figcaption><span>Python 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">bubble_sort</span>(<span class="params">arr</span>):</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(arr) - <span class="number">1</span>):</span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(arr) - <span class="number">1</span> - i):</span><br><span class="line">            <span class="keyword">if</span> arr[j] &gt; arr[j + <span class="number">1</span>]:</span><br><span class="line">                arr[j], arr[j + <span class="number">1</span>] = arr[j + <span class="number">1</span>], arr[j]</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">'排序第%2d次后数组为：%s'</span> % (i + <span class="number">1</span>, arr))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    arr = [<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'原始数组：'</span>, arr)</span><br><span class="line">    bubble_sort(arr)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">'排序后数组：'</span>, arr)</span><br></pre></td></tr></tbody></table></figure><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BubbleSort</span><span class="params">(arr *[15]<span class="type">int</span>)</span></span> {</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(arr)<span class="number">-1</span>; i++ {</span><br><span class="line">        <span class="keyword">for</span> j := <span class="number">0</span>; j &lt; <span class="built_in">len</span>(arr)<span class="number">-1</span>-i; j++ {</span><br><span class="line">            <span class="keyword">if</span> arr[j] &gt; arr[j+<span class="number">1</span>] {</span><br><span class="line">                arr[j], arr[j+<span class="number">1</span>] = arr[j+<span class="number">1</span>], arr[j]</span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        fmt.Printf(<span class="string">"排序第%2d次后数组为：%v\n"</span>, i+<span class="number">1</span>, *arr)</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := [<span class="number">15</span>]<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    BubbleSort(&amp;arr)</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h2 id="为什么最佳情况是-O-n"><a href="#为什么最佳情况是-O-n" class="headerlink" title="为什么最佳情况是 O(n)"></a>为什么最佳情况是 O(n)</h2><p>上面说过冒泡排序最佳情况是<code>O(n)</code>，这点我一开时很不理解，看上面代码实现，即便一开始已经是按顺序排序的，但最终还是要经过两层循环，也就是最佳情况依然是<code>O(n<sup>2</sup>)</code>。实际上，上面的代码是可以优化的，下面以<code>Go</code>语言来实现：</p><figure class="highlight go"><figcaption><span>Go 实现</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BubbleSort</span><span class="params">(arr *[15]<span class="type">int</span>)</span></span> {</span><br><span class="line">    flag := <span class="literal">false</span></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(arr)<span class="number">-1</span>; i++ {</span><br><span class="line">        flag = <span class="literal">false</span></span><br><span class="line">        <span class="keyword">for</span> j := <span class="number">0</span>; j &lt; <span class="built_in">len</span>(arr)<span class="number">-1</span>-i; j++ {</span><br><span class="line">            <span class="keyword">if</span> arr[j] &gt; arr[j+<span class="number">1</span>] {</span><br><span class="line">                arr[j], arr[j+<span class="number">1</span>] = arr[j+<span class="number">1</span>], arr[j]</span><br><span class="line">                flag = <span class="literal">true</span></span><br><span class="line">            }</span><br><span class="line">        }</span><br><span class="line">        fmt.Printf(<span class="string">"排序第%2d次后数组为：%v\n"</span>, i+<span class="number">1</span>, *arr)</span><br><span class="line">        <span class="keyword">if</span> !flag {</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        }</span><br><span class="line">    }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">    arr := [<span class="number">15</span>]<span class="type">int</span>{<span class="number">3</span>, <span class="number">44</span>, <span class="number">38</span>, <span class="number">5</span>, <span class="number">47</span>, <span class="number">15</span>, <span class="number">36</span>, <span class="number">26</span>, <span class="number">27</span>, <span class="number">2</span>, <span class="number">46</span>, <span class="number">4</span>, <span class="number">19</span>, <span class="number">50</span>, <span class="number">48</span>}</span><br><span class="line">    fmt.Printf(<span class="string">"原始数组：%v\n"</span>, arr)</span><br><span class="line">    BubbleSort(&amp;arr)</span><br><span class="line">    fmt.Printf(<span class="string">"排序后数组：%v\n"</span>, arr)</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><p>上面的代码，在数组已经从小到大排序的情况下，只需经过一轮循环遍历即可，也就是最佳情况为<code>O(n)</code>。</p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据结构" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    
    
    <category term="排序" scheme="https://blog.wpz.homes/tags/%E6%8E%92%E5%BA%8F/"/>
    
  </entry>
  
  <entry>
    <title>Redis 之 有序集合差集</title>
    <link href="https://blog.wpz.homes/posts/6574bc1f/"/>
    <id>https://blog.wpz.homes/posts/6574bc1f/</id>
    <published>2019-05-15T08:12:51.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="有序集合没有差集命令"><a href="#有序集合没有差集命令" class="headerlink" title="有序集合没有差集命令"></a>有序集合没有差集命令</h2><p><code>Redis</code>集合中提供了<code>SINTER</code>、<code>SUNION</code>、<code>SDIFF</code>命令分别用来处理集合的交集、并集、差集运算。</p><p>有序集合中提供了<code>ZINTERSTORE</code>、<code>ZUNIONSTORE</code>命令分别用来处理有序集合的交集、并集运算。却没有提供用来处理有序集合差集的命令。</p><p>项目中用到<code>Redis</code>的有序集合来存储数据，需要对有序集合进行差集运算，在网上看到这篇文章：<a href="https://github.com/xingrl/blog/issues/1">redis有序集合求差集 zdiff?</a> 提供的解决方法，在此记录下。</p><h2 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h2><p>先使用<code>ZUNIONSTORE</code>计算并集，并设置并集后成员分数权重。</p><pre><code>ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]</code></pre><p>再使用<code>ZREMRANGEBYSCORE</code>去除分数为<code>0</code>的成员。</p><pre><code>ZREMRANGEBYSCORE key min max</code></pre><h2 id="栗子"><a href="#栗子" class="headerlink" title="栗子"></a>栗子</h2><p>先添加两个有序集合<code>chinese</code>和<code>english</code>：</p><pre><code>127.0.0.1:6379&gt; ZADD chinese 100 user1 99 user2 98 user3(integer) 3127.0.0.1:6379&gt; ZADD english 97 user3 96 user4 95 user5(integer) 3127.0.0.1:6379&gt; ZRANGE chinese 0 10 WITHSCORES1) "user3"2) "98"3) "user2"4) "99"5) "user1"6) "100"127.0.0.1:6379&gt; ZRANGE english 0 10 WITHSCORES1) "user5"2) "95"3) "user4"4) "96"5) "user3"6) "97"</code></pre><p>再对有序集合<code>chinese</code>和<code>english</code>进行并集运算：</p><pre><code>127.0.0.1:6379&gt; ZUNIONSTORE result 2 chinese english WEIGHTS 1 0 AGGREGATE MIN(integer) 5127.0.0.1:6379&gt; ZRANGE result 0 10 WITHSCORES1) "user3"2) "0"3) "user4"4) "0"5) "user5"6) "0"7) "user2"8) "99"9) "user1"10) "100"</code></pre><p>这里有必要对<code>ZUNIONSTORE</code>的<code>WEIGHTS</code>和<code>AGGREGATE</code>选项进行说明一番：</p><ul><li><p><code>WEIGHTS</code>选项可以为每个给定的有序集合分别指定一个乘法因子(<code>Multiplication Factor</code>)。每个给定的有序集合的所有成员的分数在传递给聚合函数(<code>Aggregation Function</code>)之前都要先乘以该有序集合的因子。默认值为<code>1</code>。</p></li><li><p><code>AGGREGATE</code>选项指定并集运算结果的聚合方式。默认值为<code>SUM</code>，即将所有相同成员的分数相加。当值为<code>MIN</code>或<code>MAX</code>时，则取所有相同成员的分数的最小值或最大值。</p></li></ul><p>有序集合<code>chinese</code>的权重设置为<code>1</code>，所以合并后<code>user1</code>和<code>user2</code>的分数和合并前一样。有序集合<code>english</code>的权重设置为<code>0</code>，所以合并后<code>user4</code>和<code>user5</code>的分数变为<code>0</code>。至于<code>user3</code>的分数，<code>chinese</code>为<code>98</code>，<code>english</code>为<code>0</code>，由于<code>AGGREGATE</code>值为<code>MIN</code>，所以取最小值<code>0</code>。</p><p>最后移除有序集合<code>result</code>中分数为<code>0</code>的成员：</p><pre><code>127.0.0.1:6379&gt; ZREMRANGEBYSCORE result 0 0(integer) 3127.0.0.1:6379&gt; ZRANGE result 0 10 WITHSCORES1) "user2"2) "99"3) "user1"4) "100"</code></pre><p>现在有序集合<code>result</code>就为<code>chinese</code>和<code>english</code>进行差集运算的结果。</p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据库" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
    <category term="Redis" scheme="https://blog.wpz.homes/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Redis 之 GEO 地理位置</title>
    <link href="https://blog.wpz.homes/posts/c09adc05/"/>
    <id>https://blog.wpz.homes/posts/c09adc05/</id>
    <published>2019-05-14T06:59:50.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><p>最近在做上门洗车项目时有个需求：需要根据用户选择的坐标位置和支持的服务范围来查找附近的洗车门店。项目中用到<code>Redis</code>来做缓存，刚好<code>Redis</code>有支持<code>GEO</code>地理位置的功能，用来实现该需求再合适不过了。遂研究了下<code>Redis</code>的<code>GEO</code>地理位置如何使用。</p><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p><code>Redis</code>从<code>3.2</code>版本开始支持<code>geohash</code>算法，地理位置的坐标是以<code>WGS84</code>为标准。<code>WGS84</code>全称<code>World Geodetic System 1984</code>，是为<code>GPS</code>全球定位系统使用而建立的坐标系统。</p><h2 id="GEO-命令"><a href="#GEO-命令" class="headerlink" title="GEO 命令"></a>GEO 命令</h2><p><code>Redis</code>的<code>GEO</code>目前提供以下6个命令，详情可<a href="https://redis.io/commands#geo">点击查看</a>。</p><div class="note danger">    <p>        1. GEOADD：增加某个地理位置的坐标。<br>        2. GEOPOS：获取某个地理位置的坐标。<br>        3. GEODIST：获取两个地理位置的距离。<br>        4. GEORADIUS：根据给定地理位置坐标获取指定范围内的地理位置集合。<br>        5. GEORADIUSBYMEMBER：根据给定地理位置获取指定范围内的地理位置集合。<br>        6. GEOHASH：获取某个地理位置的<code>geohash</code>值。    </p></div><h3 id="GEOADD"><a href="#GEOADD" class="headerlink" title="GEOADD"></a>GEOADD</h3><p><code>GEOADD</code>命令是用来增加地理位置坐标的，可以批量添加多个地理位置的坐标。命令格式为：</p><pre><code>GEOADD key longitude latitude member [longitude latitude member ...]</code></pre><p><code>key</code>标识一个地理位置的集合，<code>longitude</code>是地理位置的经度，<code>latitude</code>是地理位置的纬度，<code>member</code>是该地理位置的名称。</p><p><code>Redis</code>中接受的有效经度范围为<code>-180～180</code>度，有效纬度范围为<code>-85.05112878～85.05112878</code>度（靠近南北极的一小块地方是无法生成索引的）。</p><h3 id="GEOPOS"><a href="#GEOPOS" class="headerlink" title="GEOPOS"></a>GEOPOS</h3><p><code>GEOPOS</code>命令是用来获取地理位置坐标的，可以批量获取多个地理位置的坐标。命令格式为：</p><pre><code>GEOPOS key member [member ...]</code></pre><h3 id="GEODIST"><a href="#GEODIST" class="headerlink" title="GEODIST"></a>GEODIST</h3><p><code>GEODIST</code>命令是用来获取两个地理位置的距离。命令格式为：</p><pre><code>GEODIST key member1 member2 [unit]</code></pre><p><code>unit</code>单位可选项为<code>m</code>（米，默认值），<code>km</code>（千米），<code>ft</code>（英尺），<code>mi</code>（英里）。</p><h3 id="GEORADIUS"><a href="#GEORADIUS" class="headerlink" title="GEORADIUS"></a>GEORADIUS</h3><p><code>GEORADIUS</code>命令可以根据给定的地理位置坐标获取指定范围内的地理位置集合。命令格式为：</p><pre><code>GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]</code></pre><p><code>key</code>标识一个地理位置的集合，<code>longitude</code>是地理位置的经度，<code>latitude</code>是地理位置的纬度，<code>radius</code>表示范围距离，距离单位可以为<code>m|km|ft|mi</code>，还有一些可选参数：</p><ul><li>WITHCOORD：同时返回匹配位置的经纬度。</li><li>WITHDIST：同时返回匹配位置与给定地理位置的距离。</li><li>WITHHASH：同时返回匹配位置的<code>geohash</code>值。</li><li>COUNT count：指定返回的结果个数，必须大于<code>0</code>。</li><li>ASC|DESC：默认返回的结果是未排序的，<code>ASC</code>为从近到远排序，<code>DESC</code>为从远到近排序。</li><li>STORE key：结果存到新的有序集合中，以<code>geohash</code>做为<code>score</code>，该选项与<code>WITHCOORD</code>、<code>WITHDIST</code>、<code>WITHHASH</code>、<code>STOREDIST</code>选项冲突。</li><li>STOREDIST key：结果存到新的有序集合中，以与指定位置的距离做为<code>score</code>，该选项与<code>WITHCOORD</code>、<code>WITHDIST</code>、<code>WITHHASH</code>、<code>STORE</code>选项冲突。</li></ul><h3 id="GEORADIUSBYMEMBER"><a href="#GEORADIUSBYMEMBER" class="headerlink" title="GEORADIUSBYMEMBER"></a>GEORADIUSBYMEMBER</h3><p><code>GEORADIUSBYMEMBER</code>命令可以根据给定的地理位置获取指定范围内的地理位置集合。命令格式为：</p><pre><code>GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]</code></pre><p>很明显<code>GEORADIUS</code>命令传递的是地理位置坐标，<code>GEORADIUSBYMEMBER</code>命令传递的是地理位置名称。与<code>GEORADIUS</code>相比，使用<code>GEORADIUSBYMEMBER</code>更为方便，但使用<code>GEORADIUS</code>则更为灵活，可以获取任何坐标点范围内的地理位置。</p><h3 id="GEOHASH"><a href="#GEOHASH" class="headerlink" title="GEOHASH"></a>GEOHASH</h3><p><code>GEOHASH</code>命令是用来获取地理位置的<code>geohash</code>值，可以批量获取多个地理位置的<code>geohash</code>值。命令格式为：</p><pre><code>GEOHASH key member [member ...]</code></pre><h3 id="GEORADIUS-RO-和-GEORADIUSBYMEMBER-RO"><a href="#GEORADIUS-RO-和-GEORADIUSBYMEMBER-RO" class="headerlink" title="GEORADIUS_RO 和 GEORADIUSBYMEMBER_RO"></a>GEORADIUS_RO 和 GEORADIUSBYMEMBER_RO</h3><p><code>GEORADIUS_RO</code>和<code>GEORADIUSBYMEMBER_RO</code>是<code>Redis 3.2.10</code>后新引进的两个命令。由于<code>GEORADIUS</code>和<code>GEORADIUSBYMEMBER</code>命令存在<code>STORE</code>和<code>STOREDIST</code>选项，在<code>Redis</code>中该两个命令被标记为写命令类型。即使在从节点的连接设置了<code>readonly</code>模式下，标记为写命令类型的命令，依然会收到<code>MOVED</code>消息，被转向到相应主节点。所以<code>Redis</code>新增了该两个命令的只读版本，这两个命令除了不支持<code>STORE</code>和<code>STOREDIST</code>选项外，其他可选参数与<code>GEORADIUS_RO</code>和<code>GEORADIUSBYMEMBER_RO</code>一致。新增的两个只读命令在从节点连接设置<code>readonly</code>模式下可以在从节点执行。</p><h2 id="GEO-实现"><a href="#GEO-实现" class="headerlink" title="GEO 实现"></a>GEO 实现</h2><p><code>Redis GEO</code>实现主要包含了以下两项技术：</p><div class="note danger">    <p>        1. 使用<code>geohash</code>保存地理位置的坐标。<br>        2. 使用有序集合保存地理位置的集合。    </p></div><h3 id="使用-geohash-保存地理位置的坐标"><a href="#使用-geohash-保存地理位置的坐标" class="headerlink" title="使用 geohash 保存地理位置的坐标"></a>使用 geohash 保存地理位置的坐标</h3><p>使用<code>geohash</code>保存地理位置的坐标的思想是将二维的经纬度转换成一维的字符串<code>hash</code>值。<code>geohash</code>有以下三个特点：</p><div class="note danger">    <p>        1. 字符串越长，表示的范围越精确。编码长度为 8 时，精度在 19 米左右，而当编码长度为 9 时，精度在 2 米左右。<br>        2. 字符串相似的表示距离相近。利用字符串的前缀匹配，可以快速的查询到附近的地理位置。<br>        3. geohash 计算的字符串，可以反向解码出原来的经纬度。    </p></div><p>这三个特性让<code>geohash</code>特别适合表示二维<code>hash</code>值。这篇文章：<a href="http://www.cnblogs.com/LBSer/p/3310455.html">GeoHash核心原理解析</a>详细的介绍了<code>geohash</code>的原理，想要了解<code>geohash</code>实现的朋友可以参考这篇文章。</p><h3 id="使用有序集合保存地理位置的集合"><a href="#使用有序集合保存地理位置的集合" class="headerlink" title="使用有序集合保存地理位置的集合"></a>使用有序集合保存地理位置的集合</h3><p>各个命令的实现原理：</p><ul><li><code>GEOADD</code>命令增加地理位置时，先计算地理位置坐标的<code>geohash</code>值，然后<code>geohash</code>作为给定的<code>member</code>的<code>score</code>使用<code>ZADD</code>命令插入到有序集合。</li><li><code>GEOPOS</code>命令获取地理位置坐标时，先根据给定的<code>member</code>获取到<code>score</code>，也就是地理位置的<code>geohash</code>值，然后<code>decode</code>得到地理位置的坐标。</li><li><code>GEODIST</code>命令获取两个地理位置的距离时，先根据给定的<code>member</code>获得各自的坐标，然后计算两个坐标的距离。</li><li><code>GEORADIUS</code>和<code>GEORADIUSBYMEMBER</code>使用相同的实现(<code>GEORADIUSBYMEMBER</code>多了一步把地理位置转换成对应的坐标)。先查找该坐标和周围对应<code>8</code>个坐标符合距离要求的地理位置。因为<code>geohash</code>得到的值其实是个格子，并不是点，这样通过计算周围对应<code>8</code>个坐标就能解决边缘问题。由于使用有序集合保存地理位置，在对地列位置基于范围查询，就相当于实现了<code>ZRANGE</code>命令，内部的实现确实与<code>ZRANGE</code>命令一致，只是<code>GEO</code>有些特别的处理，比如获得的某个地理位置，还需要计算该地理位置是否符合给定的距离访问。</li><li><code>GEOHASH</code>命令获取地理位置的<code>geohash</code>值时，直接根据给定的<code>member</code>获取到<code>score</code>。</li></ul><p>细心的读者可能发现，<code>Redis</code>没有实现地理位置的删除命令。不过由于<code>GEO</code>数据是使用有序集合保存的，所以可以使用<code>ZREM</code>命令来删除某个地理位置。</p><h2 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="http://weizijun.cn/2016/03/28/redis3.2%E6%96%B0%E5%8A%9F%E8%83%BD--GEO%E5%9C%B0%E7%90%86%E4%BD%8D%E7%BD%AE%E5%91%BD%E4%BB%A4%E4%BB%8B%E7%BB%8D/">redis3.2新功能—GEO地理位置命令介绍</a></p><p><a href="https://luoming1224.github.io/2019/04/08/[redis%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0]redis%E4%B8%ADGeo%E5%91%BD%E4%BB%A4%E4%BB%8B%E7%BB%8D/">[redis学习笔记]redis中Geo命令介绍</a></p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="数据库" scheme="https://blog.wpz.homes/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
    <category term="Redis" scheme="https://blog.wpz.homes/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Dockerfile 之 ADD/COPY 指令</title>
    <link href="https://blog.wpz.homes/posts/b3b04b5f/"/>
    <id>https://blog.wpz.homes/posts/b3b04b5f/</id>
    <published>2019-05-13T08:37:58.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="Build-Context-构建上下文"><a href="#Build-Context-构建上下文" class="headerlink" title="Build Context(构建上下文)"></a>Build Context(构建上下文)</h2><p>在使用<code>docker build</code>命令通过<code>Dockerfile</code>创建镜像时，会产生一个<code>build context</code>(构建上下文)。所谓的构建上下文就是<code>docker build</code>命令的<code>PATH</code>或<code>URL</code>指定的路径中的文件的集合。在镜像<code>build</code>过程中可以引用上下文中的任何文件，比如我们要介绍的<code>ADD</code>和<code>COPY</code>指令就可以引用上下文中的文件。</p><h2 id="ADD"><a href="#ADD" class="headerlink" title="ADD"></a>ADD</h2><p><code>ADD</code>指令用于将构建上下文中指定的文件添加到镜像中的，支持两种形式的写法：</p><pre><code>ADD src destADD ["src", "dest"]</code></pre><p><code>ADD</code>指令有以下几个特点：</p><div class="note danger">    <p>        1. 如果指定的 src 是归档文件(tar, zip, tgz, xz 等)会自动将其解压。<br>        2. 如果指定的 src 是目录，只会添加目录中的内容而不包含目录自身。<br>        3. 如果指定的 src 是 URL 地址，会从 URL 地址下载文件并将其添加到 dest，如果下载的文件是归档文件不会自动解压。    </p></div><h3 id="通过一个简单的栗子来说明"><a href="#通过一个简单的栗子来说明" class="headerlink" title="通过一个简单的栗子来说明"></a>通过一个简单的栗子来说明</h3><p>当前构建上下文目录结构：</p><pre><code>root# tree.├── a│   ├── a.log│   └── b.log├── alpine-minirootfs-3.9.3-x86_64.tar.gz├── a.txt└── Dockerfile1 directory, 5 files</code></pre><figure class="highlight dockerfile"><figcaption><span>Dockerfile 文件</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> scratch</span><br><span class="line"><span class="keyword">WORKDIR</span><span class="language-bash"> /workspaces</span></span><br><span class="line"><span class="comment"># 添加归档文件到镜像中</span></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> alpine-minirootfs-3.9.3-x86_64.tar.gz /</span></span><br><span class="line"><span class="comment"># 添加普通文件到镜像中</span></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> a.txt .</span></span><br><span class="line"><span class="comment"># 添加目录到镜像中</span></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> a .</span></span><br><span class="line"><span class="comment"># 从 URL 地址下载文件并添加到镜像中</span></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master .</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker build -t alpine .</code>构建镜像：</p><pre><code>root# docker build -t alpine .Sending build context to Docker daemon  2.689MBStep 1/6 : FROM scratch---&gt; Step 2/6 : WORKDIR /workspaces---&gt; Running in 669cd08b2be7Removing intermediate container 669cd08b2be7---&gt; 894324123641Step 3/6 : ADD alpine-minirootfs-3.9.3-x86_64.tar.gz /---&gt; 471bc43f5e0cStep 4/6 : ADD a.txt .---&gt; d22c05b89d9dStep 5/6 : ADD a .---&gt; 54a77a7a1dd8Step 6/6 : ADD https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master .Downloading    537kB---&gt; a443738c3f2fSuccessfully built a443738c3f2fSuccessfully tagged alpine:latest</code></pre><p><code>Step 1/6</code>获取空白镜像，<code>Step 2/6</code>指定镜像工作空间为<code>/workspaces</code>，<code>Step 3/6</code>添加<code>alpine-minirootfs-3.9.3-x86_64.tar.gz</code>归档文件到镜像中，<code>Step 4/6</code>添加<code>a.txt</code>文件到镜像中，<code>Step 5/6</code>添加<code>a</code>目录到镜像中，<code>Step 6/6</code>下载归档文件并添加到镜像中。</p><p>执行<code>docker run -it alpine /bin/sh</code>启动容器：</p><pre><code>root# docker run -it alpine /bin/sh/workspaces # ls /bin         etc         lib         mnt         proc        run         srv         tmp         vardev         home        media       opt         root        sbin        sys         usr         workspaces/workspaces # ls -ltotal 708-rw-r--r--    1 root     root             0 May 13 08:56 a.log-rw-r--r--    1 root     root             0 May 13 08:55 a.txt-rw-r--r--    1 root     root             0 May 13 08:56 b.log-rw-------    1 root     root        721697 Jan  1  1970 master</code></pre><p>可以看到<code>alpine-minirootfs-3.9.3-x86_64.tar.gz</code>文件添加到<code>/</code>根目录，由于是归档文件被自动解压了。<code>a.txt</code>文件添加到当前目录，也就是工作目录(<code>/workspaces</code>)。<code>a</code>目录中的内容添加到当前目录(<strong>只添加目录中的内容而不包含目录自身</strong>)，<code>https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master</code>下载的归档文件添加到当前目录，不会自动解压(<code>URL</code>下载和归档解包功能不能一起使用)。</p><h3 id="解决添加目录，只添加目录中的内容而不包含目录自身的问题"><a href="#解决添加目录，只添加目录中的内容而不包含目录自身的问题" class="headerlink" title="解决添加目录，只添加目录中的内容而不包含目录自身的问题"></a>解决添加目录，只添加目录中的内容而不包含目录自身的问题</h3><p>上面的栗子可以看出，本意是要添加<code>a</code>目录到镜像中，结果只添加<code>a</code>目录下面的内容到镜像中。解决这个问题也很简单，稍微修改下<code>Dockerfile</code>文件：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ADD</span><span class="language-bash"> a .</span></span><br></pre></td></tr></tbody></table></figure><p>改为：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ADD</span><span class="language-bash"> a ./a</span></span><br></pre></td></tr></tbody></table></figure><h3 id="解决从-URL-地址下载归档文件不自动解压的问题"><a href="#解决从-URL-地址下载归档文件不自动解压的问题" class="headerlink" title="解决从 URL 地址下载归档文件不自动解压的问题"></a>解决从 URL 地址下载归档文件不自动解压的问题</h3><p>解决从<code>URL</code>地址下载归档文件不自动解压的问题，思路也很简单，不自动解压那我们手动解压就是了：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ADD</span><span class="language-bash"> https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master .</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> unzip master &amp;&amp; <span class="built_in">rm</span> master</span></span><br></pre></td></tr></tbody></table></figure><p>上面的方法虽然可行，但<code>Docker</code>官方不建议这么使用！<code>Docker</code>官方建议我们当需要从远程复制文件时，最好使用<code>curl</code>或<code>wget</code>命令来代替<code>ADD</code>命令。原因是，当使用<code>ADD</code>命令时，会创建更多的镜像层，当然镜像的<code>size</code>也会更大。现在我们使用<code>wget</code>来替代上面的命令：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> wget https://codeload.github.com/lz94wpz/lz94wpz.github.io/zip/master &amp;&amp; unzip master &amp;&amp; <span class="built_in">rm</span> master</span></span><br></pre></td></tr></tbody></table></figure><h2 id="COPY"><a href="#COPY" class="headerlink" title="COPY"></a>COPY</h2><p><code>COPY</code>指令用于将构建上下文中指定的文件复制到镜像中的，同样支持两种形式的写法：</p><pre><code>COPY src destCOPY ["src", "dest"]</code></pre><p>与<code>ADD</code>不同的是<code>COPY</code>不会自动解压归档文件，也不支持<code>URL</code>作为<code>src</code>参数，因此不能用于从远程位置下载文件。<code>COPY</code>可以看做是<code>ADD</code>的精简版本。</p><h2 id="使用-ADD-还是-COPY？"><a href="#使用-ADD-还是-COPY？" class="headerlink" title="使用 ADD 还是 COPY？"></a>使用 ADD 还是 COPY？</h2><p>使用<code>ADD</code>还是<code>COPY</code>？<code>Docker</code>团队的建议是在几乎所有情况下都使用<code>COPY</code>。唯一需要使用<code>ADD</code>的情况是需要自动解压归档文件。<code>ADD</code>通过<code>URL</code>下载文件则使用<code>curl</code>或<code>wget</code>代替。</p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/categories/Docker/"/>
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>Dockerfile 之 RUN/CMD/ENTRYPOINT 指令</title>
    <link href="https://blog.wpz.homes/posts/2262a086/"/>
    <id>https://blog.wpz.homes/posts/2262a086/</id>
    <published>2019-05-13T03:53:06.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="RUN"><a href="#RUN" class="headerlink" title="RUN"></a>RUN</h2><p><code>RUN</code>指令指定的命令在<code>docker build</code>构建镜像的时候执行。常用于安装软件包。可以有多个<code>RUN</code>指令，且每个都生效。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 文件</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> ubuntu:<span class="number">18.04</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt update &amp;&amp; apt install -y vim</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">touch</span> a</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker build</code>构建镜像时会在一层镜像层中更新源并安装<code>vim</code>命令，在另一个镜像层中创建<code>a</code>文件。</p><p>注意：<code>apt update</code>和<code>apt install</code>被放在一个<code>RUN</code>指令中执行，这样能够保证每次安装的是最新的包。如果<code>apt install</code>在单独的<code>RUN</code>中执行，则会使用<code>apt update</code>创建的镜像层，而这一层可能是很久以前缓存的。</p><h2 id="CMD-amp-amp-ENTRYPOINT"><a href="#CMD-amp-amp-ENTRYPOINT" class="headerlink" title="CMD &amp;&amp; ENTRYPOINT"></a>CMD &amp;&amp; ENTRYPOINT</h2><p><code>CMD</code>指令指定的命令在容器启动后执行。可以有多个<code>CMD</code>指令，但只有最后一个生效。<code>CMD</code>指定的命令会被<code>docker run</code>之后的参数替换。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 文件</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> ubuntu:trusty</span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> hostname</span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> ping localhost</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker build -t ubuntu1 .</code>构建一个<code>ubuntu1</code>镜像。执行<code>docker run -t ubuntu1</code>：</p><pre><code>root# docker run -t ubuntu1PING localhost (127.0.0.1) 56(84) bytes of data.64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.031 ms64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.038 ms64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.037 ms^C</code></pre><p>可以看出虽然<code>Dockerfile</code>文件中指定了两个<code>CMD</code>指令，但只有最后一个<code>CMD</code>指令执行，<code>ping</code>命令在容器启动后执行。</p><p>尽管指定了<code>CMD</code>指令，但我们可以在启动容器时, 执行其他命令行参数, 覆盖默认的<code>CMD</code>指令：</p><pre><code>root# docker run -t ubuntu1 hostname59cd3e4806ee</code></pre><p>容器启动后, 并没有执行<code>ping</code>命令, 而是执行了<code>hostname</code>命令。</p><p>和<code>CMD</code>指令类似<code>ENTRYPOINT</code>指令指定的命令也在容器启动后执行。也可以有多个<code>ENTRYPOINT</code>指令，也是只有最后一个生效。也可以被覆盖，在运行时使用<code>--entrypoint</code>覆盖默认值。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 文件</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> ubuntu:trusty</span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> hostname</span></span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> ping localhost</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker build -t ubuntu2 .</code>构建一个<code>ubuntu2</code>镜像。执行<code>docker run -t ubuntu2</code>：</p><pre><code>root# docker run -t ubuntu2PING localhost (127.0.0.1) 56(84) bytes of data.64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.024 ms64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.038 ms64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.039 ms^C</code></pre><p>执行<code>docker run -t --entrypoint hostname ubuntu2</code>：</p><pre><code>root# docker run -t --entrypoint hostname ubuntu230a2145449c3</code></pre><p>从根本上说，<code>CMD</code>指令和<code>ENTRYPOINT</code>指令都是让用户指定一个可执行程序, 这个可执行程序在容器启动后自动执行。实际上，如果你想让自己制作的镜像自动运行程序(不需要在<code>docker run</code>后面添加命令行指定运行的命令)，你必须在<code>Dockerfile</code>里面使用<code>CMD</code>指令或<code>ENTRYPOINT</code>指令。如果运行一个没有调用<code>CMD</code>指令或<code>ENTRYPOINT</code>指令的镜像, 一定返回错误：</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 文件</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> scratch</span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> alpine-minirootfs-3.9.3-x86_64.tar.gz /</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker build -t alpine .</code>构建一个<code>alpine</code>镜像。执行<code>docker run -t alpine</code>：</p><pre><code>root# docker run -t alpinedocker: Error response from daemon: No command specified.See 'docker run --help'.</code></pre><h2 id="Shell-amp-amp-Exec"><a href="#Shell-amp-amp-Exec" class="headerlink" title="Shell &amp;&amp; Exec"></a>Shell &amp;&amp; Exec</h2><p><code>RUN</code>、<code>CMD</code>和<code>ENTRYPOINT</code>都支持两种形式的写法：<code>Shell</code>和<code>Exec</code>。二者在使用上有细微的区别。</p><figure class="highlight sh"><figcaption><span>Shell 格式</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;instruction&gt; &lt;<span class="built_in">command</span>&gt;</span><br></pre></td></tr></tbody></table></figure><p>当指令执行时，<code>Shell</code>格式的写法底层会调用<code>/bin/sh -c &lt;command&gt;</code>。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 片段</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ENV</span> WORLD world</span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> <span class="built_in">echo</span> <span class="string">"Hello <span class="variable">$WORLD</span>"</span></span></span><br></pre></td></tr></tbody></table></figure><p>容器启动后将输出：<code>Hello world</code>。</p><figure class="highlight sh"><figcaption><span>Exec 格式</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;instruction&gt; [<span class="string">"executable"</span>, <span class="string">"param1"</span>, <span class="string">"param2"</span>, ...]</span><br></pre></td></tr></tbody></table></figure><p>当指令执行时，<code>Exec</code>格式的写法会直接调用<code>&lt;command&gt;</code>，不会被<code>shell</code>解析。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 片段</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ENV</span> WORLD world</span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">"/bin/echo"</span>, <span class="string">"Hello <span class="variable">$WORLD</span>"</span>]</span></span><br></pre></td></tr></tbody></table></figure><p>容器启动后将输出：<code>Hello $WORLD</code>。</p><p>注意环境变量<code>WORLD</code>没有被替换。如果希望环境变量被替换，修改为：</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 片段</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ENV</span> WORLD world</span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">"/bin/sh"</span>, <span class="string">"-c"</span>, <span class="string">"echo Hello <span class="variable">$WORLD</span>"</span>]</span></span><br></pre></td></tr></tbody></table></figure><p>尽管<code>CMD</code>和<code>ENTRYPOINT</code>都支持两种形式的写法，但更推荐使用<code>Exec</code>格式。<code>RUN</code>则两种格式都可以。</p><h2 id="CMD-作为参数传递给-ENTRYPOINT"><a href="#CMD-作为参数传递给-ENTRYPOINT" class="headerlink" title="CMD 作为参数传递给 ENTRYPOINT"></a>CMD 作为参数传递给 ENTRYPOINT</h2><p>上面说过尽管<code>CMD</code>和<code>ENTRYPOINT</code>都支持两种形式的写法，但更推荐使用<code>Exec</code>格式。因为当<code>CMD</code>作为参数为<code>ENTRYPOINT</code>提供额外的参数时，<code>ENTRYPOINT</code>必须使用<code>Exec</code>格式才能接收到参数。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 片段</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">"/bin/echo"</span>, <span class="string">"Hello"</span>]</span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">"world"</span>]</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker run &lt;image&gt;</code>启动容器后将输出：<code>Hello world</code>。执行<code>docker run &lt;image&gt; 世界</code>启动容器后将输出：<code>Hello 世界</code>。</p><figure class="highlight dockerfile"><figcaption><span>Dockerfile 片段</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> <span class="string">"echo Hello"</span></span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">"world"</span>]</span></span><br></pre></td></tr></tbody></table></figure><p>执行<code>docker run &lt;image&gt;</code>启动容器后将输出：<code>Hello</code>。执行<code>docker run &lt;image&gt; 世界</code>启动容器后将输出：<code>Hello</code>。<code>ENTRYPOINT</code>的<code>Shell</code>格式会忽略任何<code>CMD</code>或<code>docker run</code>提供的参数。</p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/categories/Docker/"/>
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>创建自己的 Docker 镜像</title>
    <link href="https://blog.wpz.homes/posts/e2f703e6/"/>
    <id>https://blog.wpz.homes/posts/e2f703e6/</id>
    <published>2019-05-10T03:32:09.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><p><code>docker pull</code>下来的镜像有时候不能满足我们的需求，这时候我们可以在这些镜像的基础上创建属于我们自己的镜像。</p><h2 id="使用-docker-commit-创建自己的镜像"><a href="#使用-docker-commit-创建自己的镜像" class="headerlink" title="使用 docker commit 创建自己的镜像"></a>使用 docker commit 创建自己的镜像</h2><p>执行<code>docker run -it ubuntu:18.04 /bin/bash</code>，进入容器后发现没有<code>vim</code>命令:</p><pre><code>root# docker run -it ubuntu:18.04 /bin/bashroot@1d0e7bcf5430:/# vimbash: vim: command not found</code></pre><p>以此为例，我们来创建一个已经安装了<code>vim</code>命令的<code>ubuntu</code>镜像。</p><p>先在容器内安装<code>vim</code>命令：</p><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt update &amp;&amp; apt upgrade -y</span><br><span class="line">apt install -y vim</span><br></pre></td></tr></tbody></table></figure><p>安装完<code>vim</code>命令后我们就可以将这个容器打包成自己的镜像了。</p><p>首先我们要知道容器的<code>ID</code>，使用<code>docker ps -a</code>查看：</p><pre><code>root# docker ps -aCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES1d0e7bcf5430        ubuntu:18.04        "/bin/bash"         2 minutes ago       Up 2 minutes                            vigilant_kapitsa</code></pre><p>容器<code>ID</code>为<code>1d0e7bcf5430</code>，执行<code>docker commit 1d0e7bcf5430 ubuntu-vim-1:18.04</code>将容器打包成镜像。<code>ubuntu-vim-1:18.04</code>为容器打包后的镜像名称和标签。</p><p>使用<code>docker images</code>查看打包后的镜像：</p><pre><code>root# docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEubuntu-vim-1        18.04               ef1ded0d8102        12 seconds ago      191MBubuntu              18.04               d131e0fa2585        13 days ago         102MB</code></pre><p><code>ubuntu:18.04</code>为执行<code>docker run</code>自动<code>pull</code>下来的镜像，<code>ubuntu-vim-1:18.04</code>为我们<code>docker commit</code>创建的镜像。很明显<code>ubuntu-vim-1:18.04</code>的体积比<code>ubuntu:18.04</code>大，因为我们更新了软件(<code>apt update &amp;&amp; apt upgrade -y</code>)并安装了<code>vim</code>(<code>apt install -y vim</code>)。</p><p>现在执行<code>docker run -it ubuntu-vim-1:18.04 /bin/bash</code>，进入容器后已经安装了<code>vim</code>命令。</p><h2 id="使用-Dockerfile-创建自己的镜像"><a href="#使用-Dockerfile-创建自己的镜像" class="headerlink" title="使用 Dockerfile 创建自己的镜像"></a>使用 Dockerfile 创建自己的镜像</h2><p>前面我们介绍了使用<code>docker commit</code>创建自己的镜像，除此之外我们也可以使用<code>Dockerfile</code>创建自己的镜像。</p><p>创建一个名为<code>Dockerfile</code>的文件，编写以下内容：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> ubuntu:<span class="number">18.04</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt update &amp;&amp; apt upgrade -y</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt install -y vim</span></span><br></pre></td></tr></tbody></table></figure><p>使用<code>docker build</code>构建镜像:</p><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker build -t ubuntu-vim-2:18.04 -f Dockerfile .</span><br></pre></td></tr></tbody></table></figure><p>参数<code>-t</code>指定构建的镜像的名称和标签。参数<code>-f</code>指定构建镜像的<code>Dockerfile</code>文件，如果<code>Dockerfile</code>文件在当前路径下可以省略不指定。</p><p>使用<code>docker images</code>查看打包后的镜像：</p><pre><code>root# docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEubuntu-vim-2        18.04               2e2c1d07123c        3 seconds ago       192MBubuntu-vim-1        18.04               ef1ded0d8102        2 minutes ago       191MBubuntu              18.04               d131e0fa2585        13 days ago         102MB</code></pre><p><code>ubuntu-vim-2:18.04</code>为我们通过<code>Dockerfile</code>文件构建的镜像。</p><p>执行<code>docker run -it ubuntu-vim-2:18.04 /bin/bash</code>，进入容器后同样已经安装了<code>vim</code>命令。</p><h2 id="创建自己的-Docker-基础镜像"><a href="#创建自己的-Docker-基础镜像" class="headerlink" title="创建自己的 Docker 基础镜像"></a>创建自己的 Docker 基础镜像</h2><p>上面介绍的都是在<code>ubuntu:18.04</code>这个镜像的基础上继续叠加创建的镜像。使用<code>docker history</code>可以查看镜像的历史操作记录：</p><pre><code>root# docker history ubuntu-vim-2:18.04IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT2e2c1d07123c        24 minutes ago      /bin/sh -c apt install -y vim                   59.5MB              5955d39b6725        25 minutes ago      /bin/sh -c apt update &amp;&amp; apt upgrade -y         30.4MB              d131e0fa2585        13 days ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  &lt;missing&gt;           13 days ago         /bin/sh -c mkdir -p /run/systemd &amp;&amp; echo 'do…   7B                  &lt;missing&gt;           13 days ago         /bin/sh -c rm -rf /var/lib/apt/lists/*          0B                  &lt;missing&gt;           13 days ago         /bin/sh -c set -xe   &amp;&amp; echo '#!/bin/sh' &gt; /…   745B                &lt;missing&gt;           13 days ago         /bin/sh -c #(nop) ADD file:7ce84f13f11609a50…   102MB</code></pre><p>可以看到我们在<code>ubuntu:18.04</code>镜像的基础上添加了第六层和第七层(从下往上数)，生成了自己的新的镜像<code>ubuntu-vim-2:18.04</code>。</p><p>如果我们想要从第一层就开始自己创建，可以使用<code>scratch</code>镜像。<code>scratch</code>是<code>Docker</code>保留镜像，镜像仓库中的任何镜像都不能使用这个名字，使用<code>FROM scratch</code>表明我们要构建镜像中的第一个文件层。</p><p>创建<code>Dockerfile</code>文件，编写以下内容：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> scratch</span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> hello /</span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">"/hello"</span>]</span></span><br></pre></td></tr></tbody></table></figure><p>在<code>Dockerfile</code>文件路径下执行<code>docker build -t hello:1.0 .</code>构建镜像。执行<code>docker images</code>查看镜像：</p><pre><code>root# docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEhello               1.0                 3aedfc6e1ff4        3 minutes ago       4.75kBubuntu-vim-2        18.04               2e2c1d07123c        18 minutes ago      192MBubuntu-vim-1        18.04               ef1ded0d8102        20 minutes ago      191MBubuntu              18.04               d131e0fa2585        13 days ago         102MB</code></pre><p>可以看到<code>hello:1.0</code>镜像的大小只有<code>4.75kB</code>，这就是使用<code>scratch</code>创建镜像的一个好处，我们可以根据自己的需求来制定镜像，尽量减少镜像的大小。</p><p>执行<code>docker history hello:1.0</code>查看镜像的历史操作记录：</p><pre><code>root# docker history hello:1.0IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT3aedfc6e1ff4        16 minutes ago      /bin/sh -c #(nop)  CMD ["/hello"]               0B                  15ad555d6f11        16 minutes ago      /bin/sh -c #(nop) ADD file:68f5ca1511528e4f6…   4.75kB</code></pre><p>这就是一个基础的镜像，但是如果需要基础镜像发挥更多的作用，我们还需要其他的工作。<code>Docker</code>中的容器运行在操作系统中，共享了操作系统的内核。对于在<code>Mac</code>、<code>Windows</code>平台下，则是基于<code>Linux</code>虚拟机的内核。而<code>Linux</code>内核仅提供了进程管理、内存管理、文件系统管理等一些基础的管理模块。除此之外，我们还需要一些<code>Linux</code>下的管理工具，包括<code>ls</code>、<code>cp</code>、<code>mv</code>、<code>tar</code>以及应用程序运行依赖的一些包。因此我们就需要首先构建一个<code>Minimal</code>的操作系统镜像。</p><h2 id="创建-Linux-镜像：alpine"><a href="#创建-Linux-镜像：alpine" class="headerlink" title="创建 Linux 镜像：alpine"></a>创建 Linux 镜像：alpine</h2><p>目前比较流行的<code>rootfs</code>应该就是<code>alpine</code>了，因为他的体积特别小，最简单的环境只需要<code>5M</code>，下面是他的目录结构，下载地址在<a href="https://alpinelinux.org/downloads/">这里</a>。</p><p><img src="https://lz94wpz.oss-cn-beijing.aliyuncs.com/Blog/20190510164652.png" alt=""></p><p>创建<code>Dockerfile</code>文件，编写以下内容：</p><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> scratch</span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> alpine-minirootfs-3.9.3-x86_64.tar.gz /</span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">"/bin/sh"</span>]</span></span><br></pre></td></tr></tbody></table></figure><p>在<code>Dockerfile</code>文件路径下执行<code>docker build -t alpine:3.9 .</code>构建镜像：</p><pre><code>root# docker build -t alpine:3.9 .Sending build context to Docker daemon  31.32MBStep 1/3 : FROM scratch---&gt; Step 2/3 : ADD alpine-minirootfs-3.9.3-x86_64.tar.gz /---&gt; f305258a780dStep 3/3 : CMD ["/bin/sh"]---&gt; Running in c22527cf1c54Removing intermediate container c22527cf1c54---&gt; c9cb5e863866Successfully built c9cb5e863866Successfully tagged alpine:3.9</code></pre><p>执行<code>docker images</code>查看镜像：</p><pre><code>root# docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEalpine              3.9                 c9cb5e863866        40 minutes ago      5.53MBhello               1.0                 3aedfc6e1ff4        About an hour ago   4.75kBubuntu-vim-2        18.04               2e2c1d07123c        About an hour ago   192MBubuntu-vim-1        18.04               ef1ded0d8102        About an hour ago   191MBubuntu              18.04               d131e0fa2585        13 days ago         102MB</code></pre><p>执行<code>docker history alpine:3.9</code>查看镜像的历史操作记录：</p><pre><code>root# docker history alpine:3.9IMAGE               CREATED             CREATED BY                                      SIZE                COMMENTc9cb5e863866        About an hour ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0Bf305258a780d        About an hour ago   /bin/sh -c #(nop) ADD file:32fa3bc24e9a2340c…   5.53MB</code></pre><p>运行：</p><pre><code>root# docker run -it alpine:3.9/ # lsbin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var</code></pre><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/categories/Docker/"/>
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>Dockerfile 常用指令</title>
    <link href="https://blog.wpz.homes/posts/6cc4d10b/"/>
    <id>https://blog.wpz.homes/posts/6cc4d10b/</id>
    <published>2019-05-09T02:31:20.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><p>记录下<code>Dockerfile</code>中常用的指令，完整列表和说明可参考官方文档。</p><h2 id="Dockerfile"><a href="#Dockerfile" class="headerlink" title="Dockerfile"></a>Dockerfile</h2><figure class="highlight dockerfile"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> scratch</span><br><span class="line"></span><br><span class="line"><span class="keyword">MAINTAINER</span> lz94wpz</span><br><span class="line"></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="language-bash"> /workspaces</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> alpine-minirootfs-3.9.3-x86_64.tar.gz /</span></span><br><span class="line"><span class="comment"># COPY ["alpine-minirootfs-3.9.3-x86_64.tar.gz", "/"]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> alpine-minirootfs-3.9.3-x86_64.tar.gz /</span></span><br><span class="line"><span class="comment"># ADD ["alpine-minirootfs-3.9.3-x86_64.tar.gz", "/"]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ENV</span> HELLO hello</span><br><span class="line"><span class="keyword">ENV</span> WORLD world</span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> [<span class="string">"/bin/sh"</span>, <span class="string">"-c"</span>, <span class="string">"echo <span class="variable">$HELLO</span>"</span>]</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">echo</span> <span class="variable">$WORLD</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">"/bin/sh"</span>, <span class="string">"-c"</span>, <span class="string">"/bin/echo <span class="variable">$HELLO</span>"</span>]</span></span><br><span class="line"><span class="comment"># CMD echo $WORLD</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ENTRYPOINT ["/bin/sh", "-c", "/bin/echo $HELLO"]</span></span><br><span class="line"><span class="comment"># ENTRYPOINT echo $WORLD</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">EXPOSE</span> <span class="number">80</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">VOLUME</span><span class="language-bash"> /test</span></span><br></pre></td></tr></tbody></table></figure><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker build -t IMAGE_NAME:TAG .  <span class="comment"># 默认使用指定路径下的Dockerfile文件构建镜像，Dockerfile文件不存在时会报错</span></span><br><span class="line">docker build -t IMAGE_NAME:TAG -f Dockerfile .  <span class="comment"># 使用-f参数指定构建镜像的Dockerfile文件</span></span><br></pre></td></tr></tbody></table></figure><h2 id="FROM"><a href="#FROM" class="headerlink" title="FROM"></a>FROM</h2><p>指定基础镜像。</p><h2 id="MAINTAINER"><a href="#MAINTAINER" class="headerlink" title="MAINTAINER"></a>MAINTAINER</h2><p>设置镜像作者信息。</p><h2 id="WORKDIR"><a href="#WORKDIR" class="headerlink" title="WORKDIR"></a>WORKDIR</h2><p>设置镜像的工作目录，默认为<code>/</code>根目录。</p><h2 id="ENV"><a href="#ENV" class="headerlink" title="ENV"></a>ENV</h2><p>设置环境变量。可设置多个。</p><h2 id="EXPOSE"><a href="#EXPOSE" class="headerlink" title="EXPOSE"></a>EXPOSE</h2><p>指定容器中的进程会监听某个端口，<code>Docker</code>可以将该端口暴露出来。</p><h2 id="VOLUME"><a href="#VOLUME" class="headerlink" title="VOLUME"></a>VOLUME</h2><p>将文件或目录声明为<code>volume</code>。</p><h2 id="COPY-amp-amp-ADD"><a href="#COPY-amp-amp-ADD" class="headerlink" title="COPY &amp;&amp; ADD"></a>COPY &amp;&amp; ADD</h2><p><code>COPY</code>和<code>ADD</code>都是用于将构建环境中指定的文件添加到镜像中的。不同的是如果指定的文件是归档文件(<code>tar</code>, <code>zip</code>, <code>tgz</code>, <code>xz</code>等)，<code>ADD</code>指令会将其解压，<code>COPY</code>指令不会。</p><p><code>COPY</code>和<code>ADD</code>都支持两种形式的写法：</p><pre><code>COPY src destCOPY ["src", "dest"]ADD src destADD ["src", "dest"]</code></pre><h2 id="RUN-amp-amp-CMD-amp-amp-ENTRYPOINT"><a href="#RUN-amp-amp-CMD-amp-amp-ENTRYPOINT" class="headerlink" title="RUN &amp;&amp; CMD &amp;&amp; ENTRYPOINT"></a>RUN &amp;&amp; CMD &amp;&amp; ENTRYPOINT</h2><p><code>RUN</code>指定的命令在<code>docker build</code>构建镜像的时候执行。可以有多个<code>RUN</code>指令，且每个都生效。</p><p><code>CMD</code>指定的命令在容器启动时执行。可以有多个<code>CMD</code>指令，但只有最后一个生效。<code>CMD</code>指定的命令会被<code>docker run</code>之后的参数替换。</p><p><code>ENTRYPOINT</code>指定的命令在容器启动时执行。可以有多个<code>ENTRYPOINT</code>指令，但只有最后一个生效。<code>CMD</code>或<code>docker run</code>之后的参数会被当做参数传递给<code>ENTRYPOINT</code>。<code>ENTRYPOINT</code>命令一定会执行。</p><p><code>RUN</code>、<code>CMD</code>和<code>ENTRYPOINT</code>都支持两种形式的写法：</p><h3 id="Shell-格式"><a href="#Shell-格式" class="headerlink" title="Shell 格式"></a>Shell 格式</h3><figure class="highlight sh"><figcaption><span>Shell 格式</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;instruction&gt; &lt;<span class="built_in">command</span>&gt;</span><br></pre></td></tr></tbody></table></figure><p>当指令执行时，<code>Shell</code>格式的写法底层会调用<code>/bin/sh -c &lt;command&gt;</code>。</p><p>如：</p><pre><code>ENV WORLD worldENTRYPOINT echo "Hello $WORLD"</code></pre><p>执行<code>docker run &lt;image&gt;</code>将输出：<code>Hello world</code>。</p><h3 id="Exec-格式"><a href="#Exec-格式" class="headerlink" title="Exec 格式"></a>Exec 格式</h3><figure class="highlight sh"><figcaption><span>Exec 格式</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;instruction&gt; [<span class="string">"executable"</span>, <span class="string">"param1"</span>, <span class="string">"param2"</span>, ...]</span><br></pre></td></tr></tbody></table></figure><p>当指令执行时，<code>Exec</code>格式的写法会直接调用<code>&lt;command&gt;</code>，不会被<code>shell</code>解析。</p><p>如：</p><pre><code>ENV WORLD worldENTRYPOINT ["/bin/echo", "Hello $WORLD"]</code></pre><p>执行<code>docker run &lt;image&gt;</code>将输出：<code>Hello $WORLD</code>。</p><p>注意环境变量<code>WORLD</code>没有被替换。如果希望环境变量被替换，修改为：</p><pre><code>ENV WORLD worldENTRYPOINT ["/bin/sh", "-c", "echo Hello $WORLD"]</code></pre><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><p><a href="https://mp.weixin.qq.com/s?__biz=MzIwMTM5MjUwMg==&amp;mid=2653587610&amp;idx=1&amp;sn=fc2c45c4eb11ecc20d6bba50cc7b8cad&amp;chksm=8d308083ba470995f3e784386f4d09859fa7bdf93b0772d1b03669dd7612c818c6280f7f6b00&amp;scene=21#wechat_redirect">Dockerfile 常用指令 - 每天5分钟玩转 Docker 容器技术（16）</a></p><p><a href="https://mp.weixin.qq.com/s?__biz=MzIwMTM5MjUwMg==&amp;mid=2653587614&amp;idx=1&amp;sn=2070e193da6b71861052e393eccae055&amp;chksm=8d308087ba4709915514e06e73bba8a93fca5510f910552a8290e9a1b4ae111d7a3fd230c0a5&amp;scene=21#wechat_redirect">RUN vs CMD vs ENTRYPOINT - 每天5分钟玩转 Docker 容器技术（17）</a></p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/categories/Docker/"/>
    
    
    <category term="Docker" scheme="https://blog.wpz.homes/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>使用 nohup 和 &amp; 让命令在后台执行</title>
    <link href="https://blog.wpz.homes/posts/8777e763/"/>
    <id>https://blog.wpz.homes/posts/8777e763/</id>
    <published>2019-04-23T03:32:34.000Z</published>
    <updated>2026-09-20T09:12:05.372Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h2 id="amp"><a href="#amp" class="headerlink" title="&amp;"></a>&amp;</h2><p>在终端执行命令，如果想让命令在后台执行，不占用终端窗口，可以在该命令后面加上<code>&amp;</code>。<code>&amp;</code>可以把这个命令转换为后台运行的任务进程：</p><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">command</span> &amp;</span><br></pre></td></tr></tbody></table></figure><p>不过，虽然进程在后台运行了，但进程运行中输出的日志一样会打印到终端窗口上。如果不想终端窗口产生大量输出，我们可以将这些输出重定向到某个文件中：</p><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">command</span> &gt; out.file 2&gt;&amp;1 &amp;</span><br></pre></td></tr></tbody></table></figure><p>这样，所有的标准输出和错误输出都将被重定向到<code>out.file</code>文件中。</p><p>使用<code>&amp;</code>将命令转换为后台运行的任务进程时有两点需要了解下：</p><div class="note danger">    <p>        1. 命令转换为后台任务进程执行时，会返回该进程的 ID。有了 ID 我们就能对该进程进行操作了，如：结束进程。<br>        2. 一旦执行该命令的终端窗口关闭了，后台运行的任务进程也会随之停止。换句话说，执行该命令的终端窗口不能关闭，除非你不想让后台任务进程继续运行了。    </p></div><h2 id="nohup"><a href="#nohup" class="headerlink" title="nohup"></a>nohup</h2><p>在前面介绍<code>&amp;</code>的使用时我们知道，一旦运行<code>&amp;</code>命令的终端窗口关闭了，后台运行的任务进程也会随之停止。这显然不是我们想要的，这时<code>nohup</code>就派上用场了。<code>nohup</code>命令可以使终端窗口关闭后，后台任务进程继续运行。<code>nohup</code>是<code>no hang up</code>的缩写，意思是不挂起。常与<code>&amp;</code>一同使用，该命令的一般形式为:</p><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">nohup</span> <span class="built_in">command</span> &amp;</span><br></pre></td></tr></tbody></table></figure><p>执行完上面命令后，会在当前目录下生成一个名为<code>nohup.out</code>的文件，后台进程的所有输出都被重定向到该文件下。如果当前目录下的<code>nohup.out</code>文件不可写(用户没有写权限)，则输出重定向到<code>$HOME/nohup.out</code>文件中，如果<code>$HOME/nohup.out</code>文件也不可写，则<code>nohup</code>命令会执行失败。</p><p>当然，我们也可以自定义输出重定向：</p><figure class="highlight sh"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">nohup</span> <span class="built_in">command</span> &gt; out.file 2&gt;&amp;1 &amp;</span><br></pre></td></tr></tbody></table></figure><h2 id="不是所有命令都适合在后台运行"><a href="#不是所有命令都适合在后台运行" class="headerlink" title="不是所有命令都适合在后台运行"></a>不是所有命令都适合在后台运行</h2><p>不是所有命令都适合在后台运行，比如：需要用户交互的命令不要放在后台执行。因为程序在后台运行，用户并不知道需要输入，程序执行到需要用户交互的地方时就会一直傻等在那里。</p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Linux/Unix" scheme="https://blog.wpz.homes/categories/Linux-Unix/"/>
    
    
    <category term="nohup" scheme="https://blog.wpz.homes/tags/nohup/"/>
    
  </entry>
  
  <entry>
    <title>Crontab 定时任务</title>
    <link href="https://blog.wpz.homes/posts/f189e9a9/"/>
    <id>https://blog.wpz.homes/posts/f189e9a9/</id>
    <published>2019-04-23T02:22:48.000Z</published>
    <updated>2026-09-20T09:12:05.370Z</updated>
    
    <content type="html"><![CDATA[<p><span></span></p><span id="more"></span><h1 id="crontab"><a href="#crontab" class="headerlink" title="crontab"></a>crontab</h1><p><code>crontab</code>命令常见于<code>Unix</code>和类<code>Unix</code>的操作系统之中，用于设置周期性被执行的指令。该命令从标准输入设备读取指令，并将其存放于<code>crontab</code>文件中，以供之后读取和执行。该词来源于希腊语<code>chronos(χρνο)</code>，原意是时间。通常，<code>crontab</code>储存的指令被守护进程激活，<code>crond</code>常常在后台运行，每一分钟检查是否有预定的作业需要执行。这类作业一般称为<code>cron jobs</code>。</p><h1 id="etc-目录下的几个-cron-目录"><a href="#etc-目录下的几个-cron-目录" class="headerlink" title="/etc 目录下的几个 cron 目录"></a>/etc 目录下的几个 cron 目录</h1><p><code>/etc</code>目录主要用来存放系统中的配置文件，基本上所有的配置文件都可以在这里找到。运行以下命令查看：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">ls</span> /etc/cron*</span><br></pre></td></tr></tbody></table></figure><p>这个命令会列出<code>/etc</code>目录下所有以cron开头的文件和文件夹。可以看到主要有以下文件夹：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">/etc/cron.hourly  # 这里存放了每小时需要运行的脚本</span><br><span class="line">/etc/cron.daily  # 这里存放了每天需要运行的脚本</span><br><span class="line">/etc/cron.weekly  # 这里存放了每个星期需要运行的脚本</span><br><span class="line">/etc/cron.monthly  # 这里存放了每月需要运行的脚本</span><br><span class="line">/etc/cron.d  # 如果既不是按小时，也不按天，周和月来运行，就放在这个文件夹</span><br></pre></td></tr></tbody></table></figure><p>我们可以把我们需要定时运行的脚本放到对应的文件夹中，系统就会定时运行对应的脚本了。那么系统是怎么做到的呢？</p><p>除了上面几个文件夹外，在<code>/etc</code>目录下，还有一个<code>crontab</code>文件，该文件内容如下：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"># /etc/crontab: system-wide crontab</span><br><span class="line"># Unlike any other crontab you don't have to run the `crontab'</span><br><span class="line"># command to install the new version when you edit this file</span><br><span class="line"># and files in /etc/cron.d. These files also have username fields,</span><br><span class="line"># that none of the other crontabs do.</span><br><span class="line"></span><br><span class="line">SHELL=/bin/sh</span><br><span class="line">PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin</span><br><span class="line"></span><br><span class="line"># m h dom mon dow usercommand</span><br><span class="line">17 ** * *root    cd / &amp;&amp; run-parts --report /etc/cron.hourly</span><br><span class="line">25 6* * *roottest -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.daily )</span><br><span class="line">47 6* * 7roottest -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.weekly )</span><br><span class="line">52 61 * *roottest -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.monthly )</span><br><span class="line">#</span><br></pre></td></tr></tbody></table></figure><p><code>crontab</code>文件是一个系统级别的配置文件，里面配置了什么时候去运行什么文件的规则。Linux会定期去扫描对应的文件夹，运行里面的脚本。这就完成了定时执行任务的功能。</p><h1 id="cron服务"><a href="#cron服务" class="headerlink" title="cron服务"></a>cron服务</h1><p>cron是一个linux下的定时执行工具，可以在无需人工干预的情况下运行作业。由于cron 是Linux的内置服务，但它不自动起来，可以用以下的方法启动、关闭这个服务：</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">service cron start  <span class="comment"># 启动服务</span></span><br><span class="line">service cron stop  <span class="comment"># 关闭服务</span></span><br><span class="line">service cron restart  <span class="comment"># 重启服务</span></span><br><span class="line">service cron reload  <span class="comment"># 重新载入配置</span></span><br></pre></td></tr></tbody></table></figure><p>cron命令每分钟会定期检查是否有要执行的工作，如果有要执行的工作便会自动执行该工作。而Linux任务调度的工作主要分为以下两类：</p><ul><li>系统执行的工作：系统周期性所要执行的工作，如备份系统数据、清理缓存；</li><li>个人执行的工作：某个用户定期要做的工作，例如每天备份数据库等。</li></ul><p>在<code>/var/spool/cron/</code>目录下是所有用户的crontab文件，你也可以去看看。上面说到的/etc下的配置都是属于系统级别的，那么个人级别的定时执行如何来做呢？这就需要说到下面的<code>crontab</code>命令了。</p><h1 id="crontab命令"><a href="#crontab命令" class="headerlink" title="crontab命令"></a>crontab命令</h1><p>cron服务提供crontab命令来设定cron服务的，以下是这个命令的一些参数与说明：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">crontab -u //设定某个用户的cron服务，一般root用户在执行这个命令的时候需要此参数</span><br><span class="line">crontab -l //列出某个用户cron服务的详细内容</span><br><span class="line">crontab -r //删除没个用户的cron服务</span><br><span class="line">crontab -e //编辑某个用户的cron服务</span><br></pre></td></tr></tbody></table></figure><p>如果不指定用户，就是当前系统的登陆用户。</p><p>当你输入命令：<code>crontab -e</code>时，就会出现一个文件，让你填写对应的定时规则，这个规则是什么？</p><h1 id="定时规则"><a href="#定时规则" class="headerlink" title="定时规则"></a>定时规则</h1><p>看这条规则：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / &amp;&amp; run-parts --report /etc/cron.daily )</span><br></pre></td></tr></tbody></table></figure><p>这就是一条规则，表示每天的6点25分执行对应的脚本。没有看明白，不要紧，容我慢慢道来。</p><p>以下是 crontab 文件的格式：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{minute} {hour} {day-of-month} {month} {day-of-week} {full-path-to-shell-script}</span><br></pre></td></tr></tbody></table></figure><ul><li>minute：区间为0–59；</li><li>hour：区间为0–23；</li><li>day-of-month：区间为0–31；</li><li>month：区间为1–12；1是1月，12是12月；</li><li>Day-of-week：区间为0–6；周日是0。</li></ul><p>除了数字还有以下几个特殊的符号需要特殊说明：<br><code>*</code>：代表所有的取值范围内的数字；<br><code>/</code>：代表每的意思，”*/5″表示每5个单位；<br><code>-</code>：代表从某个数字到某个数字；<br><code>,</code>：分开几个离散的数字。</p><p>以下举几个例子说明问题：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">每五分钟执行    */5 * * * * /home/jelly/test.sh</span><br><span class="line">每小时执行      0 * * * * /home/jelly/test.sh</span><br><span class="line">每天执行        0 0 * * * /home/jelly/test.sh</span><br><span class="line">每周执行        0 0 * * 0 /home/jelly/test.sh</span><br><span class="line">每月执行        0 0 1 * * /home/jelly/test.sh</span><br><span class="line">每年执行        0 0 1 1 * /home/jelly/test.sh</span><br><span class="line"></span><br><span class="line">每天早上6点     0 6 * * * /home/jelly/test.sh</span><br><span class="line">每两个小时      0 */2 * * * /home/jelly/test.sh</span><br><span class="line"></span><br><span class="line">晚上11点到早上8点之间每两个小时</span><br><span class="line">0 23-7/2 * * * /home/jelly/test.sh</span><br><span class="line"></span><br><span class="line">1月1日早上4点</span><br><span class="line">0 4 1 1 * /home/jelly/test.sh</span><br></pre></td></tr></tbody></table></figure><p>我想这下你应该明白了，如果还没有明白，没问题，再来个实例，你就能明白了。</p><h1 id="一个小Demo"><a href="#一个小Demo" class="headerlink" title="一个小Demo"></a>一个小Demo</h1><p>先准备以下这么一段简短的脚本：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line"></span><br><span class="line">var="http://www.jellythink.com"</span><br><span class="line"></span><br><span class="line">echo $var</span><br><span class="line"></span><br><span class="line">exit 0</span><br></pre></td></tr></tbody></table></figure><p>保存为文件backupDemo.sh。<br>bash脚本不懂，没关系，看这里：</p><ul><li>《<a href="https://www.jellythink.com/archives/123">Linux Shell简明教程（一）</a>》</li><li>《<a href="https://www.jellythink.com/archives/126">Linux Shell简明教程（二）</a>》</li></ul><p>在终端输入以下命令：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">crontab -e</span><br></pre></td></tr></tbody></table></figure><p>在显示的文件末尾添加以下规则：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">*/1 * * * * /home/jelly/MySource/Shell/backupDemo.sh &gt;&gt; /home/jelly/log.log</span><br></pre></td></tr></tbody></table></figure><p>编辑完成，保存完成以后，就会显示以下提示信息：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">crontab: installing new crontab</span><br></pre></td></tr></tbody></table></figure><p>这就说明正在安装新的定时任务，如果没有这条提示信息，请重新运行<code>crontab -e</code>命令。</p><p>接下来就会看到在/home/jelly目录下会生成一个log.log文件，并写入了输入的信息。</p><p>没有问题，搞定了。</p><script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css">]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Linux/Unix" scheme="https://blog.wpz.homes/categories/Linux-Unix/"/>
    
    
    <category term="Crontab" scheme="https://blog.wpz.homes/tags/Crontab/"/>
    
  </entry>
  
</feed>
