【题目描述】
有M个人,编号分别为1到M,玩约瑟夫环游戏,最初时按编号顺序排成队列;每遍游戏开始时,有一个正整数报数密码N,队列中人依次围坐成一圈,从队首的人开始报数,报到N的人出列,然后再从出列的下一人开始重新报数,报到N的人出列;重复这一过程,直至所有人出列,完成一遍游戏,所有出列的人形成新队列;游戏可能玩很多遍,每遍有新报数密码。求若干遍游戏完成后队列次序。本题要求使用单链表实现,程序要求采用模块化设计,格式规范,有合适注解。
【输入描述】
每个测试用例包含若干个正整数(至少1个),第一个正整数为玩游戏人数M,后续每个正整数为每遍游戏报数密码;报数密码可能为1
【输出描述】
每个测试用例结果占一行,每个编号占4位。
【样例输入】
10 3 5 2
【样例输出】
4 6 5 2 9 1 3 7 8 10
题解:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node
{
int date;
struct Node* next;
};
//创建链表
struct Node* createList()
{
struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
//headNode变成一个变量
//变量使用前初始化
//headNode->date = 0;
headNode->next = NULL;
return headNode;
};
//创建结点
struct Node* createNode(int date)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->date = date;
newNode->next = NULL;
return newNode;
}
//插入结点(尾插法)
void insertNodebyTail(struct Node* headNode, int date)
{
struct Node* pmove = headNode;
while (pmove->next != NULL)
{
pmove = pmove->next;
}
struct Node* newNode = createNode(date);
pmove->next = newNode;
}
//删除结点
void deleteNode(struct Node* headNode, int posDate)
{
struct Node* posNode = headNode->next;
struct Node* posNodefront = headNode;
if (posNode == NULL)
{
printf("无法删除链表\n");
}
else
{
while (posNode->date != posDate)
{
posNodefront = posNode;
posNode = posNodefront->next;
if (posNode == NULL)
{
printf("未找到指定结点,无法删除\n");
return;
}
}
posNodefront->next = posNode->next;
//return posNode->next;
//free(posNode);
}
}
//打印链表
void printList(struct Node* headNode)
{
struct Node* pMove = headNode->next;
while (pMove != NULL)
{
printf("%-4d", pMove->date);
pMove = pMove->next;
}
printf("\n");
}
int main(void)
{
struct Node* list = createList();//建两个表,一个用来存储信息,另一个用来存储导出的信息
struct Node* list1 = createList();
int M;//完游戏人数
scanf_s("%d",&M);
for (int i = 1; i <=M; i++)
{
insertNodebyTail(list,i);
}
int temp;//报数密码
int flag = 0;//标记那个链表是空的
int count = 0;//记数
struct Node* p, * q;
while(1)
{
if (scanf_s("%d", &temp) ==EOF)//由于不知道有多少个输入数据。所以用该条件跳出接受数据的循环(含义自己百度查)
{
break;
}
if (temp == 10086) { break; }//测试时用于跳出循环
if (flag == 0) {
p = list->next;
while (p)
{
while (p) {
count++;
if (count == temp)
{
insertNodebyTail(list1, p->date);//将第一个符合条件的导入另一个链表
deleteNode(list, p->date);//删除这个符合条件的数据
count = 0;//重新开始计数
}
p = p->next;//回到第一个元素所在位置,循环,直到找到所有符合条件的数据(循环完后只剩下一个表头不在有数据)
}
p = list->next;
}
flag = 1;
//printList(list1);
//printList(list1);
}
else {
q = list1->next;
while (q)//原理同上
{
while (q) {
count++;
if (count == temp)
{
insertNodebyTail(list,q->date);
deleteNode(list1,q->date);
count = 0;
}
q = q->next;
}
q = list1->next;
}
flag = 0;
//printList(list);
}
// printf("\n%d", k);
}
printList(list);//只有一个表是有数据的,直接打印即可,也可也用flag判断后在打印
printList(list1);
return 0;
}