• GO语言-数据结构-队列


    目录

    1.队列的顺序存储结构

    1.1 队列顺序存储结构-结构体定义

    1.2 队列顺序存储结构--初始化队列

    1.3 队列顺序存储结构-入队

    1.4 队列顺序存储结构-出队

    1.5 完整代码

    2.循环队列

    2.1 循环队列-入队

    2.2 循环队列-出队

    2.3 循环队列完整代码

    3.队列的链式存储结构

    3.1 队列的链式存储结构-结构体定义

    3.2 队列的链式存储结构-队列初始化

    3.3 队列的链式存储结构-入队

    3.4 队列的链式存储结构-出队

    3.5 完整代码 


     队列(Queue),是具有一定操作限制的线性表。只能在一端插入,在另一端删除。

    • 插入数据:入队(AddQ)
    • 删除数据:出队(DeleteQ)
    • 先进先出:First In First Out(FIFO)

    队列的抽象数据类型描述

    数据对象集:一个有0或多个元素的线性表。

    操作集:

    1. 生成长度为MaxSize的空队列
    2. 判断队列是否已满
    3. 判断队列是否已空
    4. 将元素插入队列中
    5. 将元素从队列中删除并返回

    1.队列的顺序存储结构

    队列的顺序存储结构组成:一个一维数组、一个记录队列头元素位置的变量front、一个记录队列尾元素的变量rear

    • 可以声明front=0,rear=-1。每次入队rear+1,每次出队front+1。
    • rear-front=-1时,队列空。
    • rear+1=MaxSize时,队列满。

    1.1 队列顺序存储结构-结构体定义

    1. type Queue struct {
    2. front int
    3. rear int
    4. queueArray [6]int
    5. }

    1.2 队列顺序存储结构--初始化队列

    1. func initQueue() (queue *Queue) {
    2. //初始化队列
    3. queue = &Queue{
    4. front: 0,
    5. rear: -1,
    6. queueArray: [6]int{},
    7. }
    8. return queue
    9. }

    1.3 队列顺序存储结构-入队

    1. func (q *Queue) addQueue(v int) error {
    2. //判断队列是否已满
    3. if q.Rear+1 == q.MaxSize {
    4. return errors.New("队列已满")
    5. }
    6. q.Rear += 1 //队尾下标+1
    7. q.QueueArray[q.Rear] = v //数据插入队尾
    8. return nil
    9. }

    1.4 队列顺序存储结构-出队

    1. func (q *Queue) deleteQueue() (int, error) {
    2. //判断队列否为空
    3. if q.Rear-q.Front == -1 {
    4. return -1, errors.New("队列为空")
    5. }
    6. v := q.QueueArray[q.Front] //获取队列头部元素值
    7. q.Front += 1 //队头下标+1
    8. return v, nil
    9. }

    1.5 完整代码

    1. package main
    2. import (
    3. "errors"
    4. "fmt"
    5. )
    6. type Queue struct {
    7. Front int
    8. Rear int
    9. MaxSize int
    10. QueueArray [6]int
    11. }
    12. func main() {
    13. //初始化队列
    14. queue := initQueue()
    15. //队列最大能存储6个元素,最大队尾下标为5
    16. queue.addQueue(100)
    17. queue.addQueue(200)
    18. fmt.Println("入队两个元素")
    19. fmt.Printf("队列: %v, 队头front: %v, 队尾rear: %v\n", queue.QueueArray, queue.Front, queue.Rear)
    20. v, err := queue.deleteQueue()
    21. if err != nil {
    22. fmt.Println(err)
    23. } else {
    24. fmt.Printf("出队元素: %v, 队头front: %v, 队尾rear: %v\n", v, queue.Front, queue.Rear)
    25. }
    26. //入队5个元素
    27. for i := 1; i <= 5; i++ {
    28. err := queue.addQueue(i)
    29. if err != nil {
    30. fmt.Println(err)
    31. }
    32. }
    33. fmt.Printf("队列: %v, 队头front: %v, 队尾rear: %v\n", queue.QueueArray, queue.Front, queue.Rear)
    34. }
    35. //队列初始化
    36. func initQueue() (queue *Queue) {
    37. //初始化队列
    38. queue = &Queue{
    39. Front: 0,
    40. Rear: -1,
    41. MaxSize: 6,
    42. QueueArray: [6]int{},
    43. }
    44. return queue
    45. }
    46. //队列-入队
    47. func (q *Queue) addQueue(v int) error {
    48. //判断队列是否已满
    49. if q.Rear+1 == q.MaxSize {
    50. return errors.New("队列已满")
    51. }
    52. q.Rear += 1 //队尾下标+1
    53. q.QueueArray[q.Rear] = v //数据插入队尾
    54. return nil
    55. }
    56. //队列-出队
    57. func (q *Queue) deleteQueue() (int, error) {
    58. //判断队列否为空
    59. if q.Rear-q.Front == -1 {
    60. return -1, errors.New("队列为空")
    61. }
    62. v := q.QueueArray[q.Front] //获取队列头部元素值
    63. q.QueueArray[q.Front] = 0 //出队数据置为0
    64. q.Front += 1 //队头下标+1
    65. return v, nil
    66. }

     

    2.循环队列

    经过多次的入队和出队,队尾会达到数组的限制,而对头会空出几个位置。为了更好地利用数组的空间,则引入循环队列的概念。

    • 可以声明front=0,rear=-1。每次入队rear+1,每次出队front+1。
    • 循环存入时,rear和front的值一直累加。需要确定front和rear下标时,使用front和rear与数组MaxSize取模。
    • rear-front=-1时,队列空。
    • rear-front+1=MaxSize时,队列满。

    循环队列的实现与常规的使用数组实现的非循环队列的区别就在于,循环队列的出栈和入栈时的队front和rear的操作有所不同。

    2.1 循环队列-入队

    1. func (q *Queue) addQueue(v int) error {
    2. //判断循环队列是否已满
    3. if q.Rear-q.Frount+1 == q.MaxSize {
    4. return errors.New("循环队列已满")
    5. }
    6. q.Rear += 1 //队尾下标+1
    7. q.QueueArray[q.Rear%q.MaxSize] = v //数据入队尾;rear与MaxSize去模,获取实际数组下标
    8. return nil
    9. }

    2.2 循环队列-出队

    1. func (q *Queue) deleteQueue() (int, error) {
    2. //判断循环队列否为空
    3. if q.Rear-q.Frount == -1 {
    4. return -1, errors.New("队列为空")
    5. }
    6. v := q.QueueArray[q.Frount%q.MaxSize] //获取队列头部元素值;front与MaxSize去模,获取实际数组下标
    7. q.QueueArray[q.Frount%q.MaxSize] = 0 //出队数据置为0
    8. q.Frount += 1 //队头下标+1
    9. return v, nil
    10. }

    2.3 循环队列完整代码

    1. package main
    2. import (
    3. "errors"
    4. "fmt"
    5. )
    6. type Queue struct {
    7. Frount int
    8. Rear int
    9. MaxSize int
    10. QueueArray [6]int
    11. }
    12. type QueueNode struct {
    13. }
    14. func main() {
    15. //初始化队列
    16. queue := initQueue()
    17. //队列最大能存储6个元素,最大队尾下标为5
    18. queue.addQueue(100)
    19. queue.addQueue(200)
    20. fmt.Println("入队两个元素")
    21. fmt.Printf("队列: %v, 队头front: %v, 队尾rear: %v\n", queue.QueueArray, queue.Frount, queue.Rear)
    22. v, err := queue.deleteQueue()
    23. if err != nil {
    24. fmt.Println(err)
    25. } else {
    26. fmt.Printf("出队元素: %v, 队头front: %v, 队尾rear: %v\n", v, queue.Frount, queue.Rear)
    27. }
    28. //循环:入队2个元素,出队一个元素
    29. fmt.Println("---循环:入队2个元素,出队一个元素---")
    30. for i := 1; i <= 5; i++ {
    31. fmt.Printf("第%v次循环:\n", i)
    32. err := queue.addQueue(i)
    33. if err != nil {
    34. fmt.Println(err)
    35. break
    36. }
    37. fmt.Printf("队列: %v, 队头front: %v, 队尾rear: %v\n", queue.QueueArray, queue.Frount, queue.Rear)
    38. err = queue.addQueue(i)
    39. if err != nil {
    40. fmt.Println(err)
    41. break
    42. }
    43. fmt.Printf("队列: %v, 队头front: %v, 队尾rear: %v\n", queue.QueueArray, queue.Frount, queue.Rear)
    44. queue.deleteQueue()
    45. fmt.Printf("队列: %v, 队头front: %v, 队尾rear: %v\n", queue.QueueArray, queue.Frount, queue.Rear)
    46. }
    47. }
    48. //队列初始化
    49. func initQueue() (queue *Queue) {
    50. //初始化队列
    51. queue = &Queue{
    52. Frount: 0,
    53. Rear: -1,
    54. MaxSize: 6,
    55. QueueArray: [6]int{},
    56. }
    57. return queue
    58. }
    59. //队列-入队
    60. func (q *Queue) addQueue(v int) error {
    61. //判断循环队列是否已满
    62. if q.Rear-q.Frount+1 == q.MaxSize {
    63. return errors.New("循环队列已满")
    64. }
    65. q.Rear += 1 //队尾下标+1
    66. q.QueueArray[q.Rear%q.MaxSize] = v //数据入队尾;rear与MaxSize去模,获取实际数组下标
    67. return nil
    68. }
    69. //队列-出队
    70. func (q *Queue) deleteQueue() (int, error) {
    71. //判断循环队列否为空
    72. if q.Rear-q.Frount == -1 {
    73. return -1, errors.New("队列为空")
    74. }
    75. v := q.QueueArray[q.Frount%q.MaxSize] //获取队列头部元素值;front与MaxSize去模,获取实际数组下标
    76. q.QueueArray[q.Frount%q.MaxSize] = 0 //出队数据置为0
    77. q.Frount += 1 //队头下标+1
    78. return v, nil
    79. }

     

    如果用非循环队列,数组容量为6,rear为5时就无法再入队元素了。使用了循环队列,只要数组中还有空间,就可以一直循环入队元素。上述例子中rear最终达到了10,也就是一共有11个元素成功入队,充分利用了空间。

     

    3.队列的链式存储结构

    队列也可以使用一个单链表实现。插入和删除操作分别在链表的两端进行。

    链表的特点是:在链表的头部,做插入、删除操作都方便;在链表的尾部,做插入操作方便,做删除操作不方便。

    • 在链表头部进行出队操作
    • 在链表尾部进行入队操作
    • 需要front和rear分别指向链的头节点的和尾节点。当front不指向任何节点时,队列为空。

    3.1 队列的链式存储结构-结构体定义

    1. //队列-链式存储结构-结构体
    2. type LinkQueue struct {
    3. Frount *QueueNode
    4. Rear *QueueNode
    5. }
    6. //队列-链式存储结构-每个结点结构体
    7. type QueueNode struct {
    8. data int
    9. next *QueueNode
    10. }

    3.2 队列的链式存储结构-队列初始化

    1. func initQueue() (queue *LinkQueue) {
    2. //初始化队列
    3. queue = &LinkQueue{
    4. Frount: nil,
    5. Rear: nil,
    6. }
    7. return queue
    8. }

    3.3 队列的链式存储结构-入队

    1. func (lq *LinkQueue) addQueue(v int) {
    2. //链式存储结构,暂不考虑队列是否已满
    3. //新建入队节点
    4. newNode := &QueueNode{
    5. data: v,
    6. next: nil,
    7. }
    8. //如果Frount为空,表明为入队的第一个节点
    9. if lq.Frount == nil {
    10. lq.Frount = newNode
    11. lq.Rear = newNode
    12. }
    13. //原队尾指向新入队节点
    14. lq.Rear.next = newNode
    15. lq.Rear = newNode
    16. }

    3.4 队列的链式存储结构-出队

    1. func (lq *LinkQueue) deleteQueue() (int, error) {
    2. //判断循环队列否为空
    3. if lq.Frount == nil {
    4. return -1, errors.New("队列为空")
    5. }
    6. v := lq.Frount.data //获取队列头部元素值
    7. lq.Frount = lq.Frount.next //frount指向下一个结点
    8. return v, nil
    9. }

    3.5 完整代码 

    1. package main
    2. import (
    3. "errors"
    4. "fmt"
    5. )
    6. type LinkQueue struct {
    7. Frount *QueueNode
    8. Rear *QueueNode
    9. }
    10. type QueueNode struct {
    11. data int
    12. next *QueueNode
    13. }
    14. func main() {
    15. //初始化队列
    16. queue := initQueue()
    17. //循环入队&出队
    18. fmt.Println("---入队---")
    19. for i := 100; i <= 105; i++ {
    20. queue.addQueue(i)
    21. fmt.Println("入队元素:", queue.Rear.data)
    22. }
    23. fmt.Println("---出队---")
    24. for queue.Frount != nil {
    25. v, err := queue.deleteQueue()
    26. if err != nil {
    27. fmt.Println(err)
    28. } else {
    29. fmt.Println("出队元素:", v)
    30. }
    31. }
    32. }
    33. //队列初始化
    34. func initQueue() (queue *LinkQueue) {
    35. //初始化队列
    36. queue = &LinkQueue{
    37. Frount: nil,
    38. Rear: nil,
    39. }
    40. return queue
    41. }
    42. //队列-入队
    43. func (lq *LinkQueue) addQueue(v int) {
    44. //链式存储结构,暂不考虑队列是否已满
    45. //新建入队节点
    46. newNode := &QueueNode{
    47. data: v,
    48. next: nil,
    49. }
    50. //如果Frount为空,表明为入队的第一个节点
    51. if lq.Frount == nil {
    52. lq.Frount = newNode
    53. lq.Rear = newNode
    54. }
    55. //原队尾指向新入队节点
    56. lq.Rear.next = newNode
    57. lq.Rear = newNode
    58. }
    59. //队列-出队
    60. func (lq *LinkQueue) deleteQueue() (int, error) {
    61. //判断循环队列否为空
    62. if lq.Frount == nil {
    63. return -1, errors.New("队列为空")
    64. }
    65. v := lq.Frount.data //获取队列头部元素值
    66. lq.Frount = lq.Frount.next //frount指向下一个节点
    67. return v, nil
    68. }

     

  • 相关阅读:
    制作温馨浪漫爱心表白动画特效HTML5+jQuery【附源码】
    6部署AD域
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校学生社团管理系统9p5w4
    mac系统安装搭载Windows系统虚拟机方法教程
    Redis的配置、启动、操作和关闭
    Element Plus 的下拉选择器el-option的字体全部蓝色,全部是选中状态
    微信小程序 - WXML 模板语法 - 事件绑定
    C++ Reference: Standard C++ Library reference: C Library: cstdio: ftell
    日志开源组件(六)Adaptive Sampling 自适应采样
    正点原子 核心板IMX6ULL IIC RTC驱动 PCF8563
  • 原文地址:https://blog.csdn.net/qq522044637/article/details/126158885