Skip to content

Commit 89396fe

Browse files
committed
fix typo
1 parent 728ca68 commit 89396fe

File tree

20 files changed

+39
-16
lines changed

20 files changed

+39
-16
lines changed

2.算法分析/2.4.一个回文字符串检查的例子/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ print(anagramSolution2('abcde','edcba'))
7676

7777
### 2.4.4.解法4: 计数和比较
7878

79-
我们最终解决回文的方法是利用两个回文字符串具有相同的 a, b, c 等等的事实。我们首先计算的是每个字母出现的次数。由于有 26 个可能的字符,我们就用 26 个列表,每个可能的字符一个。每次看到一个特定的字符,就增加该位置的计数器。最后如果两个列表的计数器一样,则字符串为回文字符串。见 ActiveCode 3
79+
我们最终解决回文的方法是利用两个回文字符串具有相同的 a, b, c 等等的事实。我们首先计算的是每个字母出现的次数。由于有 26 个可能的字符,我们就用 一个长度为 26 的列表,每个可能的字符占一个位置。每次看到一个特定的字符,就增加该位置的计数器。最后如果两个列表的计数器一样,则字符串为回文字符串。见 ActiveCode 3
8080

8181
```` python
8282
def anagramSolution4(s1,s2):
@@ -106,7 +106,7 @@ print(anagramSolution4('apple','pleap'))
106106
````
107107
*ActiveCode 3*
108108

109-
同样,这个方案有多个迭代,但是和第一个解法不一样,它不是嵌套的。两个迭代都是 n, 第三个迭代,比较两个计数列表,需要 26 步,因为有 26个字母。一共 T(n)=2n+26T(n)=2n+26,即 O(n),我们找到了一个线性量级的算法解决这个问题。
109+
同样,这个方案有多个迭代,但是和第一个解法不一样,它不是嵌套的。两个迭代都是 n, 第三个迭代,比较两个计数列表,需要 26 步,因为有 26 个字母。一共 T(n)=2n+26T(n)=2n+26,即 O(n),我们找到了一个线性量级的算法解决这个问题。
110110

111111
在结束这个例子之前,我们来讨论下空间花费,虽然最后一个方案在线性时间执行,但它需要额外的存储来保存两个字符计数列表。换句话说,该算法牺牲了空间以获得时间。
112112

3.基本数据结构/3.1.目标/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
## 3.1.目标
22

3-
* 理解抽象数据类型的栈,队列,deque和列表
3+
* 理解抽象数据类型的栈,队列,deque 和列表
44
* 能够使用 Python 列表实现 ADT 堆栈,队列和 deque。
55
* 了解基本线性数据结构实现的性能。
66
* 了解前缀,中缀和后缀表达式格式。
7-
* 使用堆栈来实现后缀表达式
8-
* 使用堆栈将表达式从中缀转换为后缀
7+
* 使用栈来实现后缀表达式
8+
* 使用栈将表达式从中缀转换为后缀
99
* 使用队列进行基本时序仿真。
10-
* 能够识别问题中堆栈,队列和 deques 数据结构的适当使用。
11-
* 能够使用节点和参考模式将抽象数据类型列表实现为链接列表
10+
* 能够识别问题中栈,队列和 deques 数据结构的适当使用。
11+
* 能够使用节点和引用将抽象数据类型列表实现为链表
1212
* 能够比较我们的链表实现与 Python 的列表实现的性能。
1313

1414

3.基本数据结构/3.2.什么是线性数据结构/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## 3.2.什么是线性数据结构
22
我们从四个简单但重要的概念开始研究数据结构。栈,队列,deques, 列表是一类数据的容器,它们数据项之间的顺序由添加或删除的顺序决定。一旦一个数据项被添加,它相对于前后元素一直保持该位置不变。诸如此类的数据结构被称为线性数据结构。
33

4-
线性数据结构有两端,有时被称为左右,某些情况被称为前后。你也可以称为顶部和底部,名字都不重要。将两个线性数据结构区分开的方法是添加和移除项目的方式,特别是添加和移除项目的位置。例如一些结构允许从一段添加项,另一些允许从另一端移除项。
4+
线性数据结构有两端,有时被称为左右,某些情况被称为前后。你也可以称为顶部和底部,名字都不重要。将两个线性数据结构区分开的方法是添加和移除项的方式,特别是添加和移除项的位置。例如一些结构允许从一端添加项,另一些允许从另一端移除项。
55

