约瑟夫环

约瑟夫问题的一种描述是:编号为1,2,……,n点的n个人按顺时针方向围坐一个圈,每人持有一个密码。一开始选一个正整数作为报数上限值m,从第一个人开始从顺时针方向自1开始报数,报到m时停止。报到m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始从新从1报数,如此下去,直达所有人出列。

基本要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各人的编号。

测试数据:m的初始值为20;n=7,7个人的密码依次是3,1,7,2,4,8,4,首先m的值为6(正确的出列顺序为6,1,4,7,2,3,5)


法一:

链表实现

#include <stdio.h>
//#include<malloc.h>
#include <stdlib.h>
typedef struct node{
	int data;
	struct node *next;
}LNode;

LNode* Create(int n,int k)
{
	int start=k-1;
	LNode *s,*p,*L=0,*t;
	if (start==0) start=n;
	while (n!=0)
	{
		s=(LNode *)malloc(sizeof(LNode));
		if (L==0) p=s;
		if (n==start) t=s;
		s->data=n;
		s->next=L;
		L=s;
		n--;
	}
	p->next=L;
	return t;
}

LNode* deleteNode(LNode *p)
{
	LNode *q;
	for (q=p;q->next!=p;q=q->next);
	q->next=p->next;
	free (p);
	return (q);
}

int Print(LNode *p,int m)
{
	int i;
	while (p->next!=p)
	{
		for (i=1;i<=m;i++)
			p=p->next;
		printf ("%d=> ",p->data);
		p=deleteNode(p);
	}
	printf("%d\n",p->data);
	return 0;
}

void main()
{
	LNode *p;
	int n,k,m;
	printf ("n:");
	scanf ("%d",&n);
	printf ("开始人的序号:",n);
	scanf ("%d",&k);
	printf ("间隔人:");
	scanf ("%d",&m);
	p=Create(n,k);
	Print(p,m);
}	

法二:

C语言数组实现

//n为总人数,m为第几个人出去 
#include <stdio.h>

int main(){
	int i, j, k, a[100000], *p;
	int n, m;
	printf("n:");
	scanf("%d", &n);

	for(i = 0, p = a; p <= a + n; i++, p++)
		*p = i;
	p = a + 1;
	
	for(i=1;i<=n;i++)
		a[i]=i;
	p=a;
	printf("m:");
	scanf("%d", &m);

	for(i = 0,k = n; k != 1; p++){
		if(p > (a + n))
			p = a + 1;
		if(*p != 0)
			i++;
		if(i ==m){		
			*p = 0; 
			i = 0;
			k--;		
		}
	}
	for(i = 0; i <= n; i++){
		if(a[i] != 0)
			printf("%d ", a[i]);
	}
	return 0;	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值