基本介绍

  1. 队列是一个有序列表,可以用数组或是链表来实现。
  2. 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

栈: 先入后出(弹夹)

队首 , 队尾
image.png
image.png
数组模拟环形队列

image.png
image.png

使用数组实现简单队列的思路

非环

  1. 创建一个数组arrary,是作为队列的一个字段
  2. front初始化为-1
  3. rear, 表示队列尾部,初始化为-1
  4. 完成队列的基本查找

AddQueue // 加入数据到队列
GetQueue // 从队列取出数据
ShowQueue // 显示队列

代码实现(非环队列)

  1. // 数组模拟队列
  2. // 非环队列
  3. package main
  4. import (
  5. "errors"
  6. "fmt"
  7. "os"
  8. )
  9. /*
  10. 1. 创建一个数组arrary,是作为队列的一个字段
  11. 2. front初始化为-1
  12. 3. rear, 表示队列尾部,初始化为-1
  13. 4. 完成队列的基本查找
  14. AddQueue // 加入数据到队列
  15. GetQueue // 从队列取出数据
  16. ShowQueue // 显示队列
  17. */
  18. type Queue struct {
  19. maxSize int
  20. array [4]int // 数组模拟队列
  21. front int // 队列首(下标index), 不包含队首的元素
  22. rear int // 队列尾(下标index)
  23. }
  24. // 添加数据到队列 - 入队列
  25. func (que *Queue) AddQueue(val int) (err error) {
  26. // 先判断队列是否已满
  27. if que.rear == que.maxSize-1 {
  28. return errors.New("queue full")
  29. }
  30. que.rear++ // rear 后移
  31. que.array[que.rear] = val
  32. fmt.Println("front = ", que.front, "rear = ", que.rear, "array = ", que.array)
  33. return
  34. }
  35. // 显示队列
  36. func (que *Queue) ShowQueue() {
  37. fmt.Println("显示队列: ")
  38. fmt.Println("front = ", que.front, "rear = ", que.rear, "array = ", que.array)
  39. // front初始值是 -1, 不包含队首的元素
  40. for i := que.front + 1; i <= que.rear; i++ {
  41. fmt.Printf("array[%d] = %d\n", i, que.array[i])
  42. }
  43. fmt.Println()
  44. }
  45. // 出队列
  46. func (que *Queue) GetQueue() (val int, err error) {
  47. // 判断队列是否是空
  48. if que.rear == que.front {
  49. return -1, errors.New("queue empty")
  50. }
  51. que.front++
  52. val = que.array[que.front]
  53. que.array[que.front] = 0
  54. fmt.Println("front = ", que.front, "rear = ", que.rear, "array = ", que.array)
  55. return val, err
  56. }
  57. func main() {
  58. queue := &Queue{
  59. maxSize: 4,
  60. front: -1,
  61. rear: -1,
  62. }
  63. var key string
  64. var val int
  65. for {
  66. fmt.Println("1. 输入 add 表示添加数据到队列")
  67. fmt.Println("2. 输入 get 表示从队列中获取数据")
  68. fmt.Println("3. 输入 show 表示显示队列")
  69. fmt.Println("4. 输入 exit 表示退出")
  70. fmt.Scanln(&key)
  71. switch key {
  72. case "add":
  73. fmt.Println("请输入要入队列的数")
  74. fmt.Scanln(&val)
  75. err := queue.AddQueue(val)
  76. if err == nil {
  77. fmt.Println("加入队列成功")
  78. } else {
  79. fmt.Println(err.Error())
  80. }
  81. case "get":
  82. val, err := queue.GetQueue()
  83. if err == nil {
  84. fmt.Println("取到的值:", val)
  85. } else {
  86. fmt.Println(err.Error())
  87. }
  88. case "show":
  89. queue.ShowQueue()
  90. case "exit":
  91. os.Exit(0)
  92. default:
  93. fmt.Println("输入有误,请重新输入")
  94. }
  95. }
  96. }
  97. /*
  98. get
  99. front = 2 rear = 3 array = [0 0 0 4]
  100. 取到的值: 3
  101. 1. 输入 add 表示添加数据到队列
  102. 2. 输入 get 表示从队列中获取数据
  103. 3. 输入 show 表示显示队列
  104. 4. 输入 exit 表示退出
  105. get
  106. front = 3 rear = 3 array = [0 0 0 0]
  107. 取到的值: 4
  108. 1. 输入 add 表示添加数据到队列
  109. 2. 输入 get 表示从队列中获取数据
  110. 3. 输入 show 表示显示队列
  111. 4. 输入 exit 表示退出
  112. get
  113. queue empty
  114. */

数组模拟环形队列

分析思路:

  1. 什么时候表示队列满

    (tail + 1) % maxSize = head

  2. tail == head 表示空

  3. 初始化时, tail = 0 head = 0
  4. 环形实现: tail = (tail + 1) % maxSize, head = (head + 1) % maxSize

核心思想:到达队尾的时候,通过 加1取模 的方式回到队首

  1. 怎么统计该队列有多少个元素

(tail + maxSize - head ) % maxSize

注意: 数组的长度比实际存储的长度多1

