数据结构–线性链表及其应用–约瑟夫环
【实验目的】
帮助学生熟练掌握线性表的基本操作在顺序和链式两种存储结构上的实现,其中以各种链表的操作和应用作为重点内容。
【实验内容及要求】
1、问题描述:约瑟夫问题的一种描述为,编号为1,2,3,……n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m的值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。试设计一个程序求出出列顺序。
2、基本操作:利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
3、测试数据:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,首先m值为6(正确的出列顺序应为6,1,4,7,2,3,5)。
4、实现提示:程序运行后,首先要求用户指定初始报数上限值,然后读取各人的密码。可设n≤30。此题所用的循环链表中不需要“头结点”,请注意空表和非空表的界限。
5、选作内容:集合的并、交、差运算。
【实验数据】:
#include <malloc.h>
#include<iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
typedef int Status;
typedef double ElemType;
//-----------------------------------
//定义单向循环链表
typedef struct LNode
{
int number;
int data;
struct LNode *next;
} LNode, *LinkList;
//-----------------------------------
LinkList EvaluList(int n);//对单向循环链表进行尾插入赋值
int size(LinkList L);//求链表的节点个数
Status ScanList(LinkList L);//遍历单向循环链表
Status Joseph(LinkList &L,int m);//约瑟夫环的实现
//---------对单向循环链表进行尾插入赋值----------------
LinkList EvaluList(int n)
{
if(n==0)
return NULL;
int key;
cout<<"输入第1个人的密码 ";
cin>>key;
LinkList L=new LNode;
L->data=key;
L->number=1;
L->next=L;
for(int i=2; i<=n; i++)
{
LinkList p=new LNode;
int key;
cout<<"输入第"<<i<<"个人的密码 ";
cin>>key;
p->data=key;
p->number=i;
p->next=L->next;
L->next=p;
L=L->next;
}
cout<<endl;
L=L->next;
return L;
}
//---------------求链表的节点个数-------------------
int size(LinkList L)
{
if(L==NULL)
return 0;
int i=1;
LinkList p=L->next;
while(p!=L)
{
i++;
p=p->next;
}
return i;
}
//---------------遍历单向循环链表--------------------
Status ScanList(LinkList L)
{
LinkList p=L;
if(p==NULL)
{
cout<<"人数为空"<<endl;
return FALSE;
}
cout<<"第1个人的密码 ";
cout<<p->data<<endl;
p=p->next;
while(p!=L)
{
cout<<"第"<<p->number<<"个人的密码 ";
cout<<p->data<<endl;
p=p->next;
}
cout<<endl;
return TRUE;
}
//----------------约瑟夫环的实现-----------------------
Status Joseph(LinkList &L,int m)
{
if(L==NULL)
{
cout<<"人数为空,出列结束"<<endl;
return FALSE;
}
LinkList p=L;
cout<<"密码为: "<<m<<endl;
while(p->next!=L)
p=p->next;
for(int n=size(L); n>0 ; n--)
{
for(int i=1; i<=m%n-1; i++)
p=p->next;
m=p->next->data;
cout<<"密码为: "<<m<<" 出列编号为: ";
cout<<p->next->number<<endl;
LinkList q=p->next;
p->next=q->next;
free(q);
}
return OK;
}
//-------------------------------------------------
int main()
{
int m,n;
cout<<"请输入初始密码(正整数)和人数"<<endl;
cin>>m>>n;
cout<<endl<<"请输入"<<n<<"个人的密码"<<endl<<endl;
LinkList L=EvaluList(n);
cout<<n<<"个人的密码为"<<endl;
ScanList(L);
cout<<n<<"个人的出列顺序为"<<endl;
Joseph(L,m);
}