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

目录

摘要

其他布局的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的布局为例)

加入宏包

\usepackage{algorithm}  
\usepackage{algorithmicx}  
\usepackage{algpseudocode}

其他布局的package

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

常用的预定义命令集:

\usepackage<algpseudocode>
\usepackage<algcompatible>
\usepackage<algpascal>
\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}命令截至。

简单的一行

        算法每行文本以\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命令可引用给定算法的某一行。

例子:

\algref{<algorithm>}{<line>}

The \textbf{while} in algorithm
\ref{euclid} ends in line
\ref{euclidendwhile}, so
\algref{euclid}{euclidendwhile}
is the line we seek.

样式结果:

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

分解较长的算法

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

\algstore{<savename>} 
...
\algrestore{<savename>}

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

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

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

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

\algstore*{<savename>} 
...
\algrestore*{<savename>} 

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

同一文档中使用多布局

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

结构化语法

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

\begin{algorithm}
    \caption{Euclid’s algorithm}\label{euclid}
        \begin{algorithmic}[1]
\Procedure{Euclid}{$a,b$}\Comment{The g.c.d. of a and b}
    \State $r\gets a\bmod b$
\While{$r\not=0$}\Comment{We have the answer if r is 0}
    \State $a\gets b$
    \State $b\gets r$
    \State $r\gets a\bmod b$
\EndWhile\label{euclidendwhile}
    \State \textbf{return} $b$\Comment{The gcd is b}
\EndProcedure
        \end{algorithmic}
\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循环语句的几种样例如下:

\For{<text>}
    <body>
\EndFor

\ForAll{<text>}
    <body>
\EndFor

\begin{algorithmic}[1]
    \State $sum\gets 0$
\For{$i\gets 1, n$}
    \State $sum\gets sum+i$
\EndFor
\end{algorithmic}

while循环

\While{<text>}
    <body>
\EndWhile

\begin{algorithmic}[1]
    \State $sum\gets 0$
    \State $i\gets 1$
\While{$i\le n$}
    \State $sum\gets sum+i$
    \State $i\gets i+1$
\EndWhile
\end{algorithmic}

repeat语句

\Repeat
    <body>
\Until{<text>}

\begin{algorithmic}[1]
    \State $sum\gets 0$
    \State $i\gets 1$
\Repeat
    \State $sum\gets sum+i$
    \State $i\gets i+1$
\Until{$i>n$}
\end{algorithmic}

 if语句块

        得仔细看哈:

\If{<text>}
    <body>
[
  \ElsIf{<text>}
    <body>
...
]
[
  \Else
    <body>
]
\EndIf

\begin{algorithmic}[1]
\If{$quality\ge 9$}
    \State $a\gets perfect$
\ElsIf{$quality\ge 7$}
    \State $a\gets good$
\ElsIf{$quality\ge 5$}
    \State $a\gets medium$
\ElsIf{$quality\ge 3$}
    \State $a\gets bad$
\Else
    \State $a\gets unusable$
\EndIf
\end{algorithmic}

procedure语句块

\Procedure{<name>}{<params>}
    <body>
\EndProcedure

function语句块

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

\Function{<name>}{<params>}
    <body>
\EndFunction

loop语句块

\Loop
    <body>
\EndLoop

 输入输出语句

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

\Require something
\Ensure something
    \Statex
\State \Call{Create}{10}

\begin{algorithmic}[1]
\Require $x\ge5$
\Ensure $x\le-5$
    \Statex
\While{$x>-5$}
    \State $x\gets x-1$
\EndWhile
\end{algorithmic}

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

\renewcommand{\algorithmicrequire}{\textbf{Input:}}  % Use Input in the format of Algorithm  
\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>的形式存在。下面列出部分修改实例:

\algrenewcommand\algorithmicwhile{\textbf{am\’\i g}}
\algrenewcommand\algorithmicdo{\textbf{v\’egezd el}}
\algrenewcommand\algorithmicend{\textbf{v\’ege}}
\begin{algorithmic}[1]
    \State $x \gets 1$
