线性表及其应用———约瑟夫环

线性表及其应用——约瑟夫环


约瑟夫(Joseph)问题的一种描述是:编号为1,2,3,…,n的n个人按顺时针方向围坐一圈。每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数,令其出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。
    实验要求:利用无头结点的单向循环链表存储结构模拟此过程,按照出列的顺序打印出各人的编号。
测试数据:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,首先出列的是6号(正确的出列顺序应为6,1,4,7,2,3,5)
实验提示:程序运行后,首先要求用户指定初始报数上限值,然后读取各人的密码,可设n<=30,此题所用的循环链表中不需要“头结点”,请注意空表和非空表的界限。

思路及题解:

这题可以用链表来做也可以用线性表来做,题目要求用链表那我们就用链表。

大致框架:

第一步  先创建一个结构体类型,里面存有一个人的序号和密码,并且还有个next节点。在输入n个人的密码时,每输入一个密码就创建一个节点,后插如链表中,并且next指向head(第一个节点时先创建head),这样就保证在输入的同时创建了循环链表。

第二步  用一个pre指针指向head,p指针指向head->next;cnt记录报数的人数,初值为2;当p非空时循环,在循环里,如果p==prev,则表示只剩下一个节点,输出p指向的序号后释放,然后跳出循环。当cnt==m时,p只想节点的序号输出,p后移,pre->next释放后,pre->next=p;cnt更新为1,其他情况下,p和pre后移,cnt+1。

代码:

#include
using namespace std;
struct ListNode{
	int num;
	int val;
	ListNode *next;
};
int main()
{
	int m,n;
	struct ListNode *head,*tail;
	head=NULL;
	cout<<"密码和人数为:";
	cin>>m>>n;
	cout<>s->val;
		s->num=i;
		s->next=NULL;
		if(i==1)
		{
			head=tail=s;
			tail->next=s;
			continue;
		}
		tail->next=s;
		tail=tail->next;
		tail->next=head;
	}
	struct ListNode *p,*pre;
	//test 
//	p=head;
//	int i=0;
//	while(inum<<"  "<val<next;
//	}
//	cout<num<<"  "<val;
	pre=head;
	p=head->next;
	int cnt=2;
	while(p)
	{
		if(pre==p)
		{//最后一个直接出队 
			cout<num<<"号出队。  m="<val<val;
			cout<num<<"号出队。  m="<next;
			delete pre->next;
			pre->next=p;
		}
		else
		{
			pre=p;
			p=p->next;
			cnt++;
		}
	}
}

你可能感兴趣的:(数据结构学习记录,算法)