第9关:循环队列

任务描述

本关任务:假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点(注意不设头指针) ,试编写相应的置空队、判队空 、入队和出队等算法。

相关说明

输入数字代表相应的操作 1.初始化 2.入队 在输入2时,还需要输入入队的元素
3.出队 4.判断队列是否为空 0.退出

测试说明

测试输入: 1 2 a 2 b 3 3 3 4 0

预期输出: 初始化成功 a已入队 b已入队 a已出队 b已出队 队列已空,无可出队元素 此对为空队

#include <iostream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char QElemType;
typedef int Status;


typedef struct QNode {
	QElemType data;
	struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
	QueuePtr rear; //只设队尾指针
} LinkQueue;

void InitQueue(LinkQueue &Q) {//构造一个空队列Q

	//###### Begin ######
	QueuePtr x = new QNode;
	x->next = x;
	Q.rear = x;
	// ###### End ######

}

int EmptyQueue(LinkQueue Q) {
	//###### Begin ######
	return Q.rear == Q.rear->next;
	// ###### End ######
}

Status EnQueue(LinkQueue &Q, QElemType e) {
	//###### Begin ######
	QueuePtr x = new QNode;
	x->data = e;
	x->next = Q.rear->next; //循环队列;
	Q.rear->next = x;
	Q.rear = x;
	return OK;
	// ###### End ######
}

Status DeQueue(LinkQueue &Q, QElemType &e) {
	//###### Begin ######
	if (EmptyQueue(Q)) {
		return ERROR;
	}
	QueuePtr x = Q.rear->next;
	QueuePtr y = x->next;
	e = y->data;
	x->next = y->next;
	if (x->next == x)
		Q.rear = x;
	free(y);
	return OK;
	// ###### End ######
}

main() {
	int choose, flag = 0;
	LinkQueue q;
	QElemType j;

	choose = -1;
	while (choose != 0) {

		cin >> choose;
		switch (choose) {
			case 1:
				InitQueue(q);
				flag = 1;
				cout << "初始化成功\n";
				break;
			case 2:
				if (flag) {
					flag = 1;

					cin >> j;
					EnQueue(q, j);
					cout << j << "已入队\n";
				} else
					cout << "队列未建立,请重新选择\n\n";
				break;
			case 3:
				if (flag) {
					flag = 1;
					if (DeQueue(q, j))
						cout << j << "已出队\n";
					else
						cout << "队列已空,无可出队元素\n";
				} else
					cout << "队列未建立,请重新选择\n\n";
				break;
			case 4:
				if (EmptyQueue(q))
					cout << "此对为空队\n";
				else
					cout << "此对不空\n";
				break;
		}
	}
}

题目非原创,为头歌所见,侵删。
答案为作者原创。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是循环队列删除队头第k个元素的代码实现: ``` #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; int front, rear; } Queue; void initQueue(Queue *q) { q->front = q->rear = 0; } int isEmpty(Queue *q) { return q->front == q->rear; } int isFull(Queue *q) { return (q->rear + 1) % MAX_SIZE == q->front; } int enqueue(Queue *q, int x) { if (isFull(q)) { return 0; } q->data[q->rear] = x; q->rear = (q->rear + 1) % MAX_SIZE; return 1; } int dequeue(Queue *q, int k) { if (isEmpty(q)) { return -1; } int i; for (i = 0; i < k - 1; i++) { q->front = (q->front + 1) % MAX_SIZE; } int x = q->data[q->front]; q->front = (q->front + 1) % MAX_SIZE; return x; } int main() { Queue q; initQueue(&q); int i; for (i = 1; i <= 10; i++) { enqueue(&q, i); } int k = 3; int x = dequeue(&q, k); printf("删除队头第%d个元素:%d\n", k, x); while (!isEmpty(&q)) { printf("%d ", dequeue(&q, 1)); } printf("\n"); return 0; } ``` 输出结果为: ``` 删除队头第3个元素:3 1 2 4 5 6 7 8 9 10 ``` 这段代码实现了循环队列的基本操作,并且可以删除队头第k个元素。 ### 回答2: 循环队列的删除操作可以分为两个步骤来实现:定位要删除的元素位置和删除该元素。 首先,我们需要定位要删除的元素位置。由于循环队列是一个环形结构,我们需要考虑队头和队尾可能存在的"跨越"情况。为了方便计算,我们可以假设队头的索引为0,那么队尾的索引为队列的长度减1。根据这个假设,我们可以使用以下公式计算要删除的元素位置: 删除元素位置 = (队头位置 + k - 1) % 队列长度 其中,k为要删除的元素的位置,队列长度为队列的实际长度。 接下来,我们需要进行删除元素的操作。删除元素的操作比较简单,只需要将删除元素位置上的元素设为一个空值或者特定的标记即可。在实际编程中,可以使用一个数组来表示循环队列,并将要删除的元素位置上的值设为null或者-1。 最后,需要注意一些特殊情况的处理。例如,如果队列为空或者k的值大于队列长度,那么删除操作无法执行。此外,如果循环队列存在动态变化(例如入队和出队操作),那么需要及时更新队头位置。 总之,设计删除循环队列中从队头开始第k个元素的步骤可以概括为:定位要删除的元素位置和删除该元素。在定位时需要考虑循环队列的环形结构和特殊情况的处理,在删除操作中需要将删除位置上的元素设为空值。 ### 回答3: 循环队列是一种环形的数据结构,可以在固定大小的队列中依次存储数据,并且可以通过循环利用空间来提高效率。 设计删除队列中从队头开始第k个元素的算法如下: 1. 首先,需要判断队列是否为空。如果队列为空,则无法删除元素,返回错误提示。 2. 判断k的合法性。如果k小于等于0或者大于队列中的元素数量,也返回错误提示。 3. 设置两个指针:一个指向队头元素的位置(head),一个指向队尾元素的下一个位置(tail)。 4. 判断k与队列中元素的位置系: a. 如果k小于等于队头元素和队尾元素之间的距离,则直接将队头指针后移k个位置。即:head = (head + k) % 队列长度。 b. 如果k大于队头元素和队尾元素之间的距离,要注意循环利用空间的情况。首先将head移到队尾元素的下一个位置:head = (tail + 1) % 队列长度。然后再将head后移k个位置:head = (head + (k - 距离)) % 队列长度。 5. 返回删除成功的标志。 需要注意的是,当队列中只有一个元素时,无论k是多少,删除后队列为空。 以上是删除循环队列中从队头开始第k个元素的算法设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值