Go 语言实现队列

queue.go 程序描述了 Go 语言的队列实现,我们将分为五个部分来介绍。注意,这里队列的实现使用了链表。Push() 函数和 Pop() 函数分别用于队列中元素的增删。

queue.go 中的第一部分代码如下:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type Node struct {
  6. Value int
  7. Next *Node
  8. }
  9. var size = 0
  10. var queue = new(Node)

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

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

  1. func Push(t *Node, v int) bool {
  2. if queue == nil {
  3. queue = &Node{v, nil}
  4. size++
  5. return true
  6. }
  7. t = &Node{v, nil}
  8. t.Next = queue
  9. queue = t
  10. size++
  11. return true
  12. }

这部分展示了 Push() 函数的实现,这个实现很好理解。如果队列是空的就会被新的节点取代。如果队列不为空,那么新节点就会被插入到当前队列的前面,然后新节点会变成队列的头节点。

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

  1. func Pop(t *Node) (int, bool) {
  2. if size == 0 {
  3. return 0, false
  4. }
  5. if size == 1 {
  6. queue = nil
  7. size--
  8. return t.Value, true
  9. }
  10. temp := t
  11. for (t.Next) != nil {
  12. temp = t
  13. t = t.Next
  14. }
  15. v := (temp.Next).Value
  16. temp.Next = nil
  17. size--
  18. return v, true
  19. }

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

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

  1. func traverse(t *Node) {
  2. if size == 0 {
  3. fmt.Println("Empty Queue!")
  4. return
  5. }
  6. for t != nil {
  7. fmt.Printf("%d -> ", t.Value)
  8. t = t.Next
  9. }
  10. fmt.Println()
  11. }

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

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

  1. func main() {
  2. queue = nil
  3. Push(queue, 10)
  4. fmt.Println("Size:", size)
  5. traverse(queue)
  6. v, b := Pop(queue)
  7. if b {
  8. fmt.Println("Pop:", v)
  9. }
  10. fmt.Println("Size:", size)
  11. for i := 0; i < 5; i++ {
  12. Push(queue, i)
  13. }
  14. traverse(queue)
  15. fmt.Println("Size:", size)
  16. v, b = Pop(queue)
  17. if b {
  18. fmt.Println("Pop:", v)
  19. }
  20. fmt.Println("Size:", size)
  21. v, b = Pop(queue)
  22. if b {
  23. fmt.Println("Pop:", v)
  24. }
  25. fmt.Println("Size:", size)
  26. traverse(queue)
  27. }

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

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

  1. Size: 1
  2. 10 ->
  3. Pop: 10
  4. Size: 0
  5. 4 -> 3 -> 2 -> 1 -> 0 ->
  6. Size: 5
  7. Pop: 0
  8. Size: 4
  9. Pop: 1
  10. Size: 3
  11. 4 -> 3 -> 2 ->