问题描述
已知N个人(以编号1,2,3,...,N分别表示)排成一列, 第一轮从编号为1的人开始依次报数,数到2的倍数的人出列;第二轮从头开始依次报数,数到3的倍数的人出列;第三轮再次从头开始依次报数,数到2的倍数的人出列;第四轮从头开始依次报数,数到3的倍数的人出列;依此规律重复下去,直到队列中的人数不超过三个为止。要求输出此时队列中剩下的人在初始队列中的编号。
问题输入
一个正整数N,表示初始人数,N≤5000。
问题输出
输出队列中剩下的人在初始队列中的编号,编号之间有一个空格。
输入样例
20
输出样例
1 7 19
实现思路
用单链表去做,找到相应条件的就出队列
注意跳出队列的条件
#include<stdio.h>
#include<stdlib.h>
//单链表结构体
typedef struct queue{
int num;
struct queue *next;
}QNode, *Queue;
//用头插法创建编号链表从1到N
void Create(Queue *q, int N){
Queue node;
int i;
*q = (Queue)malloc(sizeof(QNode));
(*q)->next = NULL;
for(i=N; i>0; i--){
node = (Queue)malloc(sizeof(QNode));
node->num = i;
node->next = (*q)->next;
(*q)->next = node;
}
}
//报数出队列
void Out(Queue *q, int N){
int i;
int count = N; //记录队列个数
Queue p,t;
//当个数不超过3时结束循环
while( N>3 ){
//报到2的倍数的人出列
p = (*q)->next;
t = (*q);
N = count;
for(i=1; i<=N; i++){
if(i%2 == 0){
t->next = p->next;
p = p->next;
count--;
}else{
p = p->next;
t = t->next;
}
}
if(count<=3) //注意是一轮结束在判断,不能在出的时候就判断
return;
//报到3的倍数的人出列
p = (*q)->next;
t = (*q);
N = count;
for(i=1; i<=N; i++){
if(i%3 == 0){
t->next = p->next;
p = p->next;
count--;
}else{
p = p->next;
t = t->next;
}
}
if(count<=3)
return;
}
}
//输出函数
void Print(Queue head){
Queue p;
p = head->next;
while(p!=NULL){
printf("%d ", p->num);
p = p->next;
}
}
int main(){
Queue q;
int N;
scanf("%d", &N);
Create(&q, N);
Out(&q, N);
Print(q);
return 0;
}