约瑟夫环采用循环链表实现(附代码)

问题:

设有编号为 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站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值