diff --git a/datastruct/elementary/sequence/sequence-zh-cn.tex b/datastruct/elementary/sequence/sequence-zh-cn.tex index 78659c75e..3eca100e4 100644 --- a/datastruct/elementary/sequence/sequence-zh-cn.tex +++ b/datastruct/elementary/sequence/sequence-zh-cn.tex @@ -325,7 +325,7 @@ \section{数字表示} \section{双数组序列} \index{序列!双数组序列} \index{双数组列表!插入和添加} -我们把\cref{sec:paired-array-queue}中的双数组队列扩展为双数组序列。如\cref{fig:parrays},按头对头的方式连接两个数组。在列表的头部插入时,添加到$f$数组末尾;向尾部插入时,添加到$r$数组末尾。用一对数组表示列表$S = (f, r)$,令$\textproc{Front}(S) = f$,$\textproc{Rear}(S) = r$。前后插入实现如下: +我们把\ref{sec:paired-array-queue}中的双数组队列扩展为双数组序列。如\cref{fig:parrays},按头对头的方式连接两个数组。在列表的头部插入时,添加到$f$数组末尾;向尾部插入时,添加到$r$数组末尾。用一对数组表示列表$S = (f, r)$,令$\textproc{Front}(S) = f$,$\textproc{Rear}(S) = r$。前后插入实现如下: \begin{figure}[htbp] \centering @@ -430,7 +430,7 @@ \section{双数组序列} \section{可连接列表} \index{序列!可链接列表} -虽然可以用$O(\lg n)$时间在二叉树随机访问森林的头部进行插入、删除、索引,但连接两个序列并不容易。我们不能简单地将所有二叉树合并到一起,而需要不断链接大小相同的树。\cref{fig:clist}给出了一种可连接列表的实现。多叉树的根存储序列表的第一个元素$x_1$, 其它元素被分成若干片段保存在更小的序列中,每个片段是一棵子树。这些子树由一个实时队列(见\cref{sec:realtime-queue})管理。我们把序列表示为$(x_1, Q_x) = [x_1, x_2, ..., x_n]$。当需要连接另一个列表$(y_1, Q_y) = [y_1, y_2, ..., y_m]$时,我们将其入队到$Q_x$的尾部。连接运算定义如下。实时队列的入队性能为常数时间,因此列表连接的性能也是常数时间的。 +虽然可以用$O(\lg n)$时间在二叉树随机访问森林的头部进行插入、删除、索引,但连接两个序列并不容易。我们不能简单地将所有二叉树合并到一起,而需要不断链接大小相同的树。\cref{fig:clist}给出了一种可连接列表的实现。多叉树的根存储序列表的第一个元素$x_1$, 其它元素被分成若干片段保存在更小的序列中,每个片段是一棵子树。这些子树由一个实时队列(见\ref{sec:realtime-queue})管理。我们把序列表示为$(x_1, Q_x) = [x_1, x_2, ..., x_n]$。当需要连接另一个列表$(y_1, Q_y) = [y_1, y_2, ..., y_m]$时,我们将其入队到$Q_x$的尾部。连接运算定义如下。实时队列的入队性能为常数时间,因此列表连接的性能也是常数时间的。 \begin{figure}[htbp] \centering diff --git a/datastruct/tree/binary-search-tree/bstree-zh-cn.tex b/datastruct/tree/binary-search-tree/bstree-zh-cn.tex index 1332a5696..b4070b522 100644 --- a/datastruct/tree/binary-search-tree/bstree-zh-cn.tex +++ b/datastruct/tree/binary-search-tree/bstree-zh-cn.tex @@ -32,7 +32,7 @@ \chapter{二叉搜索树} \numberwithin{Exercise}{chapter} \fi -数组和链表通常被认为是最基础的数据结构,其实它们并不简单(第12章)。在某些系统中,数组是最基本的组件,甚至链表也可以由数组来实现(\cref{sec:list-index-array})。另一方面,在函数式环境中,链表被作为最基本的组件来实现数组和其它更复杂的数据结构。二叉搜索树是另一种基础数据结构。乔$\cdot$本特利在《编程珠玑》\cite{Bentley}中,讨论了如何统计一段文字中各单词的个数。下面的例子程序给出了一个解法。\index{统计单词} +数组和链表通常被认为是最基础的数据结构,其实它们并不简单(第12章)。在某些系统中,数组是最基本的组件,甚至链表也可以由数组来实现(\ref{sec:list-index-array})。另一方面,在函数式环境中,链表被作为最基本的组件来实现数组和其它更复杂的数据结构。二叉搜索树是另一种基础数据结构。乔$\cdot$本特利在《编程珠玑》\cite{Bentley}中,讨论了如何统计一段文字中各单词的个数。下面的例子程序给出了一个解法。\index{统计单词} \lstset{frame=single} \begin{lstlisting}[language=Bourbaki] diff --git a/datastruct/tree/red-black-tree/rbtree-zh-cn.tex b/datastruct/tree/red-black-tree/rbtree-zh-cn.tex index 4434e46ce..fc3f5ff28 100644 --- a/datastruct/tree/red-black-tree/rbtree-zh-cn.tex +++ b/datastruct/tree/red-black-tree/rbtree-zh-cn.tex @@ -83,7 +83,7 @@ \chapter{红黑树} \section{平衡} \index{树旋转} -为避免极不平衡的情况,可将输入序列打乱(\cref{sec:bst-random-build})。但这种方法有局限性,无法处理交互输入的序列。人们找到了一些保持平衡性的方法,它们大多依赖二叉树的旋转操作,可以在改变树结构的同时保持元素有序。本章介绍红黑树,下一章介绍AVL树,它们都是自平衡树。第8章还会介绍伸展树,它能够随着操作,逐步恢复平衡。不同的二叉树可以产生相同的中序遍历结果。树旋转如\cref{fig:tree-rotation}所示,可以通过模式匹配来定义: +为避免极不平衡的情况,可将输入序列打乱(\ref{sec:bst-random-build})。但这种方法有局限性,无法处理交互输入的序列。人们找到了一些保持平衡性的方法,它们大多依赖二叉树的旋转操作,可以在改变树结构的同时保持元素有序。本章介绍红黑树,下一章介绍AVL树,它们都是自平衡树。第8章还会介绍伸展树,它能够随着操作,逐步恢复平衡。不同的二叉树可以产生相同的中序遍历结果。树旋转如\cref{fig:tree-rotation}所示,可以通过模式匹配来定义: \begin{figure}[htbp] \centering diff --git a/datastruct/tree/trie/trie-zh-cn.tex b/datastruct/tree/trie/trie-zh-cn.tex index 894f2d593..d88209bb1 100644 --- a/datastruct/tree/trie/trie-zh-cn.tex +++ b/datastruct/tree/trie/trie-zh-cn.tex @@ -991,7 +991,7 @@ \subsection{词典和自动补齐} \EndFunction \end{algorithmic} -其中函数\textproc{Expand}($s, T, n$)从$T$中扩展出$n$个结果,并将$s$附加在每个键的前面。我们可以用广度优先搜索方法实现它(见\cref{sec:DFS-BFS}): +其中函数\textproc{Expand}($s, T, n$)从$T$中扩展出$n$个结果,并将$s$附加在每个键的前面。我们可以用广度优先搜索方法实现它(见\ref{sec:DFS-BFS}): \begin{algorithmic}[1] \Function{Expand}{$s, T, n$} diff --git a/others/appendix/list/list-zh-cn.tex b/others/appendix/list/list-zh-cn.tex index f88a6bef4..4a86c9dd9 100644 --- a/others/appendix/list/list-zh-cn.tex +++ b/others/appendix/list/list-zh-cn.tex @@ -209,7 +209,7 @@ \subsection{末尾元素} \EndFunction \end{algorithmic} -\textproc{Init}通过\textproc{Cons}累积结果。这样产生的列表是逆序的,最后需要将结果再倒转过来(见\cref{subsec:reverse})。 +\textproc{Init}通过\textproc{Cons}累积结果。这样产生的列表是逆序的,最后需要将结果再倒转过来(见\ref{subsec:reverse})。 \subsection{反向索引} \index{列表!反向索引} \index{列表!rindex} @@ -482,7 +482,7 @@ \subsubsection{插入} \EndFunction \end{algorithmic} -在循环中的任何时刻,结果列表都是已序的。和递归实现相比,它们有一个本质不同:前者从右向左处理列表,而后者从左向右处理。我们稍后将在“尾递归”(\cref{sec:tail-call})中讲述如何消除这一差异。第3章详细介绍插入排序,包括性能分析和优化。 +在循环中的任何时刻,结果列表都是已序的。和递归实现相比,它们有一个本质不同:前者从右向左处理列表,而后者从左向右处理。我们稍后将在“尾递归”(\ref{sec:tail-call})中讲述如何消除这一差异。第3章详细介绍插入排序,包括性能分析和优化。 \begin{Exercise}[label={ex:list-insert}] \Question{当插入位置越界时,将其按照添加来处理。} @@ -650,7 +650,7 @@ \subsubsection{连接} \subsection{和与积} \index{列表!和} \index{列表!积} -我们常常需要计算列表的和与积。它们有着共同的计算结构。我们在\cref{sec:fold}中对它们进行抽象。定义空列表的和为0、积为1。 +我们常常需要计算列表的和与积。它们有着共同的计算结构。我们在\ref{sec:fold}中对它们进行抽象。定义空列表的和为0、积为1。 \be \begin{array}{cc} @@ -767,7 +767,7 @@ \subsection{和与积} \end{array} \ee -这一方法的复杂度为$O(\lg n)$。将$n$表示成二进制数$n = (a_ma_{m-1}...a_1a_0)_2$,如果$a_i = 1$,我们清楚地知道,需要计算$b^{2^i}$。这和二项式堆的情况很类似(\cref{sec:binomial-heap})。将所有二进制位为1的幂计算出,再累乘到一起就得到最后的结果。例如,当计算$b^{11}$时,11写成二进制为$11 = (1011)_2 = 2^3 + 2 +1$,因此$b^{11} = b^{2^3} \times b^2 \times b$。我们可以通过以下的步骤进行计算: +这一方法的复杂度为$O(\lg n)$。将$n$表示成二进制数$n = (a_ma_{m-1}...a_1a_0)_2$,如果$a_i = 1$,我们清楚地知道,需要计算$b^{2^i}$。这和二项式堆的情况很类似(\ref{sec:binomial-heap})。将所有二进制位为1的幂计算出,再累乘到一起就得到最后的结果。例如,当计算$b^{11}$时,11写成二进制为$11 = (1011)_2 = 2^3 + 2 +1$,因此$b^{11} = b^{2^3} \times b^2 \times b$。我们可以通过以下的步骤进行计算: \begin{enumerate} \item 计算$b^1$,得$b$; @@ -1165,7 +1165,9 @@ \subsection{逐一映射} 映射是一个抽象概念,它不仅局限于列表,也可以扩展到许多复杂的代数结构。下一章我们会介绍如何对树结构进行映射。只要我们能够遍历一个结构,并且有空结构的定义,就可以使用映射的概念。 \subsection{反转} -{\label[subsection]{subsec:reverse}} \index{列表!反转} +\label{subsec:reverse} + +\index{列表!反转} 如何用最小的空间反转一个单向链表是一道经典题目,需要仔细操作节点的引用。有一个简单的策略:(1)先写出一个纯递归解;(2)转换为尾递归;(3)将尾递归转换为命令式操作。纯递归解很直观: diff --git a/others/preface/preface-en.tex b/others/preface/preface-en.tex index f3ea8b23e..90c92c7dd 100644 --- a/others/preface/preface-en.tex +++ b/others/preface/preface-en.tex @@ -96,7 +96,7 @@ \subsection*{Improvement} \be \textit{minfree}(x_1, x_2, \dotsc, x_n) \leq n -\label{eq:min-free} +{\label[equation]{eq:min-free}} \ee Use an array $F$ of $n + 1$ flags to mark whether a number is free in $[0, n]$. diff --git a/others/preface/preface-zh-cn.tex b/others/preface/preface-zh-cn.tex index 93cc34fd0..87d6b2cd1 100644 --- a/others/preface/preface-zh-cn.tex +++ b/others/preface/preface-zh-cn.tex @@ -92,7 +92,7 @@ \subsection*{改进} \be \textit{minfree}(x_1, x_2, \dotsc, x_n) \leq n -\label{eq:min-free} +{\label[equation]{eq:min-free}} \ee 我们用一个长度为$n + 1$的数组$F$,来标记区间$[0, n]$内的某个整数是否可用。 diff --git a/prelude.sty b/prelude.sty index 5b212c741..3b28c1f9b 100644 --- a/prelude.sty +++ b/prelude.sty @@ -57,9 +57,9 @@ \usepackage{textcomp} \usepackage{mdframed} \usepackage{sourcecodepro} -\usepackage{cleveref} \usepackage{etoolbox} \usepackage{csquotes} +\usepackage{cleveref} \titleformat{\paragraph} {\normalfont\normalsize\bfseries}{\theparagraph}{1em}{} diff --git a/search/search-zh-cn.tex b/search/search-zh-cn.tex index 01e5022ad..efbb1f758 100644 --- a/search/search-zh-cn.tex +++ b/search/search-zh-cn.tex @@ -435,7 +435,7 @@ \section{二维查找} \begin{Answer}[ref = {ex:binary-search}] \Question{证明$k$选择的平均复杂度为$O(n)$。 -参考快速排序的复杂度分析\cref{sec:quick-sort-big-o}。} +参考快速排序的复杂度分析\ref{sec:quick-sort-big-o}。} \Question{为了查找$A$中的前$k$小元素,我们可以获取$x = \max\ (take\ k\ A), y = \min\ (drop\ k\ A)$。如果$x < y$,则$A$的前$k$个元素就是答案;否则我们用$x$划分前$k$个元素,用$y$划分剩余元素,然后在子序列$[a \gets A, x < a < y]$中递归查找前$k'$个元素,其中$k' = k - |[a \gets A, a \leq x]|$。请实现这一算法,并分析复杂度。 @@ -908,7 +908,7 @@ \section{最大子序列和} s' = max m' s in (m', s') \end{Haskell} -其中\texttt{tails}的定义见\cref{ex:list-tails},\texttt{zipWith}的定义见\cref{sec:list-zipwith},\texttt{concatMap}的定义见\cref{sec:list-concatmap}。$scanl$和$foldl$类似,但它每次把结果都保存到一个列表中。$scanl1$是$scanl$的一个特殊情况,初始值是列表的第一个元素。 +其中\texttt{tails}的定义见\cref{ex:list-tails},\texttt{zipWith}的定义见\ref{sec:list-zipwith},\texttt{concatMap}的定义见\ref{sec:list-concatmap}。$scanl$和$foldl$类似,但它每次把结果都保存到一个列表中。$scanl1$是$scanl$的一个特殊情况,初始值是列表的第一个元素。 \[ \begin{array}{rcl} @@ -2408,7 +2408,7 @@ \subsection{华容道} \begin{Answer}[ref = {ex:conway-slide-puzzle}] \Question{按层遍历一棵二叉树。 -按广度优先顺序访问各个节点,使用\cref{sec:finger-tree}中的序列作为队列: +按广度优先顺序访问各个节点,使用\ref{sec:finger-tree}中的序列作为队列: \begin{Haskell} data Tr a = E | Br (Tr a) a (Tr a) diff --git a/sorting/dc-sort/dcsort-zh-cn.tex b/sorting/dc-sort/dcsort-zh-cn.tex index ffe9b8fc7..4d1df27d4 100644 --- a/sorting/dc-sort/dcsort-zh-cn.tex +++ b/sorting/dc-sort/dcsort-zh-cn.tex @@ -85,7 +85,7 @@ \section{快速排序} \end{array} \ee -我们使用了ZF表达式(见\cref{sec:zf-expr}、\cref{sec:list-filter})划分列表,如下面的例子代码: +我们使用了ZF表达式(见\ref{sec:zf-expr}、\ref{sec:list-filter})划分列表,如下面的例子代码: \lstset{frame = single} \begin{Haskell} @@ -93,7 +93,7 @@ \section{快速排序} sort (x:xs) = sort [y | y<-xs, y <= x] ++ [x] ++ sort [y | y<-xs, x < y] \end{Haskell} -我们假设按递增顺序排序。可以把比较条件($\leq$)抽象出来,对数字、字符串等进行各种排序。我们并不要求一定是全序,但是至少要满足\textbf{严格弱序}\cite{wiki-total-order}、\cite{wiki-sweak-order}(见\cref{sec:strict-weak-order})。 +我们假设按递增顺序排序。可以把比较条件($\leq$)抽象出来,对数字、字符串等进行各种排序。我们并不要求一定是全序,但是至少要满足\textbf{严格弱序}\cite{wiki-total-order}、\cite{wiki-sweak-order}(见\ref{sec:strict-weak-order})。 \subsection{划分} \index{快速排序!划分(partition)}