LaTeX讲解系列(3):如何插入代码块/伪代码

LaTeX讲解系列(3): 如何插入代码块/伪代码

资料更新:用LaTeX优雅地书写伪代码——Algorithm2e简明指南

https://zhuanlan.zhihu.com/p/166418214

这篇网上找到的知乎讲的非常好,简明常用优雅~建议阅读

一、LaTex 插入代码块的方法

参考资料:overleaf官方文档(https://www.overleaf.com/learn/latex/Code_listing)

方法1 使用verbatim环境

1
2
3
\begin{verbatim}
% 插入你的代码
\end{verbatim}

但是这种方式插入的效果是最朴素的,没有代码高亮、关键字边框,字体大小和行间距调整等格式设置。就是朴素的单倍行距显示,比较丑陋。

方法2 使用listings环境进行优化

step-1 引入宏包 \usepackage{listings}, 颜色宏包\usepackage{xcolor}.

step-2 设置格式,下方通过宏定义的方式定义了mystyle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
\lstdefinestyle{mystyle}{
% backgroundcolor=\color{backcolour}, % 背景色
keywordstyle= \color{ blue!70}, % 关键字/程序语言中的保留字颜色
commentstyle= \color{red!50!green!50!blue!50}, % 程序中注释的颜色
% commentstyle= \color[RGB]{40, 400, 255}
numberstyle=\tiny\color{codegray}, % 左侧行号显示的颜色
stringstyle=\color{codepurple},
basicstyle=\ttfamily\footnotesize,
breakatwhitespace=false,
breaklines=true, % 对过长的代码自动换行
captionpos=b,
keepspaces=true,
numbers=left, % 在左侧显示行号
numbersep=5pt,
showspaces=false,
showstringspaces=false, % 不显示字符串中的空格
showtabs=false,
tabsize=2,
% frame=none, % 不显示边框
frame=shadowbox, % 边框阴影
% escapebegin=\begin{CJK*},escapeend=\end{CJK*}, % 代码中出现中文必须加上,否则报错
}

step -3 导入代码

可以从源文件导入,只需要一行命令如下:

1
\lstinputlisting[language=Python, style=mystyle ]{ReduceClass.py}

填写好语言项(languange=Python), 选择需要的格式(style=mystyle, 假如定义了多个style可以选择一个来用),最后在花括号里选择引用的代码文件。

也可以选择创建一个环境,如下:

1
2
3
\begin[languange=Python]{lstlisting}
% 代码块
\end{lstlisting}

二、LaTex中插入伪代码的方法

2.1 易出错的地方总结

  1. 注意换行的时候, 可以末尾用\;,或者多空一行,但是不要像写公式换行一行用// //只是段内增加一行,不会开启新一行的编号。往往太长了放不下的时候可以//,如果要写下一行code还是用上述前两种方法。

2.2 插入伪代码的方法

常用的伪代码宏包有algorithm, algorithm2e, algorithmic等等。那么如何选择使用呢?首先,如果有论文投稿计划的话,按照相关期刊/会议要求LaTex使用伪代码的规定使用哪些宏包;如果没有明确规定,那么怎么顺手怎么来。

algorithm宏包,支持简单的伪代码格式。

基本格式如下:

1
2
3
4
5
6
7
8
9
\begin{algorithm}[htbp]
\KwIn{XXX} % 算法输入
\KwOut{XXX} % 算法输出
\BlankLine
\caption{XXX} % 算法标题
\label{} % 定义该段算法的标签

%写伪代码
\end{algorithm}

algorithm算法环境中 \label{}尽量紧跟在\caption{}后面,而且五个命令的顺序尽可能和示例中一样,不然使用\cref{}时可能会出现奇怪的问题。

聪明的联网版GPT4o给的解释是:在 LaTeX 中,\label 的位置很重要,因为它引用的是最近的编号对象。如果 \label\caption 之前,可能会默认引用到前一个环境的编号或行号,导致错误。放在 \caption 后面可以确保它引用的是当前算法的编号。这样就能正确地使用 cleveref 进行引用。确保 \label 紧跟在产生编号的命令之后是个好习惯,以避免类似问题。

algorithm2e宏包

详细讲解强烈推荐这篇博客:https://blog.csdn.net/qq_43486745/article/details/124344365

部分内容从该博客里“借鉴”,结合本人一些实践经验补充。

Step-0 宏包参数使用

1
\usepackage[linesnumbered,ruled,vlined]{algorithm2e}
参数 作用
linesnumbered 显示行号
ruled 标题显示在上方,不加就默认显示在下方
vlined 代码段中用线连接
boxed 将算法插入在一个盒子里

如果遇到一篇文档里有多段伪代码,第二段伪代码的行号没有重新开始计数的情况时,可以采用如下办法(Powered by smart GPT4o):

  • 如果是在algorithm2e环境中,可以在每段伪代码前加入 \setcounter{AlgoLine}{0}
  • 如果是在algorithmic环境中,可以在每段伪代码前加入 \setcounter{ALC@line}{0}

step-1 包裹在algorithm环境中(同时也要有algorithm宏包)

1
\usepackage[vlined,ruled,linesnumbered]{algorithm2e}

step-2 For循环怎么写

1
2
3
\For{$i \leftarrow 1$ to $100$}{
XXX % 循环体内容
}

step-3 While循环怎么写

1
2
3
\While{a > 0}{
XXX % 循环体内容
}

step-4 If-else 判断语句

if...then...

1
\If{$i>1$}{$\operatorname{QuickSort}(A[1,\cdots,i-1])$}

if...then...else...

1
2
3
\eIf{$j$ is odd}{
if执行以及
}{else执行语句}

step-5 定义子函数

1
2
3
4
5
6
7
8
\SetKwFunction{FMain}{你定义的函数名,如gcd}
\SetKwProg{Fn}{Function}{:}{}
\Fn{\FMain{函数的参变量,如int a, int b}}{
XXX % 函数内容
}
\textbf{End Function}
...
c \leftarrow gcd(a, b) % 在某个地方调用

step-6 其他

代码 作用
; 行末添加行号并自动换行
插入算法名称
显示“Data:输入信息”
显示“Output:输出信息”
显示“Result:输出信息”
For循环
If条件判断
If-else判断语句
While循环
ForEach遍历
显示“* 注释 *”
显示“\注释”
显示“每个结尾的end”
显示行号

step-7 修改算法部分为中文

使用以下语句可将默认的“Algorithm”修改为中文“算法”

1
\renewcommand{\algorithmcfname}{算法}

修改Input、Output为中文

1
2
\SetKwInOut{KwIn}{输入}
\SetKwInOut{KwOut}{输出}

自定义算法编号

1
\renewcommand{\thealgocf}{3-1}

添加算法目录

1
2
3
\renewcommand{\listalgorithmcfname}{算\ \ \ 录}
% 生成算法目录命令
\listofalgorithms

e.g.1. 冒泡排序

效果图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
\begin{algorithm}[H]
\KwIn{An array $A[1,\dots,n]$}
\KwOut{$A$ sorted nondecreasingly}
\BlankLine
\caption{BubbleSort}\label{Alg-Bubble}

$i\leftarrow 1$; $sorted\leftarrow false$\;

\While{$i\leq n-1$ \textbf{and not} $sorted$}{
$sorted\leftarrow true$\;
\For{$j\leftarrow n $ \textbf{downto} $i+1$}{
\If{$A[j]<A[j-1]$}{
interchange $A[j]$ and $A[j-1]$\;
$sorted\leftarrow false$\;
}
}
$i\leftarrow i+1$\;
}
\end{algorithm}

e.g.2. 大数据分析中经典的AMS-F2估计算法(并使用Median Trick, Average Trick)

效果图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
\begin{algorithm}[H]
\KwIn{4-wise independent hash family $h$, stream $a_i \in [n]$, $\epsilon$, $\eta$, $\delta$}
\KwOut{$z^2$}
\BlankLine
\caption{AMS Scheme for $F_2$}

% 设置子函数
\SetKwFunction{FMain}{AMS-F2}
\SetKwProg{Fn}{Function}{:}{}
\Fn{\FMain{stream $a_i$, hash family $h(\cdot)$}}{
$ z \longleftarrow 0 $\;

\While{stream $a_i$ is not empty}{
$a_i$ is current item\;

$z \longleftarrow z + h(a_i)$\;
}

\textbf{return} $ z^2$
}
\textbf{End Function}

// apply average trick

$q \longleftarrow \lceil \frac{4}{\eta \epsilon^2} \rceil$\;

$sum_1 \longleftarrow 0$

\For{$j \leftarrow 1$ to $q$}{
$sum_1 \longleftarrow sum_1 +$ AMS-F2(stream $a_i$, $h(\cdot)$)
}

$avg \longleftarrow sum_1 / q$

//apply median trick

$s \longleftarrow \lceil \frac{3\eta^2}{(\frac{1}{2} - \eta)^2}\ln\frac{2}{\delta} \rceil$

create a empty set $\Phi$

\For{$j \leftarrow 1$ to $s$}{
Add the result of AMS-F2(stream $a_i$, $h(\cdot)$) into set $\Phi$
}

$med \longleftarrow$ the smallest median of $\Phi$

\Return{$avg$, $med$} \;
\end{algorithm}

algorithmic宏包

占个坑,以后填

(感觉这个宏包不太方便定义指令)


LaTeX讲解系列(3):如何插入代码块/伪代码
https://oier99.cn/posts/200e31c0/
作者
Oier99
发布于
2022年12月29日
许可协议