东北大学JOSEPH环问题设计报告
- 格式:docx
- 大小:143.87 KB
- 文档页数:11
题目二约瑟夫环问题设编号为1,2,3,……,n 的n(n>0)个人按顺时针方向围坐一圈,每个人持有一个正整数密码。
开始时任选一个正整数做为报数上限m ,从第一个人开始顺时针方向自1起顺序报数,起顺序报数,报到报到m 时停止报数,时停止报数,报报m 的人出列,的人出列,将他的密码作为将他的密码作为新的m 值,从他的下一个人开始重新从1报数。
报数。
如此下去,如此下去,如此下去,直到所有人全部出列直到所有人全部出列为止。
令n 最大值取30。
要求设计一个程序模拟此过程,求出出列编号序列。
struct node //结点结构{ int number; /* 人的序号人的序号*/ int cipher; /* 密码密码*/ struct node *next; /* 指向下一个节点的指针*/ }; 一、循环链表的结点类型定义/* 单链表的结点类型 */typedefstruct node{int number;int cipher;struct node *next;}list, *linklist;二、循环链表的初始化/* 函数功能:初始化n 个元素的循环链表参数;链表(linklist L),元素个数(int n )通过后插法对无头结点的链表初始化。
*/voidinit(linklist&L,int n){int key, i;cout<<"输入第1个人的密码为:";//输入第一个节点的密码。
cin>>key;L= new list;L->number = 1;L->cipher = key;L->next = L;for(i = 2; i<= n; i ++)//输入2—n 的节点密码。
{linklist p = new list;cout<<"输入第"<<i<<"个人的密码为:";cin>>key;p->cipher = key;p->number = i;p->next = L->next; //使用后插法插入。
数据结构上级实验报告1——采用单向环表实现约瑟夫环一实验目的采用单向环表实现约瑟夫环二实验内容请按以下要求编程实现:①从键盘输入整数m,通过create函数生成一个具有m个结点的单向环表。
环表中的结点编号依次为1,2,……,m。
②从键盘输入整数s(1<=s<=m)和n,从环表的第s个结点开始计数为1,当计数到第n个结点时,输出该第n结点对应的编号,将该结点从环表中消除,从输出结点的下一个结点开始重新计数到n,这样,不断进行计数,不断进行输出,直到输出了这个环表的全部结点为止。
例如,m=10,s=3,n=4。
则输出序列为:6,10,4,9,5,2,1,3,8,7。
三程序设计(1)概要设计抽象数据类型:struct node{ int number;struct node * next;};宏:无主函数流程与各函数模块调用关系:创建头结点=〉输入链表的长度m=〉调用create函数建立链表=〉输入首次定位的节点s 以及间隔数n=〉调用deal函数处理链表=〉结束函数模块间无彼此调用关系(2)详细设计建立链表算法实现:void create(node * head,int m){node * p,*q;int i = 1;for(;m>0;m--){ p = (node *)malloc(sizeof(node));if(p == NULL) exit(0);p->number = m;p->next = head->next;head->next = p;if(i){q = p ; i--;}}q->next = head->next;}处理链表算法实现:void deal(node * head,int m,int s,int n){node * p,*q;int count=1,tag=0;p = head;while(s--){ p = p->next;}while(tag != m){if(count == n){printf("%d->",p->number);for(q = p->next; q->next != p; q=q->next);q->next = p->next;p = p->next;q = q->next;count = 1;tag++;}else {p = p->next;count++;}}printf("<-end\n");}主函数代码实现:int main(){ int m,s,n;node * head, * p;p = (node *)malloc(sizeof(node));p->next == NULL;head = p;printf("please input number m:\n");scanf("%d",&m);create(head,m);printf("please input number s(1<=s<=m):\n");scanf("%d",&s);printf("please input number n:\n");scanf("%d",&n);deal(head,m,s,n);system("pause");}四程序调试分析1在deal函数中进行对p节点的删除操作时出现问题,定位p的前一个节点q时,依旧采用了head指针从头遍历的方法,但是忽略了在函数操作中会删除掉头结点,这样head指针指向位置改变不能得到正确结果。
约瑟夫环数据结构实验报告约瑟夫环数据结构实验报告引言约瑟夫环是一种经典的数学问题,它涉及到一个有趣的数据结构。
本次实验旨在通过实现约瑟夫环数据结构,深入理解该问题,并探索其在实际应用中的潜力。
本报告将介绍实验的设计和实现过程,并分析实验结果。
实验设计在本次实验中,我们选择使用链表来实现约瑟夫环数据结构。
链表是一种非常灵活的数据结构,适合用于解决约瑟夫环问题。
我们设计了一个Josephus类,其中包含了创建环、添加元素、删除元素等操作。
实验实现1. 创建环在Josephus类中,我们首先需要创建一个循环链表。
我们使用一个头节点来表示环的起始位置。
在创建环的过程中,我们可以选择指定环的长度和起始位置。
2. 添加元素在创建环之后,我们可以通过添加元素来向约瑟夫环中插入数据。
我们可以选择在环的任意位置插入元素,并且可以动态地调整环的长度。
3. 删除元素根据约瑟夫环的规则,每次删除一个元素后,下一个元素将成为新的起始位置。
我们可以通过删除元素的操作来模拟约瑟夫环的运行过程。
在删除元素时,我们需要考虑环的长度和当前位置。
实验结果通过实验,我们得出了以下结论:1. 约瑟夫环数据结构可以有效地模拟约瑟夫环问题。
通过创建环、添加元素和删除元素的操作,我们可以模拟出约瑟夫环的运行过程,并得到最后剩下的元素。
2. 约瑟夫环数据结构具有一定的应用潜力。
除了解决约瑟夫环问题,该数据结构还可以用于其他类似的问题,如任务调度、进程管理等。
3. 约瑟夫环数据结构的时间复杂度较低。
由于约瑟夫环的特殊性质,我们可以通过简单的链表操作来实现该数据结构,使得其时间复杂度较低。
结论本次实验通过实现约瑟夫环数据结构,深入理解了该问题,并探索了其在实际应用中的潜力。
通过创建环、添加元素和删除元素的操作,我们可以模拟出约瑟夫环的运行过程,并得到最后剩下的元素。
约瑟夫环数据结构具有一定的应用潜力,并且具有较低的时间复杂度。
通过本次实验,我们对数据结构的设计和实现有了更深入的理解,并为将来的研究和应用奠定了基础。
数据结构约瑟夫环实习报告一、实习题目约瑟夫环(Josephus Problem)是一种经典的问题,编号为1,2,……,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。
报M的人出列,将他的密码作为新的M值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序,并利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各人的编号。
二、实习目的1. 熟悉单向循环链表的存储结构及其应用。
2. 加深对线性链表这种数据结构的基本概念理解。
3. 锻炼较强的思维和动手能力,更加了解编程思想和编程技巧。
三、实习内容1. 采用单向循环链表实现约瑟夫环。
2. 从键盘输入整数m,通过create函数生成一个具有m个结点的单向循环链表。
3. 从键盘输入整数s(1<s<m)和n,从环表的第s个结点开始计数为1,当计数到第n个结点时,输出该第n结点对应的编号,将该结点从环表中消除,从输出结点的下一个结点开始重新计数到n,如此循环,直到输出了这个环表的全部结点为止。
四、程序设计1. 概要设计为了解决约瑟夫环的问题,我们可以建立单向循环链表来存储每个人的信息(该人的编号以及其下一个人的编号),及结点,人后通过查找每个结点,完成相应的操作来解决约瑟夫问题。
抽象数据类型定义:数据对象:D数据关系:R1基本操作:操作结果:构造2. 详细设计(1)初始化循环单链表```cvoid initList(LNode *head) {head->next = head;head->number = 0;}```(2)尾插法建立循环单链表```cvoid createFromTail(LNode *head, int m, int pass, int length) { LNode *p = head;int i;for (i = 1; i <= m; i++) {LNode *s = (LNode *)malloc(sizeof(LNode));s->number = i;s->pass = pass;s->next = NULL;p->next = s;p = s;}p->next = head; // 使链表形成一个环}```(3)从链表中删除结点```cvoid deleteFromList(LNode *head, LNode *p) {if (p->next == head) { // 删除的是头结点head = p->next;}p->next = p->next->next;free(p);}```(4)约瑟夫计数```cvoid yuesefu(LNode *head, int m, int n, int *sequence) { int count = 0;LNode *p = head;while (p->next != p) { // 当链表中还有多个结点时循环 count = 0;LNode *q = p->next;while (count < n) {q = q->next;count++;}sequence[count] = q->number; // 记录下出列的人的编号deleteFromList(head, q); // 删除该结点p = q->next; // 从下一个结点又开始计算n = m; // 新的M值}}```五、实验结果与分析通过以上程序设计,我们可以得到约瑟夫环的出列顺序。
实验报告:约瑟夫环一.需求分析1.本实验中,要求模拟N个持有密码的人在一种出序规则下的出序情况,每人有一个密码,并且N人在顺时针方向编号为1,2……N,在给予一个初始密码时要求将出序的人的序号打印出以摸拟该过程。
2.程序以计算机提示的方式出现,在显示提示信息后由用户从键盘上输入相应的信息。
3.测试数据M初值为20,N=7,7人的密码依次为:3,1,7,2,4,8,4,输入后正确的输出顺序为6,1,4,7,2,3,5。
二.概要设计为实现上述模拟功能,应以循环链表表示被编号的人。
为此,仅需要一个数据类型:循环链表。
1.循环链表的抽象数据类型定义为:ADT linkpeople{数据对象:D={a i|a i∈elepeople, i=1,2,3……,n}数据关系:R1={<a i-1,a i>|a i-1,a i∈D,i=1,2,……n}基本操作:creatcircle(&L)初始条件:L不存在。
操作结果:构造一个环形链表。
Workcircle(&L)初始条件:环形链表已存在。
操作结果:按所给规则处理链表,并释放退出循环的结点。
}ADT Linkpeople2.本程序包含三个模块:(1)主程序模块:int main(){读入初始值;构造链表;处理链表;}(2)创立链表模块——创立环形链表。
(3)处理链表模块——处理链表。
各模块之间的调用关系如下:创立模块处理模块三.详细设计1.元素结点类型typedef struct people{int number;int code;struct people *next;}elepeople,*linkpeople;2.模块设计linkpeople creatcircle(linkpeople p,int n){int i;linkpeople k,q,r;printf("please enter code \n");q=p;k=p;for(i=1;i<=n;i++){ if(i==n){k->next=q;k->number=n;scanf("%d",&k->code);}//处理最末的输入数据else{ scanf("%d",&k->code);k->number=i;r=(linkpeople)malloc(sizeof(elepeople));k->next=r;k=k->next;} //依此处理输入数据}return k;//返回最后结点指针}//creatcirclevoid workcircle(linkpeople q,int m){int c;linkpeople p,r;p=q;printf("the sequence of outpeople\n");while(p!=p->next){for(c=1;c<=m-1;c++)p=p->next;//找到处理结点前一个指针printf("%d ",p->next->number);m=p->next->code;r=p->next;p->next=p->next->next;free(r);}printf("%d ",p->number);free(p);//处理最后结点}//workcircle3.主函数int main(){int m;int n;linkpeople s;linkpeople p;printf("please enter the first code and sum of people\n");scanf("%d %d",&m,&n);p=(linkpeople)malloc(sizeof(elepeople));s=creatcircle(p,n);workcircle(s,m);return 0;}//main4.函数调用关系creatcircle workcircle四.调试分析1.在creatcircle的操作中,对其参数的传值问题未认真推敲,导致运行有误,以后应该注意。
实验一线性表的基本操作及其应用一、实验目的1、帮助读者复习C++语言程序设计中的知识。
2、熟悉线性表的逻辑结构。
3、熟悉线性表的基本运算在两种存储结构上的实现,其中以熟悉链表的操作为侧重点。
二、实验内容和要求[问题描述]约瑟夫(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)。
然后输入各人的密码。
[选作内容]向上述程序中添加在顺序结构上实现的部分。
三、算法设计1、主要思想:首先,设计实现约瑟夫环问题的存储结构。
由于约瑟夫环本身具有循环性质,考虑采用循环链表,为了统一对表中任意节点的操作,循环链表不带头结点。
循环链表的结点定义为如下结构类型:typedef struct LNode{int num,pwd; //num存储人的序号,pwd存储人的密码struct LNode *next;};其次,建立一个不带头结点的循环链表并由头指针Head指示。
最后,设计约瑟夫环问题的算法。
2、本程序包含四个模块1)主函数void main(){int m,n;//分别为报数上限和人数printf("\n参数m,n传递报数上限和人数.\n\n请输入m和n:\n");scanf("%d %d",&m,&n);creatLinkList(n);//带哦用创建链表函数enterPwd(n);//调用输入密码函数printf("\n出列的人依次是:\n");outList(m,n);}2)创建链表函数creatLinkList()——根据用户输入的人数创建人数相等数量结点的循环链表。
约瑟夫环实习报告题目:编制一个程序求出约瑟夫环问题的出列顺序。
班级:06计算机A班姓名:林树地学号:0615111044 完成日期:2008-05-01顺序表实现一、需求分析1. 本程序需要由用户在键盘上输入程序中的相关数据。
2. 先输入初始密码m (m>0)和环中人的个数n(n<50),再依次输入每个人的密码。
输入形式是以“回车”为结束标志的整型数。
3. 依次输出约瑟夫环中的出列者的编号。
4. 测试数据:初值m=20,n=7,7个人的密码依次为:3,1,7,2,4,8,4。
出列顺序应为6,1,4,7,2,3,5。
二、概要设计以顺序表表示环中的人:1.顺序表数据类型定义为:ADT sqlist{数据对象:D={ a i|a i∈Elemtype,i=1,2,……n;n≥0}数据关系:R1={<a i-1,a i>| a i-1,a i∈D,i=2,……,n}基本操作:initlist_sq(&l)操作结果:构造一个空的顺序表}ADT sqlist2.本程序包含两个模块①主程序模块void main(){接受命令;处理命令;}②顺序表单元模块——实现顺序表抽象数据类型;各模式块之间的调用关系如下;主程序模块→顺序表单元模块三、详细设计1.顺序表类型typedef struct{int elem[50];//存密码int length;}sqlist;2.主函数和其他函数的伪码算法void main(){int m,n;//m为密码,n为小孩个数cout<<"请输入初始密码m和人数n(n不大于50):";while(n<1||n>50){cin>>m>>n;if(n<1||n>50) cout<<"人数不合法,请重输"<<endl;}sqlist Jos;initlist_sq(Jos);// 初始化线性表cout<<"请依次输入"<<n<<"个密码:";for(;Jos.length<n;Jos.length++)cin>>Jos.elem[Jos.length];//存密码cout<<"出列顺序为:";int i=-1;//i为数组下标(下一值为0)for(int k=0;k<n;k++){for(int j=0;j<m;){i=(i+1)%n;//对下标加1求模if(Jos.elem[i]!=0)//判断是否已出列j++;}cout<<i+1<<" ";m=Jos.elem[i];//输出已出列的编号Jos.elem[i]=0;//标识已出列}cout<<endl;}void initlist_sq(sqlist &l){l.length=0;}3.函数调用关系:mainInitList四、调试分析1.刚开始忽略了对输入数据合法性的判断,可能造成存储空间不足。
《数据结构》课程设计报告课程名称:《数据结构》课程设计课程设计题目:joseph环姓名:院系:计算机学院专业:年级:学号:指导教师:2011年12月18日目录1 课程设计的目的 (2)2 需求分析 (2)3 课程设计报告内容 (3)1、概要设计 (3)2、详细设计 (3)3、调试分析 (x)4、用户手册 (x)5、测试结果 (6)6、程序清单 (7)4 小结 (10)1、课程设计的目的(1)熟练使用C++编写程序,解决实际问题;(2)了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;(3)初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;(4)提高综合运用所学的理论知识和方法独立分析和解决问题的能力;2、需求分析1、问题描述:编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。
设计一个程序来求出出列顺序。
2、要求:利用不带表头结点的单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
3、测试数据:m的初值为20,n=7 ,7个人的密码依次为3,1,7,2,4,7,4,首先m=6,则正确的输出是什么?输出形式:建立一个输出函数,将正确的输出序列3、课程设计报告内容概要设计:在理解了题目后,我先想到的是我们所学的单链表,利用单链表先建立循环链表进行存贮,建立完循环链表后,我将所要编写的函数分为了两块,一块是经过学过的单链表改编的循环链表的基本操作函数,还有一块是运行约瑟夫环的函数。
详细设计:我先建立一个结构体,与单链表一样,只是多了一个存密码的code域struct LinkNode{int data; //顺序int code; //密码LinkNode *next;};建立一个类LinkList ,包含的函数:LinkList(); //构造函数void Creat(const int ); //创建循环链表int Delete(LinkNode* ); //删除报到数的结点int Joseph(int ); // 约瑟夫环私有成员是LinkNode* head; //指向第一个结点的指针LinkNode* elem; // 同上int len; //长度我定义了一个elem指针是为了约瑟夫环里运行方便,elem只在约瑟夫环这个函数里用到,其他函数没有特别大的用处。
数据结构课程设计
JOSEPH(约瑟夫)环问题
班级学号4100507 学生姓名陈小军
提交日期2012-7-12 成绩
设计目的:
利用单项循环链表实现以下问题;
问题描述:编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个仍开始顺时针方向自1开始顺序报数,报到m 时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。
设计一个程序来求出出列顺序。
设计要求:
(1)利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号;
(2)输入数据:建立输入处理输入数据,输入m的初值,n ,输入每个人的密码,建立单循环链表;
(3)输出形式:建立一个输出函数,将正确的输出序列。
流程图如下:
主要算法说明:
本程序主要有两个函数。
即createlist,deletelist两个函数,createlist 函数主要是建立一个带位序和自身密码的单项循环链表,deletelist 是删除报到相应位置的结点(即相应的同学出列)
全部代码如下:
#include<iostream>
#include<cstdlib>
using namespace std;
#define N 100 //定义人数上限100,可以自己调整
#define OK 1
#define ERROR 0
structLNode/*定义每个结点的类型*/
{
int data;/*每个人所拥有的密码*/
intnum;/*每个人在圈中的位序*/
structLNode *next;
};
int a[N];
structLNode *CreateList(int n)/*生成n个结点的单向循环链表*/ {
structLNode *L,*p,*q;
int i;
int j=1;
L=q=(structLNode*)malloc(sizeof(structLNode));/*建立一个不带头结点的单向循环链表q为第一个结点。
*/
if(!q) return ERROR;
q->num=j;
cout<<"Number "<<j<<" student's privacy code is: ";
cin>>q->data;
cout<<"remain "<<n-j<<" student need to input"<<endl<<endl<<endl;
while(q->data<=0)
{
cout<<"Error! please input again"<<endl;
cout<<"Number "<<j<<" privacy code is: ";
cin>>q->data;
}
j=2;
q->next=L;
//q的下一个结点作为链表的下个L结点
for(i=1;i<n;i++)
{
p=(structLNode*)malloc(sizeof(structLNode)); //有n-1个结点,加上q一共是n个结点的链表
p->num=j;
cout<<"Number "<<j<<" student's privacy code is: ";
cin>>p->data;
cout<<"remain "<<n-j<<" student need to input"<<endl<<endl<<endl;
while( p->data<=0) {
cout<<"Error! please input again"<<endl;
cout<<"Number "<<j<<" privacy code is: ";
cin>>p->data;
}
j++;
int t=n-j;
q->next=p;
p->next=L;
q=q->next;
}
return (L);
}
structLNode *DeleteList(structLNode *L,intm,int n)/*报m的人出列*/
{
inti,j=0;
int k=n;
structLNode *p,*q,*pre;
pre=p=L;
do
{
i=1;
while(i<m-1){p=p->next;i++;}
if(m==1)
{
while(pre->next!=p) pre=pre->next;
m=p->data;/*得到新的密码*/
a[j]=p->num;/*得到出列人的序号*/
q=p;
pre->next=p->next;
p=p->next;
free(q); //释放位序为m的结点
L=pre=p;/*让新的报1的人作为头结点*/
k--;j++;
}/*if */
else
{
q=p->next;
m=q->data;
a[j]=q->num;
p->next=q->next;
p=q->next;
free(q);
L=pre=p;
k--;j++;
}/*else*/
}while(k>1);
a[j]=p->num;/*最后一个出列人的序号*/
return (L);
}
int main()
{
system("color 0b");
structLNode *L;
intj,n,m;
cout<<"Input total number of suudent n: ";
cin>>n;
while(n<=0||n>N)
{
cout<<"Error! please input again"<<endl;
cout<<"Input total number of people n: ";
cin>>n;
}
L=CreateList(n);
cout<<"Input the begin code m: ";
cin>>m;
while(m<=0)
{
cout<<"Error! please input again!"<<endl;
cout<<"Input the begin code m: ";
cin>>m;
}
DeleteList(L,m,n);
cout<<"the out order is: "<<endl;
for(j=0;j<n;j++)
cout<<a[j]<<" ";
cout<<endl;
return 0;
}
测试数据:
n=7 ,7个人的密码依次为3,1,7,2,4,7,4,首先m=6,则正确的输出是什么?
正确答案应该是:6 7 4 1 5 3 2
程序答案如下:
答案正确,也即验证了程序的正确性。
个人总结:
经过好多天的努力,终于完成了这个JOSEPH环的课程设计。
本想数据结构书上应该有单项循环链表的具体内容,不料只有寥寥几个字,心一下凉了。
这下可这么做啊。
突然想到了图书馆,就去图书馆借了一本关于链表的书籍参考。
本想学习全部内容的,无奈书太厚,时间太少,就针对单项链表的内容精读了一下。
基本对链表有些了解然后便开始着手程序。
刚上去就蒙了,只学过C++,而且也忘记了大部分。
没办法啊,只好翻箱倒柜的找到了C++。
用了几天的时间熟悉了一下内容。
终于憋了几天的时间,程序有点样子出来了。
但是还是有各种各样的问题,我一是上百度找,第二就是问同学了。
最后,在同学的帮助下。
程序终于写完了,也能正常运行了。
几天的辛苦没有白费啊。