用单循环链表实现约瑟夫环(c语言)

首先我是设置的链表节点的元素包括三个:1.每个人的各自拥有的顺序(math表示)2.每个人所拥有的密码(data表示)3.指针元素指向下一个: 

typedef struct node {
	int math;  //math为人的顺序// 
	int data;  //data为人所带的密码// 
	struct node *next;
} node,*Linklist;

然后初始话是直接用的双重指针传入的函数体,当然返回值就是void了:

void Initlist(Linklist *L) {             //初始化// 
	(*L)=(Linklist)malloc(sizeof(node));
	(*L)->next=(*L);
}

然后就是创建单循环链表,这里也是引用的双重指针(比较省事),正常的链表写法,n是人数多少:

void created(Linklist *L,int n) {        //创建单循环链表// 
	node *s,*r;
	r=*L;
	int i;
	while(n--) {
		s=(Linklist)malloc(sizeof(node));
		printf("请输入元素位置和密码:");
		scanf("%d%d",&s->math,&s->data);
		r->next=s;
		r=s;
	}
	r->next=(*L)->next;      //让尾节点指向首元节点// 
}

下来就是最重要的链表处理环节,这里的话我是重新申请了两个节点(一个是后继节点,一个是普通节点),这里传入的是一重指针L和人数大小n,定义了m是第一个初始密码,第一个for循环就是找密码结束的哪个点的位置,后面的处理直接看图比较清晰:

​

void print(Linklist L,int n) {
	Linklist p,r;    
	int m;             //第一个开始密码// 
	p=L;               //指向头节点//
	r=L->next;         //后驱节点// 
	printf("请输入第一个密码:");
	scanf("%d",&m);
	printf("出列顺序:");
	while (n--)
	{
		for (int j = 1; j < m ; j++)    //循环m-1次后后继节点就是要删除的节点!!// 
		{
			p = r;                        
			r = r->next;
		}
		printf("%2d", r->math);  //后驱结点法只能输出后驱节点的math// 
		p->next = r->next;      //让后驱节点轮空// 
		m = r->data;           //将出列的玩家的密码设为新的密码//
		free(r);              //释放要删除的节点// 
		r = p->next;         //重新给r节点赋值为p的前驱// 
	}
}

​

最后附上整个代码:

#include<stdio.h>
#include<stdlib.h>
typedef struct node {
	int math;  //math为人的顺序// 
	int data;  //data为人所带的密码// 
	struct node *next;
} node,*Linklist;
void Initlist(Linklist *L) {             //初始化// 
	(*L)=(Linklist)malloc(sizeof(node));
	(*L)->next=(*L);
}
void created(Linklist *L,int n) {        //创建单循环链表// 
	node *s,*r;
	r=*L;
	int i;
	while(n--) {
		s=(Linklist)malloc(sizeof(node));
		printf("请输入元素位置和密码:");
		scanf("%d%d",&s->math,&s->data);
		r->next=s;
		r=s;
	}
	r->next=(*L)->next;      //让尾节点指向首元节点// 
}
void print(Linklist L,int n) {
	Linklist p,r;
	int m;             //第一个开始密码// 
	p=L;
	r=L->next;         //后驱节点// 
	printf("请输入第一个密码:");
	scanf("%d",&m);
	printf("出列顺序:");
	while (n--)
	{
		for (int j = 1; j < m ; j++)    //循环m-1次后后继节点就是要删除的节点!!// 
		{
			p = r;                        
			r = r->next;
		}
		printf("%2d", r->math);  //后驱结点法只能输出后驱节点的math// 
		p->next = r->next;      //让后驱节点轮空// 
		m = r->data;           //将出列的玩家的密码设为新的密码//
		free(r);              //释放要删除的节点// 
		r = p->next;         //重新给r节点赋值为p的前驱// 
	}
}
int main() {
	int n;
	Linklist L;
	Initlist(&L);
	printf("请输入人数大小:");
	scanf("%d",&n);
	created(&L,n);
	print(L,n);
	return 0;
}

后面加一张运行结果:

这里的话是7个人,从前往后每个人携带的密码分别为:3.1.7.2.4.8.4。

第一个开始密码是:20

  • 13
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新城已无旧少年_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值