约瑟夫环问题实验报告.doc
文本预览下载声明
数学与计算机学院 约瑟夫环问题 实验报告
年级 10级 学号 2010434062 姓名 成绩
专业 电气信息(计算机类)实验地点 主楼402 指导教师 史青宣
实验项目 约瑟夫环问题 实验日期 2011年12月26日
一、实验目的
本实验的目的是进一步理解线性表的逻辑结构和存储结构,进一步提高使用理论知识指导解决实际问题的能力。
二、实验问题描述
设编号为1,2,···,n的n个人围坐一圈,约定编号为k(1≤k≤n)的人从1开始报数,数到m的那个人出列,他的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
三、实验步骤
1、实验问题分析
①由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍要是围成一个圆圈,可以使用循环表;由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,应该选用效率较高的链表结构;为了程序指针每一次都指向一个具体的代表一个人的结点而不需要进行判断,链表不带表头结点。所以,对于所有人围成的圆圈所对对应的数据结构采用一个不带头结点的循环链表来描述。设头指针为p,并根据具体情况移动
可以采用数据类型定义:
Typedef struct node
{
int number;
struct node *next;
}Lnode,*Linklist;
②为了记录退出的人的先后顺序,采用一个顺序表进行存储,程序结束后再输入依次退出的人的编号顺序。由于只记录各个结点的number值就可以,所以定义一个整型一维数组。如“int quite[N];”N为一个根据实际问题定义的一个足够大的整数。
2、功能(函数)设计
根据上述分析,该算法可以由3个功能函数实现。Main()用做数据的输入和函数的调用,Init()做链表的初始化工作,使用Josephus()做删除结点和保存输出顺序的工作,OutRing()完成序列的输出工作。
1.建立单循环链表函数 LinkList InitRingList(int n);
2.产生Josephus顺序函数 void Josephus(LinkList L,int n,int k,int m,int quit[N])
3.输出顺序表void Print(int n,int quit[N])
四、实验结果(程序)及分析
1.实验的的源代码:
// 约瑟夫环问题.cpp : Defines the entry point for the console application.
//
//#include stdafx.h
#includeiostream.h
#define N 34
typedef struct Node
{
int data;
struct Node *next;
}Lnode,*LinkList;
LinkList InitRingList(int n) //尾插法建立单循环链表
{
Lnode *L,*r,*s;
L=new Lnode; //不带头结点
r=L;
for(int i=1;in;i++)
{
s=new Lnode;
r-data=i;
r-next=s;
r=s;
}
r-data=n;
r-next=L; //链表首尾相连
L=r; //L指向循环链表的尾结点
return L;
}
void Josephus(LinkList L,int n,int k,int m,int quit[N])
{
int i,j;
Lnode *p,*q;
p=L;
for(int r=1;rm;r++)
p=p-next;
for(i=0;in;i++)
{
for(j=1;j=k-1;j++)
p=p-next;
q=p-next;
p-next=q-next;
quit[i]=q-data;
delete q;
}
}
void Print(int n,int quit[N])
{
int i;
for(i=0;in;i++)
coutquit[i] ;
coutendl;
}
int main(int argc, char* argv[])
{
LinkList L;
int n;
int k;
int m;
cout请输入围坐一圈的人数n的值:endl;
cinn;
L=InitRingList(n);
int quit[N]
显示全部