深圳幻海软件技术有限公司 欢迎您!

Latex 编写算法伪代码,基于algorithmicx包的使用说明(人工翻译自CTAN)

2023-04-02

目录摘要其他布局的package简介算法块简单的一行注释标签和引用分解较长的算法同一文档中使用多布局结构化语法for语句块while循环repeat语句 if语句块procedure语句块function语句块loop语句块 输入输出语句包选项 给变量另起名字示例一份完

目录

摘要

其他布局的package

简介

算法块

简单的一行

注释

标签和引用

分解较长的算法

同一文档中使用多布局

结构化语法

for语句块

while循环

repeat语句

 if语句块

procedure语句块

function语句块

loop语句块

 输入输出语句

包选项 

给变量另起名字

示例

一份完整的伪代码

拆分算法的例子

 混合编排

References


前排提醒:

        有基础且自学很快的同学请跳转至示例结构化语法这两部分!


mlgb,搜了一圈没啥看一眼就能用的伪代码文章。有的故事将一大堆,有的各种环境或者语法问题。自己翻译一个以后还能照着看。

algorithmic 、algorithm2e与algorithmicx的故事渊源就不再介绍,文末references中可以了解(有一些不兼容的报错得注意)

本文主要参考官方说明文档编写而成,顺序有变动:(非机翻)CTAN: Package algoridicxhttps://ctan.org/pkg/algorithmicx

摘要

        algorithmicx 包提供了许多定制的可能性算法布局。 我们可以使用其中一种预定义的布局如:pseudocode、pascal 和 c 等,可以自行修改,或者可以为特定的需求定义一个全新的布局。

使用方法:(本文以伪代码pseudocode的布局为例)

加入宏包

  1. \usepackage{algorithm}
  2. \usepackage{algorithmicx}
  3. \usepackage{algpseudocode}

其他布局的package

        algorithmicx 本身没有定义任何算法命令,但给出了一些宏来定义这样的命令集。 可以使用
algorithmicx定义自己的命令,或者使用其中一种预定义的命令集。

常用的预定义命令集:

  1. \usepackage<algpseudocode>
  2. \usepackage<algcompatible>
  3. \usepackage<algpascal>
  4. \usepackage<algc>

第一个是伪代码命令集,随后是类似于algorithmic的命令集,pascal语言和c语言的命令集。

第二个包的原文介绍是:it is fully compatible with the algorithmic package, it should
be used only in old documents.也就是与algorithmic完全兼容的包,但一般只用于“旧文档”??

简介

算法块

        每个算法以\begin{algorithmic}[lines]命令开始,选项[lines]控制对行标号,1代表对每行进行标号,n代表为n,2n,3n行编号,直到\end{algorithmic}

\begin{algorithmic}[lines]命令开始,选项[lines]控制对行标号,1代表对每行进行标号,n代表为n,2n,3n行编号,直到\end{algorithmic}
命令截至。

简单的一行

        算法每行文本以\State开始,这与algorithmc包有所不同。需要指出的是,不需要在这个包的关键字前使用\State,因为这些命令会自动地启用一行。

        特别地,如果需要启用不带标号的一行,也就是承接上一行,需要使用\Statex,它会跳入新的一行,且不对新行编号。

        我们对以\State开始的行称为statements。对\Statex所在行的引用视为引用(\Statex)前一个statements所在的行号。

注释

        注释以 \Comment命令开始,在algorithmicx包中,可以任意更改注释的样式,这一点不同于algorithmic包。例如改变\algorithmiccomment 宏定义:

