1、约瑟夫环问题(C语言循环链表)
我相信大家都可以画出这个图,知道大体的解题的思想,但是却不知道代码该怎么下手,因此,下面我直接上代码,代码中该注释的地方我都进行了注释,希望到大家有帮助;
#include<stdio.h>
#include <mm_malloc.h>
typedef struct Node {
int num;
int password;
struct Node *next;
} Node, *LinkList;
int main() {
void JOsephus();
JOsephus();
}
void JOsephus() {
//定义需要用到的变量
int n = 0, m = 0, j = 0, pwd = 0;// n代表多少人参与, m是初始的期望值, j用于方便操作,pwd代表密码
Node *p, *r, *pre, *q;// p指向新开辟的节点 r始终指向链表中的最后一个节点 q存放要被释放的节点 pre指向p的前驱节点
// 申请初始化循环单链表
LinkList L = (Node *) malloc(sizeof(Node));
if (L == NULL) {
printf("申请内存空间失败!\n");
return;
}
r = L;
L->next = NULL;
printf("请输入参与的人数n:");
scanf("%d", &n);
for (int j = 1; j <= n; j++) {
p = (Node *) malloc(sizeof(Node));
if (p != NULL) {
printf("请输入第%d个人的密码:", j);
scanf("%d", &pwd);
p->num = j;
p->password = pwd;
// p->next = r->next;
r->next = p;
r = p;
}
}
r->next = L->next; // 这一步这样写是因为实际情况空节点并不是一个人,所有循环的时候没必要包括,挺妙的
//上面就是循环表的初始化,下面开始进行操作
printf("请输入第一个报数的上限值m(m>0):");
scanf("%d", &m);
printf("============================\n");
printf("出列顺序:");
pre = L;
p = L->next;
//循环结束的条件就是还剩下一个人
while (n != 1) {
// 大部分人都可以想到我们需要一个指向一直发生变化的指针,并且有相应的指针指向,他的前驱节点
j = 1;
while (j < m) {
pre = p;
p = p->next;
j++;
}
printf("%d->", p->num);
m = p->password;
n--;
// 下面几步是为了删除出列的节点,并且释放
pre->next = p->next;
q = p;
p = p->next;
free(q);
}
printf("%d\n", p->num);//最后还剩一个人的序号需要输出
}