当前位置:   article > 正文

头歌C语言数据结构课程实验(队列的应用)_头歌 循环队列

头歌 循环队列

第1关:循环队列

任务描述

本关任务:编写一个循环队列,实现入队、出队操作,判断队空、队满等特殊情况。

相关知识

为了完成本关任务,你需要掌握:1.循环队列定义,2.入队、出队的定义,3.队空、队满的情况。

循环队列定义

循环队列将数组存储区看成是一个首尾相接的环形区域(下图)。当数据存放到尾地址后,下一个地址就跳转到首地址。循环队列定义如下:

 
  1. struct Queue{
  2. int maxSize; // 队列最大长度
  3. int *data; // 数据指针
  4. int front; // 头指针索引
  5. int rear; // 尾指针索引
  6. };

入队出队定义

入队操作:队列未满,在队尾插入一个元素item,使得data[rear+1]=item,若超过存储空间则尾指针索引取模(rear+1)%maxSize

出队操作:队列不空,返回队首元素值data[front],并移除队首元素front+1,若超过存储空间则头指针索引取模(front+1)%maxSize

队空队满情况

初始化创建空队时,令front=rear=0, 其中front指向队首元素,rear指向队尾元素的下一个元素:

  • 当队空时:front==rear
  • 当队满时:front==rear 亦成立

因此只凭等式front==rear无法判断队空还是队满。 一个方法是少用一个元素空间,约定:队列头指针front在队尾指针rear的下一个位置上作为队列“满”状态的标志(如上图),即:

  • 队空时: front==rear
  • 队满时: (rear+1)%maxSize==front
编程要求

本关的编程任务是补全右侧代码片段isFullisEmptyenQueuedeQueueBeginEnd中间的代码,具体要求如下:

  • isFull中,判断队列是否为满,若满返回true并在一行打印The queue is Full,否则返回false
  • isEmpty中,判断队列是否为空,若空返回true并在一行打印The queue is Empty,否则返回false
  • enQueue中,实现入队操作:将元素item加入队列尾部;
  • deQueue中,实现出队操作:移除队列首部元素,并返回元素值。
测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入: 10 7 enqueue 30 enqueue 98 dequeue enqueue 96 dequeue dequeue enqueue 0 预期输出: 0 The queue is Empty

输入说明: 第一行n m分别表示循环队列大小、入队出队操作记录数量。 接下来m行,enqueue表示入队操作,后面接待入队元素;dequeue表示出队操作。

输出说明: 输出m个操作之后的所有队列元素。


开始你的任务吧,祝你成功!

  1. //
  2. // queue_.cpp
  3. // Queue
  4. //
  5. // Created by ljpc on 2018/5/29.
  6. // Copyright © 2018年 ljpc. All rights reserved.
  7. //
  8. #include "queue_.h"
  9. void creatQueue(Queue* que, int maxSize)
  10. // 创建一个循环队列指针que,队列最大长度为maxSize
  11. {
  12. que->maxSize = maxSize;
  13. que->data = (int*)malloc(maxSize * sizeof(int));
  14. que->front = que->rear = 0;
  15. }
  16. void destroyQueue(Queue* que)
  17. // 释放队列内存空间
  18. {
  19. free(que->data);
  20. }
  21. bool isFull(Queue* que)
  22. // 判断队列que是否为满
  23. // 若满返回 true 并在一行打印 The queue is Full 末尾换行!!!
  24. // 否则返回 false
  25. {
  26. // 请在这里补充代码,完成本关任务
  27. /********** Begin *********/
  28. if ((que->rear+1) % que->maxSize == que->front)
  29. {
  30. printf("The queue is Full\n");
  31. return true;
  32. }
  33. else return false;
  34. /********** End **********/
  35. }
  36. bool isEmpty(Queue* que)
  37. // 判断队列que是否为空
  38. // 若空返回 true 并在一行打印 The queue is Empty 末尾换行!!!
  39. // 否则返回 false
  40. {
  41. // 请在这里补充代码,完成本关任务
  42. /********** Begin *********/
  43. if ((que->rear) % que->maxSize == que->front)
  44. {
  45. printf("The queue is Empty\n");
  46. return true;
  47. }
  48. else
  49. return false;
  50. /********** End **********/
  51. }
  52. int enQueue(Queue* que, int item)
  53. // 实现入队操作:将元素item加入队列que尾部
  54. // 若队列没满,编写加入操作,返回 1
  55. // 若队列满了,不做任何操作,返回 -1
  56. {
  57. // 请在这里补充代码,完成本关任务
  58. /********** Begin *********/
  59. if (isFull(que))
  60. {
  61. return -1;
  62. }
  63. else
  64. {
  65. que->data[que->rear] = item;
  66. que->rear=(que->rear+1)%que->maxSize;
  67. return 1;
  68. }
  69. /********** End **********/
  70. }
  71. int deQueue(Queue* que)
  72. // 实现出队操作:移除队列que首部元素,并返回元素值
  73. {
  74. // 请在这里补充代码,完成本关任务
  75. /********** Begin *********/
  76. int x;
  77. if (isEmpty(que))
  78. {
  79. return false;
  80. }
  81. else
  82. {
  83. x = que->data[que->front];
  84. que->front = (que->front + 1) % que->maxSize;
  85. }
  86. return x;
  87. /********** End **********/
  88. }
  89. void printQueue(Queue* que)
  90. // 打印队列
  91. {
  92. while (isEmpty(que)==false) {
  93. int item = deQueue(que);
  94. printf("%d ", item);
  95. }
  96. }