\algrenewcommand{\algorithmiccomment}[1]{\hskip3em$\rightarrow$ #1}

会变成:

1: x ← x + 1 → Here is the new comment

这段语法我是不大懂的,猜测是将向左的箭头⬅改成了右箭头→。\hskip是用来创建水平空间的命令。

Tex命令可参考:

hskip - Tex命令 (vue5.com)http://www.vue5.com/tex_commands/hskip.html

标签和引用

        \label命令通常用于标记所在行。当使用\ref命令对行进行引用时,它将用行号对原文进行代替。

        当algorithmicx包和algorithm包联合使用时,将能够同时标记和引用算法和所在行。\algref命令可引用给定算法的某一行。

例子:

  1. \algref{<algorithm>}{<line>}
  2. The \textbf{while} in algorithm
  3. \ref{euclid} ends in line
  4. \ref{euclidendwhile}, so
  5. \algref{euclid}{euclidendwhile}
  6. is the line we seek.

样式结果:

  1. The while in algorithm 1 ends in line 7,
  2. so 1.7 is the line we seek.

分解较长的算法

        有时候一段较长的算法需要被分成几部分描述,每一部分都是相对独立的存在(原文是separate float)。我们可以使用以下语法对algorithm进行拆分:

  1. \algstore{<savename>}
  2. ...
  3. \algrestore{<savename>}

        上述语法通过自定义的savename保存算法原来的行号与所有标识。

        其中,\algstore{<savename>} 语法使用在需要保存的算法末尾之前,即在\end{algorithmc}与\end{algorithm}之前。每段被保存的算法必须有着后续!

        而后续的算法恰恰相反,\algrestore{<savename>}对具有相同<sabename>的语法段进行承接,它需要放在\begin{algorithmic}[options]这一行的后面。

        algorithmicx还提供带*号的另一种版本:

  1. \algstore*{<savename>}
  2. ...
  3. \algrestore*{<savename>}

        与上面不带*有所不同,带星号的版本可选择是否恢复\algrestore*之后的部分。一下子没看懂不用着急,示例中将对这部分进行展示。

同一文档中使用多布局

        我们能在同一文件中下载多种algorithmicx下的布局宏包。\alglanguage{<layoutname>}命令能够实现不同布局之间的转换。在\alglanguage{<layoutname>}之后,将开始启用<layoutname>这种语法的环境代替之前的语法环境。

结构化语法

        如果你对algorithmic package有一定了解的话,你会发现它们之间的转换非常简单。你可以使用旧的算法描述方式加上<algorithmic>布局, 新的算法描述则需要使用<algpseudocode>布局。下面以辗转相除法求解两数的最大公约数为例给出简单的算法模板:

  1. \begin{algorithm}
  2. \caption{Euclid’s algorithm}\label{euclid}
  3. \begin{algorithmic}[1]
  4. \Procedure{Euclid}{$a,b$}\Comment{The g.c.d. of a and b}
  5. \State $r\gets a\bmod b$
  6. \While{$r\not=0$}\Comment{We have the answer if r is 0}
  7. \State $a\gets b$
  8. \State $b\gets r$
  9. \State $r\gets a\bmod b$
  10. \EndWhile\label{euclidendwhile}
  11. \State \textbf{return} $b$\Comment{The gcd is b}
  12. \EndProcedure
  13. \end{algorithmic}
  14. \end{algorithm}

双栏下的效果: 

        \State在每句statement的开头,标志着新的一行的开始。\Procedure...\EndProcedure与\While...\EndWhile展示了绝大部分<algpseudocode>的语法规则。每段固定句式都有着开头与结尾,中继是正文,且关键字采用驼峰命名法。

        在正确编排语法后,将自动根据缩进源进行缩进,但作者提醒大家规范的语法缩进有利于错误的查找。

        突然来了一段我没太看懂的话:

In the case of syntax descriptions the text between < and > is symbolic,so if you type what you see on the left side, you will not get the algorithm on the right side. But if you replace the text between < > with a proper piece of algorithm, then you will probably get what you want. The parts between [ and ] are optional.

        可能是想强调转义字符和原字符的输入区别?<>中间的内容原样显示。然后说[ ]中间是可选的options。

for语句块

for循环语句的几种样例如下:

  1. \For{<text>}
  2. <body>
  3. \EndFor

  1. \ForAll{<text>}
  2. <body>
  3. \EndFor

  1. \begin{algorithmic}[1]
  2. \State $sum\gets 0$
  3. \For{$i\gets 1, n$}
  4. \State $sum\gets sum+i$
  5. \EndFor
  6. \end{algorithmic}

while循环

  1. \While{<text>}
  2. <body>
  3. \EndWhile

  1. \begin{algorithmic}[1]
  2. \State $sum\gets 0$
  3. \State $i\gets 1$
  4. \While{$i\le n$}
  5. \State $sum\gets sum+i$
  6. \State $i\gets i+1$
  7. \EndWhile
  8. \end{algorithmic}

repeat语句

  1. \Repeat
  2. <body>
  3. \Until{<text>}

  1. \begin{algorithmic}[1]
  2. \State $sum\gets 0$
  3. \State $i\gets 1$
  4. \Repeat
  5. \State $sum\gets sum+i$
  6. \State $i\gets i+1$
  7. \Until{$i>n$}
  8. \end{algorithmic}

 if语句块

        得仔细看哈:

  1. \If{<text>}
  2. <body>
  3. [
  4. \ElsIf{<text>}
  5. <body>
  6. ...
  7. ]
  8. [
  9. \Else
  10. <body>
  11. ]
  12. \EndIf

  1. \begin{algorithmic}[1]
  2. \If{$quality\ge 9$}
  3. \State $a\gets perfect$
  4. \ElsIf{$quality\ge 7$}
  5. \State $a\gets good$
  6. \ElsIf{$quality\ge 5$}
  7. \State $a\gets medium$
  8. \ElsIf{$quality\ge 3$}
  9. \State $a\gets bad$
  10. \Else
  11. \State $a\gets unusable$
  12. \EndIf
  13. \end{algorithmic}

procedure语句块

  1. \Procedure{<name>}{<params>}
  2. <body>
  3. \EndProcedure

function语句块

        function语句块与上面的procedure类似:

  1. \Function{<name>}{<params>}
  2. <body>
  3. \EndFunction

loop语句块

  1. \Loop
  2. <body>
  3. \EndLoop

 输入输出语句

        算法的需求参数可以用 \Require 指令描述,结果可用\Ensure 指令描述。调用可用 \Call 指令。

  1. \Require something
  2. \Ensure something
  3. \Statex
  4. \State \Call{Create}{10}

  1. \begin{algorithmic}[1]
  2. \Require $x\ge5$
  3. \Ensure $x\le-5$
  4. \Statex
  5. \While{$x>-5$}
  6. \State $x\gets x-1$
  7. \EndWhile
  8. \end{algorithmic}

        此外,可用以下语句改写成input与output的形式:

  1. \renewcommand{\algorithmicrequire}{\textbf{Input:}} % Use Input in the format of Algorithm
  2. \renewcommand{\algorithmicensure}{\textbf{Output:}} % Use Output in the format of Algorithm

包选项 

<algpseudocode> package 支持以下选项:

compatible/noncompatible:

        这个选项貌似被淘汰了,作者说如果你像使用旧的算法描述,请使用<algorithmic> package,然后使用<compatible>选项。这个选项定义了大写版本的命令,其实<algorithmic>与<algorithmicx>主要区别就是关键字的命名方法了,一个是全大写,一个是驼峰法。

        此外,作者还提醒读者需要删除注释:[...],这大概是一些版本迭代和不兼容的原故吧。

noend/end:

        默认选项为end,意思会显示所有的end。noend则意味着文中不会出现end,作者还提醒我们没有end可能会不好看。

有无end的比照:

         网友还给出了去除如EndWhile这样单一end的方法,具体见文末第三篇参考。

给变量另起名字

        不同的人可能使用到不同的伪代码语言,所以给伪代码中的关键字另起名字就变得很重要了。

在<algpseudocode>包中,所有的关键字都以\algorithmic<keyword>的形式存在。下面列出部分修改实例:

  1. \algrenewcommand\algorithmicwhile{\textbf{am\’\i g}}
  2. \algrenewcommand\algorithmicdo{\textbf{v\’egezd el}}
  3. \algrenewcommand\algorithmicend{\textbf{v\’ege}}
  4. \begin{algorithmic}[1]
  5. \State $x \gets 1$
  6. \While{$x < 10$}
  7. \State $x \gets x + 1$
  8. \EndWhile
  9. \end{algorithmic}

        在某些复杂的情况下,可能需要更多的自由更改的空间(比如上面的End与While需要对调,就是那两个看不懂的词)。有时候,命令所需要的参数可能也需要改变,这都可以通过自定义宏来完成。接下来展示一些常用的例子:

  1. \algrenewcommand\algorithmicwhile{\textbf{am\’\i g}}
  2. \algrenewcommand\algorithmicdo{\textbf{v\’egezd el}}
  3. \algrenewcommand\algorithmicend{\textbf{v\’ege}}
  4. \algrenewtext{EndWhile}{\algorithmicwhile\ \algorithmicend}
  5. \begin{algorithmic}[1]
  6. \State $x \gets 1$
  7. \While{$x < 10$}
  8. \State $x \gets x - 1$
  9. \EndWhile
  10. \end{algorithmic}

         调转了上面的End和While,得细心对比哦

  1. \algnewcommand\algorithmicto{\textbf{to}}
  2. \algrenewtext{For}[3]%
  3. {\algorithmicfor\ #1 \gets #2 \algorithmicto\ #3 \algorithmicdo}
  4. \begin{algorithmic}[1]
  5. \State $p \gets 1$
  6. \For{i}{1}{n}
  7. \State $p \gets p * i$
  8. \EndFor
  9. \end{algorithmic}

         关于自定义命令的详细讲解留在下篇文章吧,这儿留个坑..文档在这个地方还介绍了pascal的算法伪代码,我就不翻译了。

示例

一份完整的伪代码

  1. \documentclass{article}
  2. \usepackage{algorithm}
  3. \usepackage{algpseudocode}
  4. \begin{document}
  5. \begin{algorithm}
  6. \caption{The Bellman-Kalaba algorithm}
  7. \begin{algorithmic}[1]
  8. \Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
  9. \ForAll {$v \in V(G)$}
  10. \State $l(v) \leftarrow \infty$
  11. \EndFor
  12. \State $l(u) \leftarrow 0$
  13. \Repeat
  14. \For {$i \leftarrow 1, n$}
  15. \State $min \leftarrow l(v_i)$
  16. \For {$j \leftarrow 1, n$}
  17. \If {$min > e(v_i, v_j) + l(v_j)$}
  18. \State $min \leftarrow e(v_i, v_j) + l(v_j)$
  19. \State $p(i) \leftarrow v_j$
  20. \EndIf
  21. \EndFor
  22. \State $l’(i) \leftarrow min$
  23. \EndFor
  24. \State $changed \leftarrow l \not= l’$
  25. \State $l \leftarrow l’$
  26. \Until{$\neg changed$}
  27. \EndProcedure
  28. \Statex
  29. \Procedure {FindPathBK}{$v$, $u$, $p$}
  30. \If {$v = u$}
  31. \State \textbf{Write} $v$
  32. \Else
  33. \State $w \leftarrow v$
  34. \While {$w \not= u$}
  35. \State \textbf{Write} $w$
  36. \State $w \leftarrow p(w)$
  37. \EndWhile
  38. \EndIf
  39. \EndProcedure
  40. \end{algorithmic}
  41. \end{algorithm}
  42. \end{document}

拆分算法的例子

  1. \documentclass{article}
  2. \usepackage{algorithm}
  3. \usepackage{algpseudocode}
  4. \begin{document}
  5. \begin{algorithm}
  6. \caption{Part 1}
  7. \begin{algorithmic}[1]
  8. \Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
  9. \ForAll {$v \in V(G)$}
  10. \State $l(v) \leftarrow \infty$
  11. \EndFor
  12. \State $l(u) \leftarrow 0$
  13. \Repeat
  14. \For {$i \leftarrow 1, n$}
  15. \State $min \leftarrow l(v_i)$
  16. \For {$j \leftarrow 1, n$}
  17. \If {$min > e(v_i, v_j) + l(v_j)$}
  18. \State $min \leftarrow e(v_i, v_j) + l(v_j)$
  19. \State \Comment For some reason we need to break here!
  20. \algstore{bkbreak}
  21. \end{algorithmic}
  22. \end{algorithm}
  23. And we need to put some additional text between\dots
  24. \begin{algorithm}[h]
  25. \caption{Part 2}
  26. \begin{algorithmic}[1]
  27. \algrestore{bkbreak}
  28. \State $p(i) \leftarrow v_j$
  29. \EndIf
  30. \EndFor
  31. \State $l’(i) \leftarrow min$
  32. \EndFor
  33. \State $changed \leftarrow l \not= l’$
  34. \State $l \leftarrow l’$
  35. \Until{$\neg changed$}
  36. \EndProcedure
  37. \end{algorithmic}
  38. \end{algorithm}
  39. \end{document}

 混合编排

  1. \documentclass{article}
  2. \usepackage{algorithm}
  3. \usepackage{algpseudocode}
  4. \usepackage{algpascal}
  5. \begin{document}
  6. \alglanguage{pseudocode}
  7. \begin{algorithm}
  8. \caption{A small pseudocode}
  9. \begin{algorithmic}[1]
  10. \State $s \gets 0$
  11. \State $p \gets 0$
  12. \For{$i \gets 1,\, 10$}
  13. \State $s \gets s + i$
  14. \State $p \gets p + s$
  15. \EndFor
  16. \end{algorithmic}
  17. \end{algorithm}
  18. \alglanguage{pascal}
  19. \begin{algorithm}
  20. \caption{The pascal version}
  21. \begin{algorithmic}[1]
  22. \State $s := 0$
  23. \State $p := 0$
  24. \For{i = 1}{10}
  25. \Begin
  26. \State $s := s + i$
  27. \State $p := p + s$
  28. \End
  29. \end{algorithmic}
  30. \end{algorithm}
  31. \end{document}

References

latex 小白 algorithmic already defined的原因 - it610.com

LaTex伪代码手册 | algorithm2e、 algorithmicx、algorithmic - 知乎 (zhihu.com)

(176条消息) latex algpseudocode 不要 end 块 | noend | no end | without end_pineappleKID的博客-CSDN博客

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览42750 人正在系统学习中