C语言解决经典问题约瑟夫环--数组

什么时约瑟夫环问题?

约瑟夫问题,是一个计算机科学和数学中的问题,在计算机编程的算法中,类似问题又称为约瑟夫环,又称“丢手绢问题”。

问题的大致内容就是:一共有N个人,从1开始报数,报到p的人出局,之后下一个人再从1开始报数,同样报到p的人出局,直到只剩最后一个人为止,那剩下的这一个人就是胜利者。

示例图:

C语言解决经典问题约瑟夫环--数组_第1张图片此图中,外围数字为对应人的出出局顺序

当然原问题是比较简单的,那如果按退出顺序输出每个退出人的原序号该怎么实现呢?

问题分析:

1、如何判断出局

这里我们可以定义一个数组(长度视情况而定)可以将数组初始化为0,定义k来表示数组成员的报数,每次循环时k++,然后判断k是否等于p,若等于p则让arr[i] = 1;那么下次循环时判断arr[i]的值,若为1则跳过该元素。

2、如何循环

在此问题中,不是简单的对数组进行遍历,所以再想用for(i = 0;i

那我们该如何进行循环呢?

这里我们定义count来记录已经淘汰的人数,当淘汰人数count = n时则结束循环。

那么新的问题又出现了,当进行到最后一个人时如何返回从第一个人开始呢?

3、如何返回重新开始

其实这个问题不难解决,我们可以定义一个temp = n,在循环的最后判断i的值,如果i==temp,

这令i=0;就可以重新开始了。

OK主要问题就分析完了,话不多说,直接上代码。

代码:

#include 
#define N 3000

void joseph(int *arr,int n,int p); 
int main()
{
	int arr[N] = {0};
	int n,p;
	printf("请输入参加人数n和淘汰条件:");
	scanf("%d %d",&n,&p);
    printf("淘汰循序: ");
	joseph(arr,n,p);
	
	
	return 0;
}
void joseph(int *arr,int n,int p)
{
	int count,k,i,b;
	count = 0;		//记录出局的人数 
	k = 0;			//每个成员报的数
	i = 0;
	int temp;
	temp = n;
	/*
		这里定义temp的值为总人数是为了当数组遍历到最后一个后再回到第一个
		即:当 i == temp时  令 i = 0; 
	*/ 
	while(count < n)
	{
		if(arr[i] == 0)
		{
			k++;
			if(k == p)
			{
				arr[i] = 1;
				b = i+1;
				printf("%d ",i+1);
				count++;
				k = 0;
			}
		}
		i++;
		if(i == temp)
		{
			i = 0;
		} 
	}
	
}

你可能感兴趣的:(c语言,算法)