第2关:链队列

任务描述

本关任务:编写一个链队列,实现入队、出队操作,判断队空等特殊情况。

相关知识

为了完成本关任务,你需要掌握:1.链队列定义,2.入队、出队的定义,3.队空的情况。

链队列定义

链队列的定义是在单链表的基础上,增加一个尾指针。队列的特点是“先进先出”,因此只需要一头一尾两个指针,就可以快速地在队头取出数据,在队尾插入数据。

链队列动态创建节点,不需要预设大小,内存空间不需要连续,入队、出队更容易实现。但是存取速度慢,操作也比数组的方式更加复杂。

 
  1. struct Node // 数据节点
  2. {
  3. int data; // 数据类型
  4. Node *next; // 指向下一个节点的指针
  5. };
  6. struct LinkQueue // 链表队列
  7. {
  8. Node *front; // 头指针
  9. Node *rear; // 尾指针
  10. };

入队出队定义

入队操作:

  • 第一步:为待入队元素创建数据节点Node* node
  • 第二步:将队尾节点next指向新节点rear->next = node;
  • 第三步:修改队尾指针rear指向新节点rear = node

出队操作:队列不空,返回队首元素值。

  • 第一步:获取队首节点Node *node = front->next,注意front->next才是指向队列头节点,front本身不具备任何意义。
  • 第二步:移除队首节点,修改front->next = node->next
  • 特殊情况:当队列最后一个元素被删除后,队列尾指针也丢失了,因此需对队尾指针重新赋值,即指向头结点 rear = front
队空情况

初始化创建空队时,令rear = front,即队空的情况是rear == front

编程要求

本关的编程任务是补全右侧代码片段isEmptyenQueuedeQueueBeginEnd中间的代码,具体要求如下:

  • isEmpty中,判断队列是否为空,若空返回true并在一行打印The queue is Empty,否则返回false
  • enQueue中,实现入队操作:将元素item加入队列尾部;
  • deQueue中,实现出队操作:移除队列首部元素,并返回元素值。
测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入: 7 enqueue 30 enqueue 98 dequeue enqueue 96 dequeue dequeue enqueue 0 预期输出: 0 The queue is Empty

输入说明: 第一行m分别表示链队列入队出队操作记录数量。 接下来m行,enqueue表示入队操作,后面接待入队元素;dequeue表示出队操作。

输出说明: 输出m个操作之后的所有队列元素。


开始你的任务吧,祝你成功!

  1. //
  2. // queue_.cpp
  3. // LinkQueue
  4. //
  5. // Created by ljpc on 2018/5/30.
  6. // Copyright © 2018年 ljpc. All rights reserved.
  7. //
  8. #include "queue_.h"
  9. void creatLinkQueue(LinkQueue* que)
  10. // 创建一个循环队列指针que
  11. {
  12. que->front = (Node*)malloc(sizeof(Node));
  13. que->rear = que->front;
  14. que->rear->next = NULL;
  15. }
  16. bool isEmpty(LinkQueue* que)
  17. // 判断队列que是否为空
  18. // 若空返回 true 并在一行打印 The queue is Empty 末尾换行!!!
  19. // 否则返回 false
  20. {
  21. // 请在这里补充代码,完成本关任务
  22. /********** Begin *********/
  23. if (que->rear == que->front)
  24. {
  25. printf("The queue is Empty\n");
  26. return true;
  27. }
  28. return false;
  29. /********** End **********/
  30. }
  31. void enQueue(LinkQueue* que, int item)
  32. // 实现入队操作:将元素item加入队列que尾部
  33. {
  34. // 请在这里补充代码,完成本关任务
  35. /********** Begin *********/
  36. Node *newque=(Node*)malloc(sizeof(Node));
  37. if(newque!=NULL)
  38. {
  39. newque->data=item;
  40. newque->next=NULL;
  41. que->rear->next=newque;
  42. que->rear=newque;
  43. }
  44. /********** End **********/
  45. }
  46. int deQueue(LinkQueue* que)
  47. // 实现出队操作:移除队列que首部元素,并返回元素值
  48. {
  49. // 请在这里补充代码,完成本关任务
  50. /********** Begin *********/
  51. int x;
  52. Node* p = que->front->next;
  53. x = p->data;
  54. que->front->next = p->next;
  55. if (p == que->rear)
  56. {
  57. que->rear = que->front;
  58. }
  59. return x;
  60. /********** End **********/
  61. }
  62. void printQueue(LinkQueue* que)
  63. // 打印队列
  64. {
  65. while (isEmpty(que)==false) {
  66. int item = deQueue(que);
  67. printf("%d ", item);
  68. }
  69. }

