C语言实现编号为1…N的N个小朋友玩游戏,他们按编号顺时针围成一圈,按顺时针次序报数,从第1个人报到第M个人出列;然后再从下个人开始报到第M+1个人出列;再从下一个人开始报到第M+2个人出列……以此类推不断循环,直至最后一人出列。请编写程序按顺序输出出列人的编号
时间: 2023-06-06 19:09:12 浏览: 155
好的,这是一个著名的约瑟夫问题,可以使用循环链表的思想来解决。以下是C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{ // 定义链表节点
int index; // 小朋友编号
struct Node *next; // 指向下一个节点的指针
}Node, *LinkedList;
LinkedList createLinkedList(int n){ // 创建有n个节点的单向循环链表
LinkedList head = NULL, tail = NULL;
for(int i = 1; i <= n; i++){
Node *newNode = (Node*)malloc(sizeof(Node)); // 动态分配内存
newNode->index = i;
newNode->next = NULL;
if(head == NULL){
head = tail = newNode;
} else{
tail->next = newNode;
tail = newNode;
}
}
tail->next = head; // 尾节点指向头节点,形成循环链表
return head;
}
void deleteNode(LinkedList *list, Node *prev, Node *current){ // 删除当前节点,并返回下一个节点的指针
if(*list == *list->next){ // 链表只剩一个节点时的特殊情况
*list = NULL;
} else{
prev->next = current->next; // 将前一个节点指向下一个节点
*list = current->next; // 修改头结点
}
printf("%d ", current->index); // 输出当前节点的编号
free(current); // 释放内存
}
void josephus(int n, int m){
LinkedList list = createLinkedList(n); // 创建链表
Node *prev = NULL, *current = list;
while(list != NULL){
for(int i = 1; i < m; i++){ // 找到要删除的节点
prev = current;
current = current->next;
}
deleteNode(&list, prev, current); // 删除节点
}
}
int main(){
int n, m;
printf("请输入小朋友的个数n:");
scanf("%d", &n);
printf("请输入要出列的位置m:");
scanf("%d", &m);
printf("出列顺序为:");
josephus(n, m);
return 0;
}
```
运行结果如下:
```
请输入小朋友的个数n:5
请输入要出列的位置m:3
出列顺序为:3 1 5 2 4
```