Skip to content

Commit

Permalink
05.8 05.8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
kasheemlew committed May 3, 2019
1 parent f4c6e95 commit 648a8b3
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 0 deletions.
129 changes: 129 additions & 0 deletions eBook/chapter5/05.8.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
### Go 语言实现栈

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

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

```go
package main

import (
"fmt"
)

type Node struct {
Value int
Next *Node
}

var size = 0
var stack = new(Node)
```

`stack.go` 的第二部分包含了 `Push()` 函数的实现:

```go
func Push(v int) bool {
if stack == nil {
stack = &Node{v, nil}
size = 1
return true
}

temp := &Node{v, nil}
temp.Next = stack
stack = temp
size++
return true
}
```

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

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

```go
func Pop(t *Node) (int, bool) {
if size == 0 {
return 0, false
}

if size == 1 {
size = 0
stack = nil
return t.Value, true
}

stack = stack.Next
size--
return t.Value, true
}
```

`stack.go` 的第四个代码段如下:

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

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

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

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

```go
func main() {

stack = nil
v, b := Pop(stack)
if b {
fmt.Print(v, " ")
} else {
fmt.Println("Pop() failed!")
}

Push(100)
traverse(stack)
Push(200)
traverse(stack)

for i := 0; i < 10; i++ {
Push(i)
}

for i := 0; i < 15; i++ {
v, b := Pop(stack)
if b {
fmt.Print(v, " ")
} else {
break
}
}
fmt.Println()
traverse(stack)
}
```

如你所见,`stack.go` 的源代码比 `queue.go` 的稍微短一点,这主要是因为栈背后的思想比队列更简单。

执行 `stack.go` 将生成如下输出:

```sh
Pop() failed!
100 ->
200 -> 100 ->
9 8 7 6 5 4 3 2 1 0 200 100
Empty Stack!
```

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

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

栈最大的有点就是简单,因为你只需要实现两个函数就能使用栈,向栈中添加新节点或者删除栈中的节点。
87 changes: 87 additions & 0 deletions eBook/examples/chapter5/stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package main

import (
"fmt"
)

type Node struct {
Value int
Next *Node
}

var size = 0
var stack = new(Node)

func Push(v int) bool {
if stack == nil {
stack = &Node{v, nil}
size = 1
return true
}

temp := &Node{v, nil}
temp.Next = stack
stack = temp
size++
return true
}

func Pop(t *Node) (int, bool) {
if size == 0 {
return 0, false
}

if size == 1 {
size = 0
stack = nil
return t.Value, true
}

stack = stack.Next
size--
return t.Value, true
}

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

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

func main() {

stack = nil
v, b := Pop(stack)
if b {
fmt.Print(v, " ")
} else {
fmt.Println("Pop() failed!")
}

Push(100)
traverse(stack)
Push(200)
traverse(stack)

for i := 0; i < 10; i++ {
Push(i)
}

for i := 0; i < 15; i++ {
v, b := Pop(stack)
if b {
fmt.Print(v, " ")
} else {
break
}
}
fmt.Println()
traverse(stack)
}

0 comments on commit 648a8b3

Please sign in to comment.