任务描述
本关任务:实现step2/CLnkQueue.cpp
中的CLQ_IsEmpty
、CLQ_Length
、CLQ_In
和CLQ_Out
四个操作函数,以实现判断队列是否为空、求队列长度、队列元素入队和出队等功能。
相关知识
链式队列的定义
队列的存储除了顺序存储之外也可以采用链接存储方式来实现。下面描述了队列的链接存储实现方案。
该队列存储了 3 个元素 {56,77,15} ,其中 56 为队列头, 15 为队列尾。
这种实现方案中涉及到的两个属性元素如下:
rear
: 指向队列尾结点的指针;next
: 指向队列头结点的指针。
特别说明:空间的开始地址为
data
,连续空间里的位置编号从data
所指的开始位置起,到该空间的结束位置,编号依次是0,1,2,…,max-1
。在图1的示例中max=6
。下一个出队元素(这里是队列的头结点)所存储的位置编号用front
给出,下一个入队元素应存储的位置编号用rear
给出。
当队列是空队列时,rear
指向附加头结点,附加头结点的数据项等于 0 ,如图2所示。
基于这些属性要素组织成的链表结点的结构定义为:
struct LNode {
T data;
LNode* next;
};
为了讨论简单,我们假设队列元素的数据类型为整数:
typedef int T; // 队列元素的数据类型
据此,只要给定rear
指针,我们就可以对队列进行入队和出队的操作。
- 在给定图1的状态下,进队一个元素 25 以后的状态如图3所示:
- 若出队一个元素是指将当前队列头结点去掉。则在给定图3的状态下,进行一次出队后的状态如图4所示:
链式队列的主要操作
对数据元素进行操作处理是一个数据结构的重要组成部分。队列涉及的主要操作如下:
-
创建队列:创建一个队列。具体操作函数定义如下:
LNode* CLQ_Create()
; -
释放队列空间:释放队列所占用的空间,其中
rear
指向尾结点。具体操作函数定义如下:void CLQ_Free(LNode* rear)
; -
置空队列:将队列变为空队列,其中
rear
指向尾结点。具体操作函数定义如下:void CLQ_MakeEmpty(LNode* & rear)
; -
判断队列是否为空:若队列为空,则返回
true
,否则返回false
。具体操作函数定义如下:bool CLQ_IsEmpty(LNode* rear)
; -
求队列长度:获取队列的长度,其中
rear
指向尾结点。具体操作函数定义如下:int CLQ_Length(LNode* rear)
; -
新结点入队列:新结点加入链表尾部,其中
rear
指向尾结点。具体操作函数定义如下:void CLQ_In(LNode* & rear, T x)
; -
队列元素出队列:
item
为出队的元素的值。若出队成功(队列不为空),则返回true
;否则(队列空),返回false
。具体操作函数定义如下:bool CLQ_Out(LNode* & rear, T& item)
; -
获取队列头结点元素:若获取失败(队列空),则返回值为
false
,否则返回值为true
。具体操作函数定义如下:bool CLQ_Head(LNode* rear, T& item)
; -
打印队列:依次打印出队列中的每个元素。具体操作函数定义如下:
void CLQ_Print(LNode* rear)
。
编程要求
本关任务是实现step2/CLnkQueue.cpp
中的CLQ_IsEmpty
、CLQ_Length
、CLQ_In
和CLQ_Out
四个操作函数,以实现判断队列是否为空、求队列长度、队列元素入队和出队等功能。具体要求如下:
-
CLQ_IsEmpty
:判断队列是否为空,若队列为空,则返回true
,否则返回false
; -
CLQ_Length
:获取队列的长度; -
CLQ_In
:新结点加入链表尾部; -
CLQ_Out
:队列元素出队列,若出队成功(队列不为空),则返回true
;否则(队列空)返回false
; -
输入输出格式请参见后续说明及测试样例。
注意:本关必读中提及的其他操作已经由平台实现,你在实现本关任务的四个操作函数时,在函数体内可调用其他操作。
本关涉及的代码文件CLnkQueue.cpp
中的4个操作函数的代码框架如下:
bool CLQ_IsEmpty(LNode* rear)
// 判断队列是否为空
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
/********** End **********/
}
int CLQ_Length(LNode* rear)
// 返回队列长度,rear指向尾结点
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
/********** End **********/
}
void CLQ_In(LNode* & rear, T x)
// 入队列, 新结点加入链表尾部。rear指向尾结点
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
/********** End **********/
}
bool CLQ_Out(LNode* & rear, T& item)
// 出队列。空队列时,返回值为false。rear指向尾结点
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
/********** End **********/
}
测试说明
本关的测试文件是step2/Main.cpp
,负责对你实现的代码进行测试。具体代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CLnkQueue.h"
#pragma warning(disable:4996)
int main()
{
LNode* rear=CLQ_Create();
char dowhat[100];
while(true) {
scanf("%s", dowhat);
if (!strcmp(dowhat,"in")) {
T x;
scanf("%d", &x);
CLQ_In(rear,x);
}else if (!strcmp(dowhat,"out")) {
T item;
CLQ_Out(rear, item);
}
else {
break;
}
}
int length=CLQ_Length(rear);
printf("Queue length: %d\n", length);
printf("Queue data: ");
CLQ_Print(rear);
CLQ_Free(rear);
}
#include <stdio.h>
#include <stdlib.h>
#include "CLnkQueue.h"
LNode* CLQ_Create()
// 创建一个队列。
{
LNode* rear = (LNode*)malloc(sizeof(LNode));
rear->data = 0;
rear->next = rear;
return rear;
}
void CLQ_Free(LNode* rear)
// rear指向尾结点。
{
CLQ_MakeEmpty(rear);
free(rear);
}
void CLQ_MakeEmpty(LNode*& rear)
// rear指向尾结点。
// 将队列变为空队列。
{
T item;
while (!CLQ_IsEmpty(rear))
CLQ_Out(rear, item);
}
bool CLQ_IsEmpty(LNode* rear)
// 判断队列是否为空。
{
// 请在Begin-End之间补充代码,完成队列是否为空的判断。
/********** Begin *********/
return rear->next == rear;
/********** End **********/
}
int CLQ_Length(LNode* rear)
// 返回队列长度,rear指向尾结点。
{
// 请在Begin-End之间补充代码,获取队列长度。
/********** Begin *********/
return rear->next->data;
/********** End **********/
}
void CLQ_In(LNode*& rear, T x)
// 入队列, 新结点加入链表尾部。rear指向尾结点。
{
// 请在Begin-End之间补充代码,完成新结点入队操作。
/********** Begin *********/
LNode* p = new LNode;
p->data = x;
p->next = rear->next;
rear->next = p;
rear = p;
rear->next->data++;
/********** End **********/
}
bool CLQ_Out(LNode*& rear, T& item)
// 出队列。空队列时,返回值为false。rear指向尾结点。
{
// 请在Begin-End之间补充代码,完成结点出队操作。
/********** Begin *********/
if (CLQ_IsEmpty(rear)) return false;
if(rear->next->data==1)
{
rear=rear->next;
rear->next=rear;
rear->data--;
}else
{
LNode* p = rear->next;
p->next = p->next->next;
p->data--;
}
return true;
/********** End **********/
}
bool CLQ_Head(LNode* rear, T& item)
// rear指向尾结点。
// 获取队列头。空队列时返回值为false。
{
if (CLQ_IsEmpty(rear))
return false;
item = rear->next->next->data;
return true;
}
void CLQ_Print(LNode* rear)
// 打印队列。
{
if (CLQ_IsEmpty(rear)) {
printf("The queue is: empty. \n");
return;
}
LNode* node = rear->next->next;
do {
printf("%d ", node->data);
node = node->next;
} while (node != rear->next);
//printf("\n");
}