第3关:单链表循环队列

任务描述

本关任务:编写一个单链表循环队列,实现入队、出队操作,判断队空等特殊情况。

相关知识

为了完成本关任务,你需要掌握:1.单链表循环队列定义,2.入队、出队的定义,3.队空的情况。

单链表循环队列

单链表循环队列设一个尾指针rear,不设头指针。队尾添加数据的时候,只需要在rearrear->next之间插入该数据节点,然后将rear指向这个节点。因为没有头指针,所以添加一个整形变量size_来判定队列空的情况。

 
  1. struct Node // 数据节点
  2. {
  3. int data; // 数据类型
  4. Node *next; // 指向下一个节点的指针
  5. };
  6. struct CycleQueue // 循环链表队列
  7. {
  8. int size_; // 目前队列元素个数
  9. Node *rear; // 尾指针
  10. };
入队出队定义

注意初始队列时,尾指针rear = NULL以及rear->next = NULL

入队操作:

  • 为待入队元素创建数据节点Node* node
  • 如果队列为空,则尾节点指向新节点rear = noderear->next指向队首节点rear->next = node
  • 如果队列非空,则在rearrear->next之间插入新节点:
     
      
    1. Node *temp = rear->next;
    2. rear->next = node;
    3. node->next = temp;
    4. rear = node;
    5. rear->next = temp;

出队操作:队列不空,返回队首元素值。

  • 第一步:获取队首节点Node *node = rear->next;
  • 第二步:移除队首节点,修改rear->next = node->next
队空情况

队列中不含数据节点,通过变量size_来判定队列空的情况。

编程要求

本关的编程任务是补全右侧代码片段isEmptyenQueuedeQueueBeginEnd中间的代码,具体要求如下:

  • isEmpty中,判断队列是否为空,若空返回true并在一行打印The queue is Empty,否则返回false
  • enQueue中,实现入队操作:将元素item加入队列尾部;
  • deQueue中,实现出队操作:移除队列首部元素,并返回元素值。
测试说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是平台的测试样例:

测试输入: 7 enqueue 30 enqueue 98 dequeue enqueue 96 dequeue dequeue enqueue 0 预期输出: 0 The queue is Empty

输入说明: 第一行m分别表示链队列入队出队操作记录数量。 接下来m行,enqueue表示入队操作,后面接待入队元素;dequeue表示出队操作。

输出说明: 输出m个操作之后的所有队列元素。


开始你的任务吧,祝你成功!

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #pragma warning(disable:6031)
  3. //
  4. // queue_.cpp
  5. // Cycle
  6. //
  7. // Created by ljpc on 2018/5/30.
  8. // Copyright © 2018年 ljpc. All rights reserved.
  9. //
  10. #include "queue_.h"
  11. void creatCycleQueue(CycleQueue* que)
  12. // 创建一个循环队列指针que
  13. {
  14. que->size_ = 0;
  15. que->rear = NULL;
  16. }
  17. bool isEmpty(CycleQueue* que)
  18. // 判断队列que是否为空
  19. // 若空返回 true 并在一行打印 The queue is Empty 末尾换行!!!
  20. // 否则返回 false
  21. {
  22. // 请在这里补充代码,完成本关任务
  23. /********** Begin *********/
  24. if (que->size_ == 0)
  25. {
  26. printf("The queue is Empty\n");
  27. return true;
  28. }
  29. return false;
  30. /********** End **********/
  31. }
  32. void enQueue(CycleQueue* que, int item)
  33. // 实现入队操作:将元素item加入队列que尾部
  34. {
  35. // 请在这里补充代码,完成本关任务
  36. /********** Begin *********/
  37. Node* newque = (Node*)malloc(sizeof(Node));
  38. newque->data = item;
  39. if (que->size_ > 0)
  40. {
  41. newque->next = que->rear->next;
  42. que->rear->next = newque;
  43. que->rear = newque;
  44. que->size_++;
  45. }
  46. else
  47. {
  48. que->rear = newque;
  49. que->rear->next = newque;
  50. que->size_++;
  51. }
  52. /********** End **********/
  53. }
  54. int deQueue(CycleQueue* que)
  55. // 实现出队操作:移除队列que首部元素,并返回元素值
  56. {
  57. // 请在这里补充代码,完成本关任务
  58. /********** Begin *********/
  59. Node* p;
  60. int x;
  61. if (isEmpty(que))
  62. {
  63. return false;
  64. }
  65. if (que->size_ == 1)
  66. {
  67. x = que->rear->data;
  68. p = que->rear;
  69. que->rear = NULL;
  70. free(p);
  71. }
  72. if (que->size_ > 1)
  73. {
  74. p = que->rear->next;
  75. que->rear->next = p->next;
  76. x = p->data;
  77. free(p);
  78. }
  79. que->size_--;
  80. return x;
  81. /********** End **********/
  82. }
  83. void printQueue(CycleQueue* que)
  84. // 打印队列
  85. {
  86. while (isEmpty(que) == false) {
  87. int item = deQueue(que);
  88. printf("%d ", item);
  89. }
  90. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号