约瑟夫环(数据结构小实验二)

题目二:约瑟夫环(**)

[问题描述]

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

[基本要求]

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

[测试数据]

由学生任意指定。
  如:m的初值为20;n的值为7;密码:3,1,7,2,4,8,4;
(正确的输出结果应为6,1,4,7,2,3,5)。
(报告上要求写出多批数据测试结果)

[实现提示]

程序运行后首先要求用户输入初始报数上限值m,人数n,(设n≤30)。然后输入各人的密码。

[选作内容]

向上述程序中添加在顺序结构上实现的部分。

#include
#include
using namespace std;
struct node{
	int data,num;
	node* next;
};
int main()
{
	int n,m,k;
	while(~scanf("%d%d",&m,&n))
	{	
		node* head=(node*)malloc(sizeof(node));
		node *rear=head;
		head->next=NULL;
		head->num=1;
		scanf("%d",&head->data); 
		for(int i=2;i<=n;i++){
			scanf("%d",&k);
			node* p=(node*)malloc(sizeof(node));
			p->data=k;
			p->num=i;
			rear->next=p;
			rear=p;
		}
		rear->next=head;
		node *p=rear;
		while(n--){
			m=(m+n)%(n+1); 
			while(m--)	p=p->next;
			printf("%d ",p->next->num);
			m=p->next->data;
			node* temp=p->next;
			p->next=p->next->next;
			free(temp);
		}
	}
	return 0;
}

实现中出现的一些小问题

实现也并不是特别的麻烦,但是头结点我懒得简化掉(之前一直想着连成环),后来一想,可以直接用头结点存编号1就好了,有点麻烦的是第一次数数和其他时刻不一样,所以必须要从rear开始查。其次考虑到算法的效率,大于人数上限的直接公式求解,注意到m-1=(m+n-1)%n与n- -,所以以公式m=(m+n)%(n+1)简化操作。考虑到的内存问题,特设置temp进行使用过的释放。

你可能感兴趣的:(数据结构)