问题:
设有编号为 1,2,…,n 的 n(n>0)个人围成一个圈,每个人持有一个密码 m。 从第一个人开始报数,报到 m 时停止报数,报 m 的人出圈,再从他的下一个人 起重新报数,报到 m 时停止报数,报 m 的出圈,……,如此下去,直到所有人 全部出圈为止。当任意给定 n 和 m 后,设计算法求 n。
首先需要明白指针是存储位置的一个称呼
//约瑟夫环
#include<stdlib.h>
#include<stdio.h>
//常用的函数如malloc()、calloc()、realloc()、free()、system()、atoi()、atol()、rand()、srand()、exit()等等。
typedef struct node{
int data;//存储的序列
int password;//这个比之前的多一个密码可以定义,也就是不同的m
struct node *next;//递归
}ElemSN;
ElemSN * Create();//函数的声明
int n,m; //n是人数,m在主函数中是初始密码,m在被调函数中是各个值的密码
void Josephus(ElemSN * tail);//去掉函数
int main(void){//主函数
ElemSN *tail; //利用尾结点保证创建链表时操作的一致性(不用对第一个结点进行特殊判断)
tail=Create(); //创建一个循环链表
Josephus(tail);
}
ElemSN * Create(){//建立循环链表
ElemSN * tail=NULL, *p;//尾结点,tail=null,是tail那也不指
scanf("%d %d",&n,&m);
for(int i=0;i<n;++i){
p=(ElemSN *)malloc(sizeof(ElemSN));//让p指向实际的空间
if(!tail){//如果尾指针是空指针,这个是应对*tail=NULL
tail=p->next=p;//就是将tail和p的下一个都赋值为p,但是是从右往左,先是p->next=p,tail=(p->next=p),在第一个
//结点,p就是tail
p->data=i+1;//p内存的值为i加1
scanf("%d",&p->password);//输入p中密码
}
else{
p->data=i+1;
scanf("%d",&p->password);
p->next=tail->next;
tail=tail->next=p;//从右往左
}//当data的值为2的时候,p指向2,2指向1,然后35行1也指向2,然后tail就为p都是2位置的名称
}
return tail;//创建循环链表
}
void Josephus(ElemSN * tail){
int i=0;
ElemSN * p=NULL;
while(n){
i=(i+1) % m;//验证要删除的位置在哪
if(i)//i不为0,就继续往下走
tail = tail->next;
else{
p = tail->next;
tail->next = p->next;
printf("%d ", p->data);
m = p->password;
free(p);//释放空间
n--;
i=0;
}
}
}
/*验证方法
7 20
3 1 7 2 4 8 4
*/
/*头结点是链表里面第一个结点,他的数据域可以不存放任何信息
(有时候也会存放链表的长度等等信息),他的指针区域存放的是
链表中第一个数据元素的结点(就是传说中的首元结点)存放的地址。*/
/*
if (指针) {
// 不是空指针 执行这个
}else {
//指针 是一个空指针, 执行这个
}
*/
/*
if (!指针) {
// 如果指针是空指针 !指针后 那么条件就成立了。也就是会执行这个地方的语句
}else {
// 如果指针不是空指针 !指针后 那么条件相当于false了。也就是会执行这个地方的语句
}*/
讲解在b站