Skip to content

Commit

Permalink
updated 05.5 - 05.8
Browse files Browse the repository at this point in the history
  • Loading branch information
kasheemlew committed May 4, 2019
1 parent e16d2a1 commit 07d63c3
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 23 deletions.
4 changes: 2 additions & 2 deletions eBook/chapter5/05.5.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Node struct {
var root = new(Node)
```

在这部分代码中,我们定义了用作链表节点的 `Node` 结构体类型和保存链表第一个元素的全局变量 `root`,在代码的其他任何地方我们都能访问这个变量。
在这部分代码中,我们定义了用作链表节点的 `Node` 结构类型和保存链表第一个元素的全局变量 `root`,在代码的其他任何地方我们都能访问这个变量。

`linkedList.go` 的第二部分是如下的 Go 代码:

Expand Down Expand Up @@ -104,7 +104,7 @@ func size(t *Node) int {

这一部分包含了两个非常方便的函数——`lookupNode()``size()` 的实现。前一个函数检查链表中是否存在给定的元素,后一个函数返回链表的大小,也就是链表中节点的数量。

`lookupNode()` 函数实现背后的逻辑很容易理解:访问单向链表中所有的元素来查找你想要的值。如果你从头到尾都没找到想要的值,那就说明链表中没有这个值。
`lookupNode()` 函数实现背后的逻辑很容易理解:依次访问单向链表中所有的元素来查找你想要的值。如果你从头到尾都没找到想要的值,那就说明链表中没有这个值。

`linkedList.go` 的最后一部分包含 `main()` 函数的实现:

Expand Down
6 changes: 3 additions & 3 deletions eBook/chapter5/05.5.2.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### 链表的优点

链表最大的有点就是容易理解和实现。链表的通用型使得它们可以用于很多不同的情形。这意味着可以用它们对各种不同类型的数据建模。此外,在链表中使用指针进行顺序检索的速度非常快。
链表最大的有点就是容易理解和实现。链表的通用性使得它们可以用于很多不同的情形。这意味着可以用链表对各种不同类型的数据建模。此外,在链表中使用指针进行顺序检索的速度非常快。

链表不仅可以帮你对数据排序,还可以在插入和删除元素之后帮你保持数据的有序性。从有序链表中删除一个节点的操作与无序链表中相同。然而,向有序链表中插入新的节点则与无需链表中不同,为了保持链表的有序性,必须将新节点放到正确的位置。实践过程中,这意味着如果你有大量数据并且会频繁删除数据,那么相对于哈希表和二叉树,使用链表是一个更好的选择。
链表不仅可以对数据排序,还可以在插入和删除元素之后保持数据的有序性。从有序链表中删除一个节点的操作与无序链表中相同,而向有序链表中插入新的节点则与无需链表中不同,为了保持链表的有序性,必须将新节点放到正确的位置。实际上,这意味着如果你有大量数据并且会频繁删除数据,那么相对于哈希表和二叉树,使用链表是一个更好的选择。

最后,**有序链表**允许你在搜索和查找节点时使用各种优化技术。其中最通用一种就是保存一个指向游戏链表中间节点的指针,然后从这里开始进行查找。这个简单的优化方法可以将查找操作的时间减少一半
最后,有很多技术可以优化**有序链表**中搜索和查找节点的过程。其中最常用的一种就是保存一个指向有序链表中间节点的指针,之后每次都从这个节点开始查找。这个简单的优化方法可以将查找操作的时间减少一半
6 changes: 3 additions & 3 deletions eBook/chapter5/05.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

**链表**是一种包含有限个元素的数据结构,其中每个元素至少占用两个存储单元,一个用于存储真正的数据,另一个用于存储链接当前元素和下一个元素的指针,从而建立了一个元素序列构成的链表。

链表中的第一个元素称为头,最后一个元素称为尾。在定义链表的过程中,你需要做的第一件事就是将链表头与其他变量区分开,因为链表头是你访问整个链表的唯一媒介。注意,如果弄丢了指向单向链表第一个节点的指针,你就没法再找到它了。
链表中的第一个元素称为头,最后一个元素称为尾。在定义链表的过程中,你需要做的第一件事就是将链表头用单独的变量存储,因为链表头是你访问整个链表的唯一媒介。注意,如果弄丢了指向单向链表第一个节点的指针,你就没法再找到它了。

下图展示了一个拥有五个节点的链表:

![](../../images/chapter5/05.5-1.jpg)

下图描述了如何从链表中移除一个节点,它将帮助你更好地理解这个过程所涉及的步骤。你要做的主要是修改被删除节点左侧的那个节点,将其下一个元素设定为被删除节点右侧的那个节点
下图描述了如何从链表中移除一个节点,它将帮助你更好地理解这个过程所涉及的步骤。你要做的主要是修改被删除节点左侧的那个节点,将它指向下一个元素的指针指向被删除节点右侧的那个节点

![](../../images/chapter5/05.5-2.jpg)

下面的链表实现已经相对简化了,并且不含删除节点的功能,这个功能将留给读者作为练习题
下面的链表实现已经相对简化了,并且不含删除节点的功能,这个功能的实现将留给读者作为练习题
6 changes: 3 additions & 3 deletions eBook/chapter5/05.6.1.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Go 语言实现双向链表

双向链表相关实现的 Go 程序是 `doublyList.go`,我们将分为五个部分来介绍。双向链表背后的基本思想和单向链表相同。不过由于双向链表中每个节点都有两个指针,所以操作更冗杂。
实现了双向链表的 Go 程序是 `doublyList.go`,我们将分为五个部分来介绍。双向链表背后的基本思想和单向链表相同。不过由于双向链表中每个节点都有两个指针,所以操作更冗杂。

`doublyList.go` 的第一部分如下:

Expand All @@ -18,7 +18,7 @@ type Node struct {
}
```

这部分中使用 Go 的结构体对双向链表的节点进行了定义。不过这次的 `struct` 中有两个指针字段,原因很明显
这部分中使用 Go 的结构体定义了双向链表的节点。不过这次的 `struct` 中有两个指针字段,原因就不必多说了

`doublyList.go` 的第二部分包含如下的 Go 代码:

Expand Down Expand Up @@ -84,7 +84,7 @@ func reverse(t *Node) {
}
```

这是 `traverse()``reverse()` 函数的 Go 代码。`traverse()` 的实现和 `linkedList.go` 中的一样。但是 `reverse()` 背后的逻辑很有趣。因为没有指向双向链表尾节点的指针,所以我们必须先从头向后访问,直到找到尾节点。
这是 `traverse()``reverse()` 函数的 Go 代码。`traverse()` 的实现和 `linkedList.go` 中的一样。但是 `reverse()` 背后的逻辑很有趣。因为没有指向双向链表尾节点的指针,所以我们必须先从头向后访问,直到找到尾节点,之后才能反向遍历所有的节点

`doublyList.go` 的第四部分包含如下的 Go 代码:

Expand Down
2 changes: 1 addition & 1 deletion eBook/chapter5/05.6.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

双向链表的功能比单向链表更加丰富,你可以从任意方向遍历双向链表,也可更容易地在双向链表中增删元素。此外,即使弄丢了指向双向链表头节点的指针,你也可以重新找回它。然而,这种多功能性的代价就是每个节点需要维护两个指针。开发者需要考虑这种额外的复杂性是否值得。

总之,你的音乐播放器中的歌单肯定是用的双向链表,所以你才能选择上一首和下一首
总之,你的音乐播放器中的歌单用的可能就是双向链表,所以你才能切换到上一首歌和下一首歌
2 changes: 1 addition & 1 deletion eBook/chapter5/05.6.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

![](../../images/chapter5/05.6-2.jpg)

所以,单向链表和双向链表的主要区别实际上只是双向链表的操作会更冗杂。这是你为了能够从两个方向都能访问双向链表所必须付出的代价。
所以,单向链表和双向链表的主要区别实际上只是双向链表的操作更冗杂。这是你为了能够从两个方向都能访问双向链表所必须付出的代价。
27 changes: 23 additions & 4 deletions eBook/chapter5/05.7.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var size = 0
var queue = new(Node)
```

用一个参数(`size`)保存队列中节点的数量很实用但不是必须的。但这个实现为了简化操作而提供了这个功能
用一个参数(`size`)保存队列中节点的数量很实用但不是必须的。不过为了简化操作,这里展示的实现还是提供了这个功能

`queue.go` 的第二部分包含如下的 Go 代码:

Expand Down Expand Up @@ -71,9 +71,28 @@ func Pop(t *Node) (int, bool) {
}
```

以上代码展示了 `Pop()` 函数的实现,该函数将最老的元素从队列中移除。如果队列为空(`size == 0`就没有数值可以返回。如果队列只有一个节点,那么将返回这个节点的数值,队列也会变成空的。其他情况下将取出队列中的最后一个元素,并将移除最后一个节点,然后修改节点的指针,最后返回节点的值
以上代码展示了 `Pop()` 函数的实现,该函数将最老的元素从队列中移除。如果队列为空(`size == 0`就没有值可以返回。如果队列只有一个节点,那么将返回这个节点的值,队列也会变成空的。其他情况下将取出队列中的最后一个元素,并将移除最后一个节点,然后对节点的指针进行必要的修改,最后返回被删除节点的值

`queue.go` 的第四个代码段如下:
`queue.go` 的第四个代码段包含如下的 Go 代码:

```go
func traverse(t *Node) {
if size == 0 {
fmt.Println("Empty Queue!")
return
}

for t != nil {
fmt.Printf("%d -> ", t.Value)
t = t.Next
}
fmt.Println()
}
```

严格来说,`traverse()` 函数对于队列的操作并不是必须的,但是它提供了一种实用的方法来查看队列中的所有节点。

`queue.go` 的最后一个代码段如下:

```go
func main() {
Expand Down Expand Up @@ -109,7 +128,7 @@ func main() {
}
```

`main()` 中几乎所有的代码都是对队列操作的检查。其中最重要的代码是两个 `if` 语句,它能让你知道 `Pop()` 函数返回了一个确切的值还是因队列为空而没有返回
`main()` 中几乎所有的代码都是对队列操作的检查。其中最重要的代码是两个 `if` 语句,它能让你知道 `Pop()` 函数返回了一个确切的值还是因队列为空而没有返回任何值

执行 `queue.go` 将产生如下输出:

Expand Down
8 changes: 4 additions & 4 deletions eBook/chapter5/05.8.1.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Go 语言实现栈

现在是时候看看如何使用 Go 语言实现栈了。相关的细节在 `stack.go` 源文件中。同样,栈的实现也会用到链表。如你所知,你需要两个函数:一个 `Push()` 函数将元素放入栈中,一个 `Pop()` 函数从栈中删除元素。单独使用一个变量保存栈中元素的数量很实用,这样不需要访问链表就能分辨栈是否为空,不过这不是必须的。
现在是时候看看如何使用 Go 语言实现栈了。相关的细节在 `stack.go` 源文件中。同样,栈的实现也会用到链表。如你所知,你需要两个函数:一个 `Push()` 函数将元素放入栈中,一个 `Pop()` 函数从栈中删除元素。单独使用一个变量保存栈中元素的数量是个很实用的方法,这样即使不访问链表也能判断栈是否为空,不过这不是必须的。

`stack.go` 中的源代码将分四个部分介绍。第一部分如下:

Expand Down Expand Up @@ -38,7 +38,7 @@ func Push(v int) bool {
}
```

如果栈为空就创建一个新节点(`temp`)并将它放在当前栈的最前面,然后新节点会成为栈的头节点。这个版本的 `Push()` 函数永远返回 `true`对于存储空间有限栈,你可以修改一下,在栈将要溢出时返回 `false`
如果栈为空就创建一个新节点(`temp`)并将它放在当前栈的最前面,然后新节点会成为栈的头节点。这个版本的 `Push()` 函数永远返回 `true`对于存储空间有限的栈,你可以修改一下,在栈将要溢出时返回 `false`

第三部分包含 `Pop()` 函数的实现:

Expand Down Expand Up @@ -77,7 +77,7 @@ func traverse(t *Node) {
}
```

由于这里的栈使用链表实现的,所以也用链表的方式进行遍历。
由于这里的栈是使用链表实现的,所以也用链表的方式进行遍历。

`stack.go` 的最后一部分如下:

Expand Down Expand Up @@ -126,4 +126,4 @@ Pop() failed!
Empty Stack!
```

> 现在为止,你已经知道了如何使用链表实现哈希表、队列和栈。这些例子会让你意识到,一般情况下链表对编程和计算机科学来时是多么的有效和重要
> 现在为止,你已经知道了如何使用链表实现哈希表、队列和栈。这些例子会让你意识到,在一般情况下链表对于编程和计算机科学来说是多么的有效和重要
4 changes: 2 additions & 2 deletions eBook/chapter5/05.8.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
### Go 语言中的栈

****是一种看起来像一堆盘子的数据结构。在你需要一个新盘子时,最后一个被放在这堆盘子顶端的盘子将会最先被使用
****是一种看起来像一堆盘子的数据结构。你在需要一个新盘子时会先使用最后一个被放在这堆盘子顶端的那个盘子

栈最大的有点就是简单,因为你只需要实现两个函数就能使用栈,向栈中添加新节点或者删除栈中的节点
栈最大的优点就是简单,因为你只需要实现两个函数就能使用栈,之后你可以向栈中添加新节点或者删除栈中的节点

0 comments on commit 07d63c3

Please sign in to comment.