代码实现

  1. // 数组模拟环形队列(有缺口)
  2. package main
  3. import (
  4. "errors"
  5. "fmt"
  6. "os"
  7. )
  8. /*
  9. 分析思路:
  10. 1. 什么时候表示队列满
  11. (tail + 1) % maxSize == head
  12. 2. tail == head 表示空
  13. 3. 初始化时, tail = 0 head = 0
  14. 4. 怎么统计该队列有多少个元素
  15. (tail + maxSize - head ) % maxSize
  16. */
  17. type CircleQueue struct {
  18. maxSize int
  19. array [5]int
  20. head int // 队首, 初始 0
  21. tail int // 队尾, 初始 0
  22. }
  23. // 判断环形队列是否已满
  24. func (que *CircleQueue) IsFull() bool {
  25. fmt.Println("IsFull --- head", que.head, "tail", que.tail)
  26. return (que.tail+1)%que.maxSize == que.head
  27. }
  28. // 判断环形队列是否为空
  29. func (que *CircleQueue) IsEmpty() bool {
  30. return que.tail == que.head
  31. }
  32. // 环形队列所有元素
  33. func (que *CircleQueue) Size() int {
  34. return (que.tail + que.maxSize - que.head) % que.maxSize
  35. }
  36. // 入队列
  37. func (que *CircleQueue) Push(val int) (err error) {
  38. // 先判断队列是否已满
  39. if que.IsFull() {
  40. return errors.New("CircleQueue full")
  41. }
  42. que.array[que.tail] = val
  43. fmt.Println("head = ", que.head, "tail = ", que.tail, "array = ", que.array)
  44. // que.tail = (que.tail + 1) % que.maxSize
  45. que.tail = (que.tail + 1) % len(que.array)
  46. // que.tail++ // tail 后移
  47. return
  48. }
  49. // 出队列
  50. func (que *CircleQueue) Pop() (val int, err error) {
  51. // 判断队列是否是空
  52. if que.IsEmpty() {
  53. return 0, errors.New("CircleQueue empty")
  54. }
  55. val = que.array[que.head]
  56. que.array[que.head] = 0
  57. fmt.Println("Pop --- head = ", que.head, "tail = ", que.tail, "array = ", que.array)
  58. que.head = (que.head + 1) % que.maxSize
  59. return val, err
  60. }
  61. // 显示队列
  62. func (que *CircleQueue) ShowQueue() {
  63. fmt.Println("显示队列: ")
  64. size := que.Size()
  65. if size == 0 {
  66. fmt.Println("队列为空")
  67. }
  68. tempHead := que.head
  69. for i := 0; i < size; i++ {
  70. fmt.Printf("arr[%d]=%d\t", tempHead, que.array[tempHead])
  71. tempHead = (tempHead + 1) % que.maxSize
  72. }
  73. fmt.Println()
  74. fmt.Println("head = ", que.head, "tail = ", que.tail, "array = ", que.array)
  75. fmt.Println()
  76. }
  77. func main() {
  78. circleQueue := &CircleQueue{
  79. maxSize: 5,
  80. head: 0,
  81. tail: 0,
  82. }
  83. var key string
  84. var val int
  85. for {
  86. fmt.Println("1. 输入 add 表示添加数据到队列")
  87. fmt.Println("2. 输入 get 表示从队列中获取数据")
  88. fmt.Println("3. 输入 show 表示显示队列")
  89. fmt.Println("4. 输入 exit 表示退出")
  90. fmt.Scanln(&key)
  91. switch key {
  92. case "add":
  93. fmt.Println("请输入要入队列的数")
  94. fmt.Scanln(&val)
  95. err := circleQueue.Push(val)
  96. if err == nil {
  97. fmt.Println("加入队列成功")
  98. } else {
  99. fmt.Println(err.Error())
  100. }
  101. case "get":
  102. fmt.Println("取出")
  103. val, err := circleQueue.Pop()
  104. if err == nil {
  105. fmt.Println("取到的值:", val)
  106. } else {
  107. fmt.Println(err.Error())
  108. }
  109. case "show":
  110. circleQueue.ShowQueue()
  111. case "exit":
  112. os.Exit(0)
  113. default:
  114. fmt.Println("输入有误,请重新输入")
  115. }
  116. }
  117. }
  118. /*
  119. get
  120. 取出
  121. Pop --- head = 1 tail = 0 array = [0 0 3 4 5]
  122. 取到的值: 2
  123. 1. 输入 add 表示添加数据到队列
  124. 2. 输入 get 表示从队列中获取数据
  125. 3. 输入 show 表示显示队列
  126. 4. 输入 exit 表示退出
  127. add
  128. 请输入要入队列的数
  129. 6
  130. IsFull --- head 2 tail 0
  131. head = 2 tail = 0 array = [6 0 3 4 5]
  132. 加入队列成功
  133. 1. 输入 add 表示添加数据到队列
  134. 2. 输入 get 表示从队列中获取数据
  135. 3. 输入 show 表示显示队列
  136. 4. 输入 exit 表示退出
  137. show
  138. 显示队列:
  139. arr[2]=3 arr[3]=4 arr[4]=5 arr[0]=6
  140. head = 2 tail = 1 array = [6 0 3 4 5]
  141. */