66
这些变种的形式产生了计算机科学最有用的数据结构。他们出现在各种算法中,并可以用于解决很多重要的问题。
77

3.基本数据结构/3.3.什么是栈/README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11

22
## 3.3.什么是栈
33

4-
栈(有时称为“后进先出栈”)是一个项的有序集合,其中添加移除新项目总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。
4+
栈(有时称为“后进先出栈”)是一个项的有序集合,其中添加移除新项总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。
55

66
栈的底部很重要,因为在栈中靠近底部的项是存储时间最长的。最近添加的项是最先会被移除的。这种排序原则有时被称为 LIFO,后进先出。它基于在集合内的时间长度做排序。较新的项靠近顶部,较旧的项靠近底部。
77

88
栈的例子很常见。几乎所有的自助餐厅都有一堆托盘或盘子,你从顶部拿一个,就会有一个新的托盘给下一个客人。想象桌上有一堆书(Figure 1), 只有顶部的那本书封面可见,要看到其他书的封面,只有先移除他们上面的书。Figure 2 展示了另一个栈,包含了很多 Python 对象。
99

1010
![3.3.什么是栈](assets/3.3.%E4%BB%80%E4%B9%88%E6%98%AF%E6%A0%88.png)
11+
12+
1113
*Figure 1*
1214
![3.3.什么是栈.primitive](assets/3.3.%E4%BB%80%E4%B9%88%E6%98%AF%E6%A0%88.primitive.png)
15+
16+
1317
*Figure 2*
1418

1519
和栈相关的最有用的想法之一来自对它的观察。假设从一个干净的桌面开始,现在把书一本本叠起来,你在构造一个栈。考虑下移除一本书会发生什么。移除的顺序跟刚刚被放置的顺序相反。栈之所以重要是因为它能反转项的顺序。插入跟删除顺序相反,Figure 3 展示了 Python 数据对象创建和删除的过程,注意观察他们的顺序。
1620

1721
![3.3.什么是栈.simplereversa](assets/3.3.%E4%BB%80%E4%B9%88%E6%98%AF%E6%A0%88.simplereversal.png)
22+
23+
1824
*Figure 3*
1925

2026
想想这种反转的属性,你可以想到使用计算机的时候所碰到的例子。例如,每个 web 浏览器都有一个返回按钮。当你浏览网页时,这些网页被放置在一个栈中(实际是网页的网址)。你现在查看的网页在顶部,你第一个查看的网页在底部。如果按‘返回’按钮,将按相反的顺序浏览刚才的页面。

3.基本数据结构/3.4.栈的抽象数据类型/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
例如,s 是已经创建的空栈,Table1 展示了栈操作序列的结果。栈中,顶部项列在最右边。
1313
![3.4.栈的抽象数据类型.table1](assets/3.4.%E6%A0%88%E7%9A%84%E6%8A%BD%E8%B1%A1%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B.table1.png)
1414

15+
1516
*Table1*
1617

1718

3.基本数据结构/3.5.Python实现栈/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ class Stack:
3030
````
3131
*ActiveCode 1*
3232

33-
记住我们只定义类的实现,我们需要创建一个栈,然后使用它。ActiveCode 2 展示了我们通过实例化 Stack 类执行Table 1中的操作。注意,Stack 类的定义是从 pythonds 模块导入的。
33+
记住我们只定义类的实现,我们需要创建一个栈,然后使用它。ActiveCode 2 展示了我们通过实例化 Stack 类执行 Table 1中的操作。注意,Stack 类的定义是从 pythonds 模块导入的。
3434

3535

