编写算法的良好做法


22

这是关于我们如何有效地表达手头的算法。我的本科教学需要这个。

我了解没有编写伪代码的标准方法。不同的作者遵循不同的约定。

如果这里的人们指出他们遵循和思考最佳方法的方式,那将是有帮助的。

是否有任何书籍对此进行了详细介绍?


9
“最佳”是非常主观的,我认为您应该修改标题,而不是要求“最佳”询问人们在实践中做什么。也许像“如何展示算法”或“展示算法的良好做法”之类的东西。通过介绍算法,您可能还需要更具体:1.针对本科班的学生2.教科书3.会议论文中的任务非常不同。
卡夫

1
您可能还需要检查Knuth,Larrabee和Roberts 的“ 数学写作”的相关部分。
卡夫

Answers:


26

编写伪代码就像编写代码:遵循哪个标准并不特别重要,只要您(以及与您一起编写代码的人)实际上遵循某个标准即可。

但是为了记录,这是我在讲义,研究论文和新书中使用的特质标准。

  • 使用标准命令式语法进行控制流和内存访问-如果返回,则返回array [index],function(arguments)。拼写“否则”。

    • 但使用代替或F一世Ëd[RËCØ[Rdrecord.fieldrecord->field
  • 使用标准的数学符号的数学-写代替,一个MOD b代替,小号牛逼的不是,¬ p代替,Xÿx*y一种ba%bsŤs <= t¬p!p代替,π代替,代替,等等。Xsqrt(x)πPIMAX_INT

    • 但是请使用进行分配,以避免出现此问题。Xÿ==

    • 但是,如果英语更清晰,请完全避免使用符号(和伪代码!)。

      • 对称地,如果符号更清晰,请避免使用英语!
  • 最小化语法糖—通过一致的缩进来表示块结构(如Python)。省略含糖关键字,例如“开始/结束”或“执行/结束”或“ fi”。省略行号。难道不是强调关键字,如“for”或“while”或“如果”通过在不同设置它们typeface风格。曾经 只是不要。

    • 但是在\ textsc {Small Caps}中排版算法的名称和常量,在斜体中使用变量名,在Sans Serif中使用文字字符串。

    • 但是\\[0.5ex]在有意义的代码块之间添加少量垂直“呼吸”空间()。

  • 不要指定不重要的细节。如果您访问顶点的顺序无关紧要,只需说“对于所有顶点”。

例如,这是Borůvka的最小生成树算法的递归公式。我之前将定义为通过收缩集合L中的所有边而从G获得的图,并将Flatten作为删除循环和平行边的子例程。G/大号G大号

Borůvka算法

我使用自己的轻量级algorithmLaTeX环境排版伪代码。(这只是一个tabbing内部的环境\fbox。)这是我的Borůvka算法的源代码:

\begin{algorithm}
	\textul{$\textsc{Borůvka}(G)$:}\+
\\	if $G$ has no edges\+
\\		return $\varnothing$\-
\\[0.5ex]
	$L \gets \varnothing$
\\	for each vertex $v$ of $G$\+
\\		add the lightest edge incident to $v$ to $L$\-
\\[0.5ex]
	return $L \cup \textsc{Borůvka}(\textsc{Flatten}(G / L))$
\end{algorithm}

有趣的是,您使用field(record)而不是record [field]。我想这就是“ Ĵ 牛逼^ h的坐标v ”对世界的看法?FĴvĴŤHv
Suresh Venkat

@SureshVenkat:这是您通常使用函数式语言以及TAoCP中的符号表示的方式。(显然,我不知道这就是Jɛff E使用此表示法的原因。)
Radu GRIGore 2011年

5
伪代码要小心的主要原因是,对于算法很容易感到困惑,因此强调一些内容很重要。Jeff在Boruvka上面的示例说明了这一点。在代码L中被视为一组。边uv可以是入射到u以及v的最轻的边,因此它在循环中被添加了两次,但是如果您将L视为集合则没关系。但是,这并不明显,如果将L实现为列表,则可以很容易地实现此功能。
Chandra Chekuri 2011年

2
@ChandraChekuri:是的,错误地实现集合会导致操纵集合的算法出现问题。
杰夫·杰西斯2011年

1
@SureshVenkat:哦,那。不,我受不了。粗体的关键字会使婴儿耶稣哭泣。迪克斯特拉(Dijkstra)应该因引入这种可执行的印刷惯例而失去图灵奖。
Jeffε

11

我倾向于使用类似于Python语法的内容。Python已经足够接近伪代码了,以至于在某些情况下我的伪代码可以变成实际的工作代码。


我也是,但在Ruby中。使用github gist,您可以轻松共享可执行代码片段,以供他们使用。gist.github.com/chadbrewbaker/7202412
乍得·布鲁贝克

但是,Python不能很好地表示线性代数。我认为在这种情况下,八度音阶更适合(更接近伪代码)。
令人惊讶的2015年

3

如果您要使用确定的代码(即几乎没有数学,几乎等于实际编程),则可能需要考虑使用实际编译的代码。这有几个优点:

  • 您到处都有语法高亮显示。
  • 编译器会为您检查语法并加强一致性。
  • 您可以对实现进行单元测试以提高代码质量。
  • 您可以运行算法,并将测得的运行时间与分析进行比较(因此可以激发高级分析技术)。

我大学的一位教授在其算法课程中做到了这一点。他选择的语言是Modula。不过,我认为语言的特定选择并不重要。只要坚持最适合您抽象水平的一种(每个范例)即可。


“只要坚持一个最适合您抽象水平的(每个范例)即可。” 我认为这是找到伪代码替代方法的好建议。语言种类繁多,几乎总是有至少一种针对特定范式的简单语法:Ada用于并发设计,Octave用于线性代数,Python用于程序,NetLogo用于多智能体系统,Prolog用于逻辑,CLIPS用于基于规则的编程等
令人惊讶的是

@gaborous如果您拥有可读的抽象代码,那就去吧。不幸的是,我怀疑这将使您在任何较大的工作量中至少使用三种语言。那也是不幸的。
拉斐尔2015年

我当然同意较大的代码没有语言,但是对于较小的核心算法,通常可以找到一种非常接近伪代码的语言。
令人惊讶的2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.