【顺序结构+链表结构+C语言程序改错】之约瑟夫环问题

1.顺序结构

【最新写的代码版本】

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#define maxSize 100

void Joseph(int m, int n)
{
	int a[maxSize];
	int i, k, count;

	for (i = 1; i <= n; ++i)
		a[i] = i;

	count = 0;
	i = 1;//从第一个人开始报数

	//当第n-1个人出队的时候退出循环,此时队列还剩下一个人未出队
	while (count < n - 1)
	{
		k = 1;
		while (k < m)
		{
			//下一个人报数,当报数为m时,找到报该数的人,然后退出循环
			k++;

			i = (i + 1) % (n + 1);
			if (i == 0)
				i = i + 1;

			while (a[i] == 0)//若该人已经出队,则找到下一个还未出队的人
			{
				i = (i + 1) % (n + 1);
				if (i == 0)
					i = i + 1;
			}

		}

		printf("%d ", a[i]);
		a[i] = 0;//将此人出队
		count++;//出队人数加一
		
		//找到下一个未出队的人
		i = (i + 1) % (n + 1);
		if (i == 0)
			i = i + 1;

		while (a[i] == 0)
		{
			i = (i + 1) % (n + 1);
			if (i == 0)
				i = i + 1;
		}
	}

	printf("%d ", a[i]);
}

int main()
{
	Joseph(3, 13);

	return 0;
}

【问题代码】

void Josehus(int j)//从第j个人开始报数
{
	int a[N];
	int count, k;
	int i = j - 1;

	for (k = 0; k < N; ++k)
		a[k] = k + 1;
	count = 0;

	while (count < N)
	{
		k = 1;
		while (k < M)
		{
			k++;

			i = (i + 1) % N;
			while (a[i] == 0)
				i = (i + 1) % N;
		}
		printf("%d ", a[i]);
		a[i] = 0;
		i++;
		count++;
	}
}

【错误原因】

在i++这里出错,目的是找到下一个报数为1的人,但此处必须加循环,否则下一个报数为1的人就会变成已经出队的人的编号,此外,还需要有结束循环的条件,否则会变成死循环。

【正确代码】

#include <stdio.h>
#define N 13
#define M 3

void Josehus(int j)//从第j个人开始报数
{
	int a[N];
	int count, k;
	int i = j - 1;

	for (k = 0; k < N; ++k)
		a[k] = k + 1;
	count = 0;

	while (1)
	{
		k = 1;
		while (k < M)
		{
			i = (i + 1) % N;//默认第1个人已经报过数了
			while (a[i] == 0)
				i = (i + 1) % N;
			k++;
		}
		printf("%d ", a[i]);
		a[i] = 0;

		count++;
		if (count >= N)
			break;

		i = (i + 1) % N;//找到下一个报数为1的人,此处必须加循环,否则下一个报数为1的人就会变成已经出队的人的编号
		while (a[i] == 0)
			i = (i + 1) % N;

	}
}

int main()
{
	Josehus(1);
	return 0;
}

【测试结果】

2.链表结构

【正确代码】

#include <stdio.h>
#include <stdlib.h>
#define N 13
#define M 3

typedef struct LNode
{
	int data;
	struct LNode* next;
}LNode;

void Josehus(int i)//从第j个人开始报数
{
	LNode* L;
	int count, k;
	int j;

	LNode*pre, *p;
	LNode*s;
	L = (LNode*)malloc(sizeof(LNode));
	p = L;

	for (j = 1; j <= N; ++j)
	{
		s = (LNode*)malloc(sizeof(LNode));
		s->data = j;
		p->next = s;
		p = s;
	}

	p->next = L;
	
	//查找第i个人
	for (p = L->next, pre = L; p != L; pre = p, p = p->next)
		if (p->data == i)
			break;

	count = 0;

	while (count < N)
	{
		k = 1;
		while (k < M)
		{
			pre = p;
			p = p->next;
			if (p == L)
			{
				pre = p;
				p = p->next;
			}
			k++;
		}

		printf("%d ", p->data);

		pre->next = p->next;
		free(p);//出队
		p = pre->next;

		if (p == L)
		{
			pre = p;
			p = p->next;
		}

		count++;

	}
}

int main()
{
	Josehus(1);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值