循环队列的基本操作
实验目的
通过该实验,使学生理解循环队列的构造特点并灵活应用,掌握循环队列基本操作的编程实现,认识队列是在一端进行插入,在另一端进行删除集中操作的线性结构,掌握队列的“先入先出”操作特点,知道判断队列空和满的条件,进一步熟悉C语言中指针操作。
实验内容
用顺序存储结构,实现教材定义的循环队列的基本操作。
参考界面
验收/测试用例
通过菜单调用各个操作,测试点:
- 没有初始化前进行其他操作,程序是否能控制住;
- 初始化一个队列;
- 判队列空,屏幕显示队列为空;
- 4个数入队, 1、2、3、5;
- 队列长度,屏幕输出4;
- 出队,再判队列长度;
- 销毁队,再做其他操作,判断程序是否能控制。
参考代码
// From:TengMMVP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXQSIZE 100
typedef int QElemType;
// 循环队列结构体定义
typedef struct {
QElemType *base;
int front;
int rear;
} SqQueue;
// 函数声明
int InitQueue(SqQueue *Q);
int DestroyQueue(SqQueue *Q);
int ClearQueue(SqQueue *Q);
int QueueEmpty(SqQueue Q);
int QueueLength(SqQueue Q);
int GetHead(SqQueue Q, QElemType *e);
int EnQueue(SqQueue *Q, QElemType e);
int DeQueue(SqQueue *Q, QElemType *e);
void QueueTraverse(SqQueue Q);
int CreateQueue(SqQueue *Q);
// From:TengMMVP
// 主函数
int main() {
SqQueue Q;
int op = 0, flag = 0, result;
QElemType e;
while (1) {
printf("\n*******************循环队列*******************\n");
printf("1. 初始化并创建队列 2. 初始化队列\n");
printf("3. 销毁队列 4. 清空队列\n");
printf("5. 判断队列是否为空 6. 返回队列中元素个数\n");
printf("7. 返回队列队头元素 8. 插入新的队尾元素\n");
printf("9. 删除队头元素 10.输出队列元素\n");
printf("11.退出程序 From:TengMMVP\n");
printf("**********************************************\n");
printf("请输入操作码:");
scanf("%d", &op);
if (op == 11) break; // 操作码为11,直接退出程序,不继续进行其他操作
if(op < 1 || op > 11) { // 范围之外的操作码无效,输出提示信息
printf("操作码无效,请重新输入!\n");
continue;
}
// 在没有初始化之前和销毁后,只能执行初始化创建队列、初始化队列和退出程序
if ((flag == 0 || flag == 3) && op != 1 && op != 2 ) {
printf("队列未初始化或已经被销毁,无法进行相关操作!\n");
continue;
}
switch (op) {
case 1: // 初始化并创建队列
result = CreateQueue(&Q);
if (result) {
flag = 1; // 表示已创建并初始化
printf("队列创建并初始化成功。\n");
} else {
printf("队列创建或初始化失败!\n");
}
break;
case 2: // 初始化队列
result = InitQueue(&Q);
if (result) {
flag = 1;
printf("队列初始化成功。\n");
} else {
printf("队列初始化失败!\n");
}
break;
case 3: // 销毁队列
result = DestroyQueue(&Q);
if (result) {
flag = 3; // 表示已销毁
printf("队列销毁成功。\n");
} else {
printf("队列销毁失败!\n");
}
break;
case 4: // 清空队列
result = ClearQueue(&Q);
if (result) {
printf("队列清空成功。\n");
} else {
printf("队列清空失败!\n");
}
break;
case 5: // 判断队列是否为空
result = QueueEmpty(Q);
if (result) {
printf("队列为空。\n");
} else {
printf("队列不为空。\n");
}
break;
case 6: // 返回队列中元素个数
result = QueueLength(Q);
printf("队列中元素个数为:%d。\n", result);
break;
case 7: // 返回队列队头元素
result = GetHead(Q, &e);
if (result) {
printf("队头元素为:%d。\n", e);
} else {
printf("获取队头元素失败。\n");
}
break;
case 8: // 插入新的队尾元素
printf("请输入要插入的元素:");
scanf("%d", &e);
result = EnQueue(&Q, e);
if (result) {
printf("元素 %d 插入成功。\n",e);
} else {
printf("元素 %d 插入失败!\n",e);
}
break;
case 9: // 删除队头元素
result = DeQueue(&Q, &e);
if (result) {
printf("删除成功,删除的元素为:%d。\n", e);
} else {
printf("删除失败!\n");
}
break;
case 10: // 输出队列元素
QueueTraverse(Q);
break;
default:
printf("操作码无效,请重新输入!\n");
}
}
return 0;
}
// From:TengMMVP
// 函数实现
// 初始化队列
int InitQueue(SqQueue *Q) {
// 为循环队列分配内存
Q->base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
// 分配内存失败
if (!Q->base) {
return 0;
}
Q->front = Q->rear = 0;
return 1; // 初始化成功
}
// 初始化并创建队列
int CreateQueue(SqQueue *Q) {
// 初始化队列
if (!InitQueue(Q)) {
return 0; // 初始化失败
}
printf("请输入将要输入的元素个数:");
int num;
scanf("%d", &num);
// 检查输入的数字是否超出队列容量
if (num < 1 || num > MAXQSIZE) {
printf("输入的元素个数不合法,必须在1到%d之间。\n", MAXQSIZE);
return 0; // 返回失败
}
printf("请连续输入%d个元素,以空格分隔:", num);
QElemType element;
int count = 0;
for (int i = 0; i < num; i++) {
scanf("%d", &element);
if (!EnQueue(Q, element)) {
printf("队列已满,无法添加更多元素。\n");
return 0; // 返回失败
}
count++;
}
if (count != num) {
printf("输入的元素数量与预期不符,预期数量为%d,实际数量为%d。\n", num, count);
return 0;
}
return 1; // 创建成功
}
// 销毁队列
int DestroyQueue(SqQueue *Q) {
if (Q->base) {
free(Q->base);
Q->base = NULL;
Q->front = Q->rear = 0;
return 1; // 销毁成功
}
return 0; // 销毁失败
}
// 清空队列
int ClearQueue(SqQueue *Q) {
Q->front = Q->rear = 0;
return 1; // 清空成功
}
// 判断队列是否为空
int QueueEmpty(SqQueue Q) {
return Q.front == Q.rear;
}
// 返回队列中元素个数
int QueueLength(SqQueue Q) {
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
// 返回队列队头元素
int GetHead(SqQueue Q, QElemType *e) {
if (Q.front == Q.rear) return 0; // 队列为空
*e = Q.base[Q.front];
return 1;
}
// 插入新的队尾元素
int EnQueue(SqQueue *Q, QElemType e) {
if ((Q->rear + 1) % MAXQSIZE == Q->front) return 0; // 队列满
Q->base[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXQSIZE;
return 1;
}
// From:TengMMVP
// 删除队头元素
int DeQueue(SqQueue *Q, QElemType *e) {
if (Q->front == Q->rear) return 0; // 队列为空
*e = Q->base[Q->front];
Q->front = (Q->front + 1) % MAXQSIZE;
return 1;
}
// 输出队列元素
void QueueTraverse(SqQueue Q) {
if (Q.front == Q.rear) {
printf("队列为空,无元素可显示。\n");
return;
}
int i = Q.front;
while (i != Q.rear) {
printf("%d ", Q.base[i]);
i = (i + 1) % MAXQSIZE;
}
printf("\n");
}
// From:TengMMVP