问题描述:一群小朋友围坐一圈,已按照1,2,...,n编号。从1开始报数,报到k出局;下一个小朋友又从1开始报。到最后只会剩一个小朋友,即为获胜者。
要求:设计程序实现以下操作: A. 键盘输入n和k; B. 输出淘汰的n-1个小朋友的出局顺序; c. 输出获胜者的编号。 提示:采用队列实现算法。1,2,...,n这些小朋友站在队列里,报数过程中,队首的人出队,然后走到队尾,报到k的小朋友被淘汰出局,不再入队。重复操作,直到剩最后一个人。
C语言代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//循环队列
typedef struct circular_queue {
int* data;
int head, tail;
int length, cnt;
}Queue;
Queue* initQueue(int n) {
Queue* q = (Queue*)malloc(sizeof(Queue));
q->data = (int*)malloc(sizeof(int) * n);
q->head = q->tail = q->cnt = 0;
q->length = n;
return q;
}
int empty(Queue* q) {
return q->cnt == 0;
}
int lenQueue(Queue* q) {
if (q == NULL) {
printf("队列不存在\n");
return -1;
}
return q->cnt;
}
int front(Queue* q) {
return q->data[q->head];
}
int push(Queue* q, int val) {
if (q == NULL)return 0;
if (q->cnt == q->length) {
//printf("队列已满,将%d入队失败\n", val);
return 0;
}
q->data[q->tail++] = val;
if (q->tail == q->length)q->tail -= q->length;
q->cnt += 1;
//printf("将%d入队成功\n", val);
return 1;
}
int pop(Queue* q) {
if (q == NULL)return 0;
if (empty(q))return 0;
//printf("将%d出队\n", front(q));
q->head++;
if (q->head == q->length)q->head -= q->length;
q->cnt -= 1;
return 1;
}
void DestroyQueue(Queue* q) {
if (q == NULL)return;
free(q->data);
free(q);
return;
}
void output(Queue* q) {
printf("queue = [");
for (int i = q->head, j = 0; j < q->cnt; j++) {
int ind = (i + j) % q->length;
printf(" %d", q->data[ind]);
}
printf(" ]\n");
return;
}
int main() {
printf("约瑟夫游戏,请输入n和k\n");
int n, k;
printf("请输入n:\n");
scanf_s("%d", &n);
printf("请输入k:\n");
scanf_s("%d", &k);
if (n <= 0 || k <= 0) {
printf("输入不合法\n");
return 0;
}
if (n == 1) {
printf("玩家只有一人,小朋友自动获胜\n");
return 0;
}
Queue* q = initQueue(n);
for (int i = 1; i < n + 1; i++) {
push(q, i);
}
printf("被淘汰的小朋友依次是:");
while (1) {
for (int i = 1; i < k; i++) {
int t = front(q);
pop(q);
push(q, t);
}
printf(" %d号 ",front(q));
pop(q);
if (lenQueue(q) == 1) {
printf("\n游戏结束,胜利者是%d号小朋友\n", front(q));
DestroyQueue(q);
return 0;
}
}
}
运行示例: