约瑟夫环

         数据结构习题集上有有一个问题,名为约瑟夫环:

      编号为1,2,3,···,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。试设计一个程序求出出列顺序。

    一看就知道是递归问题,而且是我没有实现过的循环链表。搞了几个小时,终乃成。

/*
约瑟夫问题:编号为1~n的n个人顺时针围圈,每人拿一密码。先选初值m,从第一个报数知道报m,
此人出列,以此人的密码当做新的m报数,直到n个人全部出列。求出列顺序。
*/
#include <iostream>

using namespace std;
typedef struct Joseph
{
	int		num;		//人的编号
	int		password;	//所携密码
	Joseph *next;	
}CircularLink, *CLL;

void createCL(CLL& L, int n);
CLL printOrder(CLL L, int m);
CLL deleteCL(CLL L, int i);
CLL getElem(CLL L, int i);
int CLLength(const CLL L);

int main()
{
	int n,m;
	CLL L;
	cout << "The number of people: ";cin >> n;
	cout << "The initial-value: ";cin >> m;
	createCL(L,n);
	cout << "Result:(";	printOrder(L,m);cout << ")\n";
	return 0;
}

void createCL(CLL& L, int n)
{
	int i;
	CLL p, q;
	L = new CircularLink;
	cout << "Enter person 1 's password: "; cin >> L->password;
	L->num = 1;
	L->next = L;
	p = q = L;
	
	for(i = 1; i< n; i++)
	{
		p = new CircularLink;
		cout << "Enter person " << i + 1<< " 's password: ";cin >> p->password;
		p->num = i + 1;
		q->next = p;
		q = p;
	}
	p->next = L;
}

int CLLength(const CLL L)
{
	CLL p;
	int length = 1;
	for(p = L; p->next != L; p = p->next)
		length++;
	return length;
}
//获得某一轮中出列的编号
CLL getElem(CLL L, int i)
{
	int j;
	CLL p;
	for(p = L, j = 1; j< i; j++, p = p->next);
	return p;
}
//获得某一轮中出列编号的前一个
CLL deleteCL(CLL from, int i)
{
	int j;
	CLL p, q;
	i = (i == 1)?( i + CLLength(from) ):i;

	for(p = from, j = 1; j< i - 1; j++, p = p->next);
	q = p->next;
	p->next = q->next;

	delete q;
	return p->next;
}

CLL printOrder(CLL L, int m)
{
	CLL p, output;
	int tempPassword;

	output = getElem(L,m);
	//必须使用临时变量储存out->password,
	//否则下面进行删除语句是会将output释放,不能应用于递归
	tempPassword = output->password;
	cout << output->num << ",";
	p = deleteCL(L,m);

	if(CLLength(p) == 1)
	{
		cout << p->num;
		return NULL;
	}
	else
		return printOrder(p,tempPassword);	
	
}
        最后那个注释说的内容,我可是花了一个多小时才发现。令我郁闷的是,两个相隔十万八千里的函数居然是会相互影响,不得不佩服动态储存之神奇啊。

       编完查了下资料,这个程序是复杂了,如果想简单是可以的。不过我没这个时间,何况解决此问题的初衷是实现一次循环链表。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值