士兵队列训练问题

首先是介绍题目:
某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
输入描述
本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
输出描述
共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
输入样例
2
20
40
输出样例
1 7 19
1 19 37

思考

不知道你看完题目否会打退堂鼓?我一开始的想法是用顺序队列还是链队列,我心目中两个都有对方没有的优点。(两个都能实现的,)
顺序队列优点:我可以直接找到要删除的数字,通过他们的下标。但是输出的时候不太方便。
链队列优点:删除方便,但是不好找到要删除的对象。

后来我先选择的是链队列(顺序队列也可以实现的,大家可以试试),通过两个链队列,不是要删除的数字我把它转移到另外一个队列后进行删除,如果是要删除的数字,就不转移了,直接删除。这里需要一个变量记录队列里面的数字个数为3就输出。

代码

我希望大家把这个题目做出来后,再来看我的代码,这样对自己也有提高。

#include<iostream>
using namespace std;
struct Node
{
int data; //数据域
Node *next; //指针域
};

class LinkQueue
{
public:
LinkQueue( )
{
Node*s = NULL;
   s = new Node;
 s->next = NULL; //创建头结点s
front = rear = s; //将队头指针和队尾指针都指向头结点s
}

void EnQueue(int x)
{
Node*s = NULL;
s = new Node; //申请结点s
s->data = x; s->next = NULL;
rear->next = s; rear = s; //将结点s插入到队尾
}
int DeQueue( )
{
int x;
Node*p = NULL;
if (rear == front) throw "下溢";
p = front->next; x = p->data; //暂存队头元素
front->next = p->next; //将队头元素所在结点摘链
if (p->next == NULL) rear = front; //判断出队前队列长度是否为1
delete p;
return x;
}
 
int GetQueue( )
{
if(front == rear)
throw "下溢异常";
else
return front->next->data;
}
int Empty()
{
if(front == rear)
return 1;
else
return 0;
}

private:
Node*front, *rear; 
};
int main() {
	LinkQueue l,k;//设置两个链队列 
	int num,num1,num3,num4;//num为循环的次数,num1为每次循环的人数,num3为每次数数字为2活3的判断,num4是队列里面人数 
	cin>>num;
	for(int i = 0;i < num;i ++) {
		cin>>num1;
		for(int i = 0;i < num1;i ++){
			l.EnQueue(i+1);//先放在l里面 
		}
		num4=num1;
		while(num4!=3){
			num3=0;
			while(!l.Empty()){//以2为循环 
				num3++;
				if(num4 == 3){
					while(!k.Empty()) {
						cout<<k.GetQueue();
						cout<<" ";
						k.DeQueue();
					}
					while(!l.Empty()) {
					    cout<<l.GetQueue();
					    cout<<" ";
						l.DeQueue();
					}
					break;
				}
				if(num3 % 2 == 0){
					l.DeQueue();
					num4--;
				}else{
					k.EnQueue(l.GetQueue());
					l.DeQueue();
				}
			}
			num3=0;
			while(!k.Empty()){//以3为循环 
				num3++;
				if(num4 == 3){
					while(!l.Empty()) {
						cout<<l.GetQueue();
						cout<<" ";
						l.DeQueue();
					}
					while(!k.Empty()) {
						cout<<k.GetQueue();
						cout<<" ";
						k.DeQueue();
					}
					break;
				}
				if(num3 % 3 == 0){
					k.DeQueue();
					num4--;
				}else{
					l.EnQueue(k.GetQueue());
					k.DeQueue();
				}
			}
		}
	}
	return 0;
}

实现效果如下:
在这里插入图片描述
以上就是我的题目分享,希望对大家有所帮助,也希望通过此题,可以让你对队列有所了解,如果有用,希望可以得到你的支持与鼓励ლ(´ڡ`ლ)。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值