\While{$x < 10$}
    \State $x \gets x + 1$
\EndWhile
\end{algorithmic}

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

\algrenewcommand\algorithmicwhile{\textbf{am\’\i g}}
\algrenewcommand\algorithmicdo{\textbf{v\’egezd el}}
\algrenewcommand\algorithmicend{\textbf{v\’ege}}
\algrenewtext{EndWhile}{\algorithmicwhile\ \algorithmicend}
\begin{algorithmic}[1]
    \State $x \gets 1$
\While{$x < 10$}
    \State $x \gets x - 1$
\EndWhile
\end{algorithmic}

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

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

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

示例

一份完整的伪代码

\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\begin{document}
\begin{algorithm}
\caption{The Bellman-Kalaba algorithm}
\begin{algorithmic}[1]
\Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
\ForAll {$v \in V(G)$}
    \State $l(v) \leftarrow \infty$
\EndFor
    \State $l(u) \leftarrow 0$
\Repeat
\For {$i \leftarrow 1, n$}
    \State $min \leftarrow l(v_i)$
\For {$j \leftarrow 1, n$}
\If {$min > e(v_i, v_j) + l(v_j)$}
    \State $min \leftarrow e(v_i, v_j) + l(v_j)$
    \State $p(i) \leftarrow v_j$
\EndIf
\EndFor
    \State $l’(i) \leftarrow min$
\EndFor
    \State $changed \leftarrow l \not= l’$
    \State $l \leftarrow l’$
\Until{$\neg changed$}
\EndProcedure
    \Statex
\Procedure {FindPathBK}{$v$, $u$, $p$}
\If {$v = u$}
    \State \textbf{Write} $v$
\Else
    \State $w \leftarrow v$
\While {$w \not= u$}
    \State \textbf{Write} $w$
    \State $w \leftarrow p(w)$
\EndWhile
\EndIf
\EndProcedure
\end{algorithmic}
\end{algorithm}
\end{document}

拆分算法的例子

\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\begin{document}
\begin{algorithm}
\caption{Part 1}
\begin{algorithmic}[1]
\Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
\ForAll {$v \in V(G)$}
    \State $l(v) \leftarrow \infty$
\EndFor
    \State $l(u) \leftarrow 0$
\Repeat
\For {$i \leftarrow 1, n$}
    \State $min \leftarrow l(v_i)$
\For {$j \leftarrow 1, n$}
\If {$min > e(v_i, v_j) + l(v_j)$}
    \State $min \leftarrow e(v_i, v_j) + l(v_j)$
    \State \Comment For some reason we need to break here!
\algstore{bkbreak}
\end{algorithmic}
\end{algorithm}

And we need to put some additional text between\dots

\begin{algorithm}[h]
\caption{Part 2}
\begin{algorithmic}[1]
\algrestore{bkbreak}
    \State $p(i) \leftarrow v_j$
\EndIf
\EndFor
    \State $l’(i) \leftarrow min$
\EndFor
    \State $changed \leftarrow l \not= l’$
    \State $l \leftarrow l’$
\Until{$\neg changed$}
\EndProcedure
\end{algorithmic}
\end{algorithm}
\end{document}

 混合编排

\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\usepackage{algpascal}
\begin{document}
\alglanguage{pseudocode}
\begin{algorithm}
\caption{A small pseudocode}
\begin{algorithmic}[1]
    \State $s \gets 0$
    \State $p \gets 0$
\For{$i \gets 1,\, 10$}
    \State $s \gets s + i$
    \State $p \gets p + s$
\EndFor
\end{algorithmic}
\end{algorithm}
\alglanguage{pascal}
\begin{algorithm}
\caption{The pascal version}
\begin{algorithmic}[1]
    \State $s := 0$
    \State $p := 0$
\For{i = 1}{10}
\Begin
    \State $s := s + i$
    \State $p := p + s$
\End
\end{algorithmic}
\end{algorithm}
\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博客

  • 39
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七月是你的谎言..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值