C/C++队列

一、队列的基本使用

#include<queue>
using namespace std;
queue<int>myQueue;

入队:push
出队:pop
判断为空:empty
队首元素:front

queue<int>myQueue;
for(int i=0;i<5;i++){
	myQueue.push(i);
}
while(true){
	if(myQueue.empty()){
		printf("myQueue is empty!");
		break;
	}
	printf("front of myQueue is %d\n",myQueue.front());
	myQueue.pop();
}

二、问题

1.约瑟夫问题
描述
n个小孩围坐一圈,并被顺时针编号为1,2,…,n,从编号为p的小孩顺时针依次报数。由1报到m,报到m时,这名小孩从圈中出去;然后下一名小孩再从1报数,报到m时再出去,依次类推,直到所有小孩都从圈中出去,请按出去的先后顺序输出小孩的编号
输入:
第一个时n,第二个是p,第三个是m(0<m,n<300)
最后一行是:0 0 0
输出:
按出圈的顺序输出编号,编号之间以逗号间隔
样例

输入:
8 3 4
0 0 0
输出
6,2,7,4,3,5,1,8

解题思路

  • 从p到p-1入队
  • 从队首开始,报数,出队
  • 检查以下,报数是否是m,是不归队,不是归队
    小技巧:循环队列——>先出队再入队
    代码
#include<queue>
#include<cstdio>
using namespace std;
int main() {
	int n, p, m;
	while (true) {
		scanf_s("%d%d%d", &n, &p, &m);
		if (n == 0 && p == 0 && m == 0) {
			break;
		}
		queue<int>children;//孩子的编号
		//把第一轮要喊编号的孩子排好队
		for (int i = p, j = 0; j < n; ++j) {
			//i用来遍历孩子的编号
			//j用来记录已经遍历的孩子的数量
			children.push(i);
			++i;//p->p+1->...->n->1->...->p-1
			if (i > n) {
				i = 1;
			}
		}
		//喊号的过程
		int num = 1;//将要喊的编号
		while (true) {
			int cur = children.front();//cur是队首孩子的编号
			children.pop();//喊完了,队首出队
			if (num == m) {//检查以下刚才喊号的号码是不是m
				num = 1;//下一个同学喊的号就是1
				//喊号的同学不需要归队
				if (children.empty()) {
					printf("%d\n", cur);
					break;
				}else {
					//还有同学再喊号
					printf("%d,", cur);
				}
			}else {
				//需要归队
				num += 1; children.push(cur);
			}
		}
	}
}

2、猫狗收容所
描述:
有家动物收容所只收留猫和狗,但有特殊的收容规则。收养人有两种收养方式:
第一种为直接收养所有动物中最早收入收容所的。
第二种为选择收养动物的类型(猫或狗),并收养该种动物最早进入收容所的
给定一个操作序列代表所有的事件。
若第一个元素为1,则代表有动物进入收容所。第二个元素为动物的编号,正数代表狗,负数代表猫。
若第一个元素为2,则代表有人收养动物。第二个若为0,则采取第一种收养方式;若为1,则指定收养狗;若为-1,则指定收养猫。
请按顺序输出收养动物的序列。
若出现不合法的操作,即没有可以符合领养要求的动物,则将这次领养操作忽略。
输入:
第一个是n,它代表操作序列的次数,接下来是n行,每行有两个值m和t,分别代表题目中操作的两个元素
输出:
按顺序输出收养动物的序列,编号之间以空格间隔
样例

输入:
6
1 1
1 - 1
2 0
1 2
2 -1
2 1
输出:
1 -1 2

解题思路
维护两个队列,cat,dog,两个队列要记录插入的次序
代码

#include<queue>
#include<cstdio>
using namespace std;
struct Animal {
	int num;
	int seq;
};
int main() {
	queue<Animal>catQue;
	queue<Animal>dogQue;
	int seq = 0;
	int n;
	scanf_s("%d", &n);
	for (int i = 0; i < n; i++) {
		int method, para;
		scanf_s("%d%d", &method, &para);
		if (method == 1) {
			//入队 para代表动物的编号
			if (para > 0) {
				//处理狗
				Animal dog;
				dog.num = para;
				dog.seq = seq;
				++seq;
				dogQue.push(dog);
			}
			else {
				//处理猫
				Animal cat;
				cat.num = para;
				cat.seq = seq;
				++seq;
				catQue.push(cat);
			}
		}
		else {
			//出队
			if (para == 0) {
				//不区分猫狗
				//1.无猫无狗
				if (dogQue.empty() && catQue.empty()) {
					continue;//跳过本次循环
				}
				//2.收养狗
				//2.a狗非空,猫空
				//2.b狗非空,猫非空,队首狗的序号小一点
				else if (catQue.empty() ||!dogQue.empty()&& !catQue.empty() && dogQue.front().seq < catQue.front().seq) {
					printf("%d ", dogQue.front().num);
					dogQue.pop();
				}
				else {
					printf("%d ", catQue.front().num);
					catQue.pop();
				}
			}
			else if(para==1){
				//领养狗
				if (dogQue.empty()) {
					continue;
				}
				printf("%d ", dogQue.front().num);
				dogQue.pop();
			}
			else {
				//领养猫

				if (catQue.empty()) {
					continue;
				}
				printf("%d ", catQue.front().num);
				catQue.pop();
			}
			printf("\n");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值