好玩的约瑟夫环:有M个人,编号分别为1到M,玩约瑟夫环游戏,最初时按编号顺序排成队列;每遍游戏开始时,有一个正整数报数密码N,队列中人依次围坐成一圈,从队首的人开始报数,报到N的人出列,然后再从出列的下一人开始重新报数,报到N的人出列;重复这一过程,直至所有人出列,完成一遍游戏,所有出列的人形成新队列;游戏可能玩很多遍,每遍有新报数密码。求若干遍游戏完成后队列次序。题目输入包括若干个正整数(至少1个),第一个正整数为玩游戏人数M,后续每个正整数为每遍游戏报数密码,报数密码可能为1,题目要求按出队列顺序输出他们的编号。
输入样例:
10 3 5 2
输出样例:
4 6 5 2 9 1 3 7 8 10
代码如下:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
//createNew
struct Node *createNew()
{
struct Node *p;
p = (struct Node *)malloc(sizeof(struct Node));
p -> next = NULL;
return p;
};
//build创建循环链表
void build (struct Node **pp, int m) {
struct Node *phead, *pnew, *pold;
phead = *pp;
pold = phead;
int i;
for(i = 1; i <= m; i++) {
pnew = createNew();
pnew -> data = i;
pold -> next = pnew;
pold = pold -> next;
}
pold -> next = phead -> next;
}
//append添加人数
void append(struct Node **pp1, struct Node **pp2, int n) {
struct Node *phead1, *phead2, *pold, *pafter, *pnext;
phead1 = *pp1;
phead2 = *pp2;
pold = phead1 -> next;
pafter = pold -> next;
pnext = phead2;
while(phead1 -> next){
if(n >= 3) {
for(int i = 0; i < n - 2; i++) {
pold = pold -> next;
pafter = pold -> next;
}
}
else if(n == 2) {
pafter = pold -> next;
}
else if(n == 1) {
pold = phead1;
pafter = pold -> next;
}
//phead2未存储数据
if(!phead2 -> next) {
phead2 -> next = pafter;
pnext = pnext -> next;
}
//printf("pnext = %d\n",pnext -> data);
else {
pnext -> next = pafter;
pnext = pnext -> next;
}
pold -> next = pafter -> next;
pold = pold -> next;
//printf("pnext->next = %d\n",pnext -> data);
//printf("pold = %d\n",pold -> data);
//只剩下一个人n >= 2跳出循环的条件
if(pold == pold -> next) {
pnext = pold;
pnext -> next = NULL;
break;
}
//n == 1跳出循环的条件
if(n == 1) {
if(pafter -> next -> data == phead2 -> next -> data) {
pafter -> next = NULL;
break;
}
}
}
}
//print
void print(struct Node *p, int m)
{
for(int i = 0; i < m; i++) {
printf("%4d",p -> next -> data);
p = p -> next;
}
}
void repeat(struct Node **pp) {
struct Node *phead, *pnext;
phead = *pp;
pnext = phead -> next;
while(pnext -> next) {
pnext = pnext -> next;
}
pnext -> next = phead -> next;
}
//destroy
void destroy(struct Node *p)
{
struct Node *pnext;
while(p) {
pnext = p -> next;
free(p);
p = pnext;
}
//printf("destroyed!");
}
int main()
{
//新建两个链表的头节点
struct Node *phead1, *phead2;
phead1 = createNew();
phead2 = createNew();
//输入人数
int m;
scanf("%d",&m);
//创建循环链表
build(&phead1,m);
//第一次游戏
int x;
scanf("%d",&x);
append(&phead1,&phead2,x);
//循环游戏
while(getchar() == ' ') {
phead1 = phead2;
repeat(&phead1);
phead2 = createNew();
scanf("%d",&x);
append(&phead1,&phead2,x);
}
//打印
print(phead2,m);
//销毁
destroy(phead2);
return 0;
}