3636
> **Note**
37-
pythonds 模块包含本书中讨论的所有数据结构的实现。它根据以下部分构造:基本数据类型,树和图形。 该模块可以从 [pythonworks.org](http://www.pythonworks.org/pythonds)下载。
37+
pythonds 模块包含本书中讨论的所有数据结构的实现。它根据以下部分构造:基本数据类型,树和图。 该模块可以从 [pythonworks.org](http://www.pythonworks.org/pythonds)下载。
3838

3939
````
4040
from pythonds.basic.stack import Stack

3.基本数据结构/3.6.简单括号匹配/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## 3.6.简单括号匹配
2-
我们现在把注意力转向使用栈来解决真正的计算机问题。你会这么写算术表达式
2+
我们现在把注意力转向使用栈解决真正的计算机问题。你会这么写算术表达式
33

44
`(5+6)∗(7+8)/(4+3)`
55

@@ -33,9 +33,11 @@
3333
区分括号是否匹配的能力是识别很多编程语言结构的重要部分。具有挑战的是如何编写一个算法,能够从左到右读取一串符号,并决定符号是否平衡。为了解决这个问题,我们需要做一个重要的观察。从左到右处理符号时,最近开始符号必须与下一个关闭符号相匹配(见 Figure 4)。此外,处理的第一个开始符号必须等待直到其匹配最后一个符号。结束符号以相反的顺序匹配开始符号。他们从内到外匹配。这是一个可以用栈解决问题的线索。
3434

3535
![3.6.简单括号匹配.simpleparcheck](assets/3.6.%E7%AE%80%E5%8D%95%E6%8B%AC%E5%8F%B7%E5%8C%B9%E9%85%8D.simpleparcheck.png)
36+
37+
3638
*Figure 4*
3739

38-
一旦你认为栈是保存括号的恰当的数据结构,算法是很直接的。从空栈开始,从左到右处理括号字符串。如果一个符号是一个开始符号,将其作为一个信号,对应的结束符号稍后会出现。另一方面,如果符号是结束符号,弹出栈,只要可以弹出栈的开始符号可以匹配每个结束符号,则括号保持匹配状态。如果任何时候栈上没有出现符合结束符号的开始符号,则字符串不匹配。最后,当所有符号都被处理后,栈应该是空的。实现此算法的 Python 代码见 ActiveCode 1。
40+
一旦你认为栈是保存括号的恰当的数据结构,算法是很直接的。从空栈开始,从左到右处理括号字符串。如果一个符号是一个开始符号,将其作为一个信号,对应的结束符号稍后会出现。另一方面,如果符号是结束符号,弹出栈,只要弹出栈的开始符号可以匹配每个结束符号,则括号保持匹配状态。如果任何时候栈上没有出现符合开始符号的结束符号,则字符串不匹配。最后,当所有符号都被处理后,栈应该是空的。实现此算法的 Python 代码见 ActiveCode 1。
3941

4042
````
4143
from pythonds.basic.stack import Stack

3.基本数据结构/3.8.十进制转换成二进制/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
在你学习计算机的过程中,你可能已经接触了二进制。二进制在计算机科学中是很重要的,因为存储在计算机内的所有值都是以 0 和 1 存储的。如果没有能力在二进制数和普通字符串之间转换,我们与计算机之间的交互非常棘手。
44

5-
整数值是常见的数据项。他们一直用于计算机程序和计算。我们在数学类中学习它们,当然最后用十进制或者基数 10 来表示它们。十进制 233^10 以及对应的二进制表示 11101001^2 分别解释为
5+
整数值是常见的数据项。他们一直用于计算机程序和计算。我们在数学课上学习它们,当然最后用十进制或者基数 10 来表示它们。十进制 233^10 以及对应的二进制表示 11101001^2 分别解释为
66

77
![3.8.十进制转换成二进制.2](assets/3.8.%E5%8D%81%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2%E6%88%90%E4%BA%8C%E8%BF%9B%E5%88%B6.2.png)
88

@@ -13,6 +13,8 @@
1313
“除 2” 算法假定我们从大于 0 的整数开始。不断迭代的将十进制除以 2,并跟踪余数。第一个除以 2 的余数说明了这个值是偶数还是奇数。偶数有 0 的余数,记为 0。奇数有余数 1,记为 1.我们将得到的二进制构建为数字序列,第一个余数实际上是序列中的最后一个数字。见 Figure 5 , 我们再次看到了反转的属性,表示栈可能是解决这个问题的数据结构。
1414

1515
![3.8.十进制转换成二进制.figure5](assets/3.8.%E5%8D%81%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2%E6%88%90%E4%BA%8C%E8%BF%9B%E5%88%B6.figure5.png)
16+
17+
1618
*Figure 5*
1719

1820
Activecode 1 中的 Python 代码实现了 “除 2” 算法,函数 divideBy2 传入了一个十进制的参数,并重复除以 2。第 7 行使用内置的模运算符 % 来提取余数,第 8 行将余数压到栈上。当除到 0 后,11-13 行构造了一个二进制字符串。
@@ -39,7 +41,7 @@ print(divideBy2(42))
3941
````
4042
*ActiveCode 1*
4143

42-
这个用于二进制转换的算法可以很容易的扩展以执行任何基数的转换。在计算可科学中,通常会使用很多不同的编码。其中最常见的是二级制,八进制和十六进制。
44+
这个用于二进制转换的算法可以很容易的扩展以执行任何基数的转换。在计算机科学中,通常会使用很多不同的编码。其中最常见的是二级制,八进制和十六进制。
4345

4446
十进制 233 和它对应的八进制和十六进制 352^8, E9^16
4547

3.基本数据结构/3.9.中缀后缀和后缀表达式/README.md renamed to 3.基本数据结构/3.9.中缀前缀和后缀表达式/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,24 @@
1818
在后缀中,表达式将是 `A B C * +`,再次,操作的顺序被保留,因为 `*` 紧接在 B 和 C 之后出现,表示 `*` 具有高优先级,`+` 优先级低。虽然操作符在它们各自的操作数前后移动,但是顺序相对于彼此保持完全相同。
1919

2020
![3.9.中缀后缀和后缀表达式.table2](assets/3.9.%E4%B8%AD%E7%BC%80%E5%90%8E%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F.table2.png)
21+
22+
2123
*Table 2*
24+
2225
现在考虑中缀表达式 `(A + B) * C`,回想下,在这种情况下,中缀需要括号在乘法之前强制执行加法。然而,当 A+B 写到前缀中时,加法运算符简单的移动到操作数 `+ A B` 之前。这个操作的结果成为乘法的第一个操作数。乘法运算符移动到整个表达式的前面,得出 `* + A B C`,同样,在后缀 `A B +`中,强制先加法。可以直接对该结果和剩余的操作数 C 相乘。然后,得出后缀表达式为 `A B + C *`
2326

2427
再次考虑这三个表达式(见 Table 3),括号不见了。为什么在前缀和后缀的时候不需要括号了呢?答案是操作符对于他们的操作数不再模糊,只有中缀才需要括号,前缀和后缀表达式的操作顺序完全由操作符的顺序决定。
2528

2629
![3.9.中缀后缀和后缀表达式.table3](assets/3.9.%E4%B8%AD%E7%BC%80%E5%90%8E%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F.table3.png)
30+
31+
2732
*Table 3*
2833

2934
Table 4 展示了一些其他的例子
3035

3136
![3.9.中缀后缀和后缀表达式.table4](assets/3.9.%E4%B8%AD%E7%BC%80%E5%90%8E%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F.table4.png)
37+
38+
3239
*Table 4*
3340

3441
### 3.9.1.中缀表达式转换前缀和后缀
@@ -39,10 +46,14 @@ Table 4 展示了一些其他的例子
3946
看上面的子表达式`(B * C)`中的右括号。 如果我们将乘法符号移动到那个位置,并删除匹配的左括号,得到 `B C * `,我们实际上已经将子表达式转换为后缀符号。 如果加法运算符也被移动到其相应的右括号位置并且匹配的左括号被去除,则将得到完整的后缀表达式(见 Figure 6)。
4047

4148
![3.9.中缀后缀和后缀表达式.figure6](assets/3.9.%E4%B8%AD%E7%BC%80%E5%90%8E%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F.figure6.png)
49+
50+
4251
*Figure 6*
4352

4453
如果我们不是将符号移动到右括号的位置,我们将它向左移动,我们得到前缀符号(见 Figure 7)。圆括号对的位置实际上是包含的运算符的最终位置的线索。
4554
![3.9.中缀后缀和后缀表达式.figure7](assets/3.9.%E4%B8%AD%E7%BC%80%E5%90%8E%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F.figure7.png)
55+
56+
4657
*Figure 7*
4758

4859
所以为了转换表达式,无论是对前缀还是后缀符号,先根据操作的顺序把表达式转换成完全括号表达式。然后将包含的运算符移动到左或右括号的位置,具体取决于需要前缀或后缀符号。
@@ -51,6 +62,7 @@ Table 4 展示了一些其他的例子
5162

5263
![3.9.中缀后缀和后缀表达式.figure8](assets/3.9.%E4%B8%AD%E7%BC%80%E5%90%8E%E7%BC%80%E5%92%8C%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F.figure8.png)
5364

65+
5466
*Figure 8*
5567

5668
### 3.9.2.中缀转后缀通用法

0 commit comments

Comments
 (0)