约瑟夫环实习报告(参考)

合集下载

Joseph ring实习报告

Joseph ring实习报告

约瑟夫环问题模拟一、需求分析1、本演示程序模拟约瑟夫环问题:编号为1,2,……,n得n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。

一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。

报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。

2、演示程序以用户和计算机对话的方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中需要的相关信息及命令。

运算结果显示在其后。

3、程序需要输入的信息与命令包括:1)初始人数n ;2)n 个人的密码;3)初始的m 值;4、测试数据1)n:7 密码:3、1、7、2、4、8、4 m:62)n:1 密码:4 m:33)n:4 密码:4、2、3、1 m:124)n:3 密码:1、2、3 m:2二、概要设计为了实现上述程序功能,应以单向循环链表模拟问题过程。

每个结点代表一个玩家。

1、有序表抽象数据类型定义:ADT list{数据对象:D = {a i | a i ∈LNode, i = 1,2,……,n, n >= 0}数据关系:R = {<a i-1, a i> | a i-1, a i∈D, i = 2,……,n}基本操作:Init(&L)操作结果:构造一个空的单向循环链表。

Insert(&L, n, s)初始条件:链表L已存在,玩家编号n,玩家密码s。

操作结果:插入一个玩家结点。

Del(&L, m, e)初始条件:链表L已存在,m值有效。

操作结果:删除链表中第m个结点,并有e返回这个结点。

}ADT list2、本程序包含两个模块:a)主程序模块:int main(){初始化;接受命令;处理命令;退出;return 0;}b)循环单向链表单元模块——实现单向循环链表抽象数据类型;模块之间的调用关系如下:主程序模块↓单向循环链表单元模块三、详细设计int main() {//主函数main的实现int n, m, s, i;List l;if (Init(l)) { //初始化链表,执行成功后接受命令printf("how many players? : ");scanf("%d", &n);for (i = 1; i <= n; i++) {printf("the password of the number %d player: ", i);scanf("%d", &s);if (!Insert(l, i, s)) {printf("ERROR!");exit(1);}}//forprintf("Input the value of m: ");scanf("%d", &m);Lnode e;for (i = n; i >= 1; i--) { //处理命令,模拟人员的退出——结点的删除if (Del(l, m, e)) {printf("the number %d player come out\n", e.intNum);m = (m - 1 + e.intSec) % (i - 1);if (m == 0) m = i - 1;}}//for}//ifelse printf("ERROR!");return 0;}typedef struct Lnode {//链表结点类型定义int intNum;int intSec;struct Lnode *next;}Lnode, *Linklist;typedef struct {//循环单向链表类型定义Linklist head;Linklist tail;}List;bool Init(List &l) {//链表初始化l.head = l.tail = NULL;return true;}bool Insert(List &l, int N, int S) {//在链表末尾插入玩家号为N,玩家密码为S的结点Linklist p = (Linklist)malloc(sizeof(Lnode));if (!p) return false;p ->intNum = N;p ->intSec = S;if (!l.head) {l.head = p;}else {l.tail ->next = p;}p ->next = l.head;l.tail = p;return true;}bool Del(List &l, int m, Lnode &e) {//删除链表中第m个结点,并用e返回Linklist p = l.tail;if (!p || m < 1) return false;int cnt = 1;while (cnt < m) {p = p ->next;cnt++;}if (l.head == l.tail) {p ->next = NULL;e = *p;free(p);return true;}Linklist q = p ->next;if (q == l.tail) l.tail = p;if (m == 1) l.head = q ->next;p ->next = q ->next;q ->next = NULL;e = *q;free(q);return true;}四、调试分析1、由于程序时模拟约瑟夫环过程的,只是单纯的对问题的抽象解决,在数据范围不是很大的情况下程序可以比较迅速的完成问题的模拟,但是在大数据范围下,本程序模拟的方法是不适用的,需要更优化的算法。

实验报告——约瑟夫环

实验报告——约瑟夫环

《数据结构》课程设计报告课程名称:《数据结构》课程设计课程设计题目:约瑟夫环姓名:张光栋院系:计算机学院专业:网络工程年级:2013级学号:13055532指导教师:张纪林一、需求分析1.以单项循环链表存储结构模拟约瑟夫环问题。

即编号为1、2、3…、n的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。

一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数。

报m的人出列,将他的密码作为新的m值,从他在顺时针方向下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。

按出列顺序印出各人的编号。

2.演示程序以用户与计算机的对话方式执行,用户输入相应的数据,输出结果显示在其后。

3.测试数据:(1)n=55个人的密码依次为:2,4,2,6,2;首先m值为2(正确的输出顺序为:2 1 4 3 5)(2)n=77个人的密码依次为:2,4,1,4,3,2,3首先m值为5(正确的输出顺序为:5 1 3 4 6 2 7)二、概要设计为实现上述程序功能,可利用单向循环链表存储结构模拟此过程。

1.单向循环链表的抽象数据类型定义为:ADT CircularList{数据对象:D={ai|ai∈LNode,i=1,2,…,n,n≥0}数据关系:R1={<ai-1,ai>|ai-1∈D,i=2,…,n}基本操作:Status LisCreate_L(LinkList &L,int I,ElemType &e)操作结果:在不带头结点的单链表L中,创建第i个元素,并用e赋值}2.本程序中包括的两个基本模块:1)主程序模块:Void main(){初始化;do{接受命令;处理命令;}while(“命令”=”退出”)}2)循环链表模块:实现循环链表的抽象数据结构三、详细设计1.结点类型typedef struct ListNode{int mi;int n;struct ListNode *next;}ListNode,*LinkList;2.用循环链表存储约瑟夫环,没有头结点,基本操作函数如下:void CreateList(LinkList&L, int n){LinkList s;int i;L=(LinkList)malloc(sizeof(ListNode));L->n=1;L->next=L;for(i=2;i<=n;i++){s=(LinkList)malloc(sizeof(ListNode));s->next=L->next;L->next=s;s->n=i;L=L->next;}}void Delete(LinkList L, int m){int i;LinkList p,q;p=L;while(p->next!=p){for(i=1;i<m;i++)p=p->next;q=p->next;m=q->mi;printf("%d ",q->n);p->next=q->next;free(q);}printf("%d ",p->n);free(p);}3.主函数:int main(){int n,i,m;LinkList L,p;printf("请输入人数:");scanf("%d",&n);CreateList(L,n);printf("请输入密令\n");p=L->next;for(i=1;i<=n;i++){printf("请输入第%d条密令\n",i);scanf("%d",&p->mi);p=p->next;}printf("请输入初始密令\n");scanf("%d",&m);printf("输出为\n");Delete(L, m);return 0;}四、调试分析1.第一次写时,没有区分出只剩下的一个的情况,导致最终输出出现错误。

约瑟夫环问题实验报告

约瑟夫环问题实验报告

约瑟夫问题实验报告背景约瑟夫问题(Josephus Problem)据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

原题:用户输入M,N值,N个人围成一个环,从0号人开始数,数到M,那个人就退出游戏,直到最后一个人求最后一个剩下的人是几号?问题描述设编号为1-n的n(n>0)个人按顺时针方向围成一圈.首先第1个人从1开始顺时针报数.报m的人(m 为正整数).令其出列。

然后再从他的下一个人开始,重新从1顺时针报数,报m的人,再令其出列。

如此下去,直到圈中所有人出列为止。

求出列编号序列。

一.需求分析:(1)基本要求需要基于线性表的基本操作来实现约瑟夫问题需要利用循环链表来实现线性表(2)输入输出格式输入格式:n,m(n,m均为正整数,)输出格式1:在字符界面上输出这n个数的输出序列(3)测试用例(举例)输入:8,4输出:4 8 5 2 1 3 7 6二.概要设计(1)抽象数据类型:数据对象:n个整数数据关系:除第一个和最后一个n外,其余每个整数都有两个元素与该元素相邻。

基本操作:查找,初始化,删除,创建链表循环链表的存储结构:(2).算法的基本思想循环链表基本思想:先把n个整数存入循环链表中,设置第m个数出列,从第一个开始查找,找到第m个时,输出第m个数,并删掉第m个节点,再从下一个数开始查找,重复上一步骤,直到链表为空,结束。

(3).程序的流程程序由三个模块组成:1.输入模块:完成两个正整数的输入,存入变量n和m中2.处理模块:找到第m个数3.输出模块:按找到的顺序把n个数输出到屏幕上三.详细设计首先,设计实现约瑟夫环问题的存储结构。

约瑟夫环实验报告

约瑟夫环实验报告

约瑟夫环问题实验报告一、实验内容本实验利用单向循环链表模拟约瑟夫环问题(编号为1,2,…,n的n个人按顺时针方向围坐一圈,没人持有一个密码(正整数)。

开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m是停止报数。

报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止),按照出列顺序印出个人的编号。

M的初值为20,n=7,7个人的密码依次为3,1,7,2,4,8,4,首先m值为6。

二、源程序#include"stdafx.h"#include<iostream>using namespace std;#include<conio.h>//getch();/*write: Han.JH*/static int people_number_count; typedef struct People_Node{int Password_Data,people_number;struct People_Node *next;}People_Node,*People_LinkList;void GreatList(People_LinkList &L){People_Node *s,*r; int flag=1;int Password;L=new People_Node;L->next=NULL;r=L;while(flag==1){cout<<"输入每个人的密码,以回车作间隔,'0'表示结束:";cin>>Password;//输入每个人的密码;if(Password!=0){s=new People_Node;s->Password_Data=Password;people_number_count++; //对人的编号s->people_number=people_number_count;r->next=s;r=s;}else{ r->next=L->next;flag=0;}}}void GetList(People_LinkList &L){People_Node *r;int m,k;int count=0;cout<<"输入报数上限值m:";cin>>m;r=L;cout<<"出列排序:";while(count!=people_number_count){ //则所有人以出列,结束循环for(k=1;k<=m-1;k++){r=r->next;}count++;m=r->next->Password_Data;cout<<"["<<r->next->people_number<<"]";r->next=r->next->next;}}void main(){People_LinkList L;void GreatList(People_LinkList &);void GetList(People_LinkList &);cout<<"++++++++++++约瑟夫环问题+++++++++++"<<endl;GreatList(L);GetList(L);cout<<"[--结束--]"<<endl;getch();}三、调试刚开始调试时出现了无法打开<iostream.h>头文件的错误,经过上网查询,#include<iostream.h>是C语言风格,但是在标准 C 里面,是不用#include <iostream.h>的,而要使用#include <iostream>把#include<iostream.h>改为:#include<iostream>using namespace std;后,问题解决。

约瑟夫环心得(精品3篇)

约瑟夫环心得(精品3篇)

约瑟夫环心得(精品3篇)约瑟夫环心得篇3约瑟夫环问题是一个经典的数学问题,其历史可以追溯到古希腊时期。

这个问题涉及到循环数组、计数器和数学推理,对于了解算法和数据结构非常有用。

在这个问题中,我们考虑了一个循环数组,其中包含n个人,每个人的编号从1到n。

我们想要找到一种方法,使得经过m次移位后,所有的人都被消除。

为了解决这个问题,我们可以使用递归或循环算法。

递归算法是一种基于函数调用的方法,它可以通过不断地将当前数组中的最大值移除来解决问题。

然而,这种方法在处理大量数据时可能会导致堆栈溢出。

因此,我们需要使用循环算法来避免这种情况。

循环算法的基本思想是使用计数器来跟踪当前要移除的人的编号。

我们可以通过循环遍历数组,每次移除计数器所指向的人来实现移除操作。

然而,这种方法可能导致数组不循环,从而导致问题无法解决。

因此,我们需要使用计数器和移除操作来构建一个循环数组。

解决约瑟夫环问题需要仔细考虑算法的效率和适用性。

在实际应用中,我们需要考虑问题的规模和数据类型,以确保算法能够有效地处理大量数据。

同时,我们需要理解算法的原理和实现细节,以便更好地理解和优化算法。

总之,约瑟夫环问题是一个有趣的数学问题,它可以帮助我们更好地理解循环数组、计数器和数学推理。

在解决这个问题时,我们需要仔细考虑算法的效率和适用性,并理解算法的原理和实现细节。

约瑟夫环心得篇4心得体会应由本人根据自身实际情况书写,以下仅供参考,请您根据自身实际情况撰写。

约瑟夫环问题是一个经典的数学问题,它涉及到循环队列和约瑟夫问题的应用。

这个问题在计算机科学、数学和经济学等领域都有广泛的应用。

在解决约瑟夫环问题时,我们需要考虑一些关键的算法和数据结构。

首先,我们需要使用循环队列来模拟约瑟夫环中的环。

其次,我们需要使用递归或循环来解决约瑟夫问题。

最后,我们需要使用一些优化技巧来提高算法的效率。

通过解决约瑟夫环问题,我学到了很多有用的算法和数据结构。

例如,我学会了如何使用循环队列来模拟约瑟夫环中的环,如何使用递归或循环来解决约瑟夫问题,以及如何使用一些优化技巧来提高算法的效率。

约瑟夫环数据结构实验报告

约瑟夫环数据结构实验报告

约瑟夫环数据结构实验报告《约瑟夫环数据结构实验报告》摘要:本实验旨在通过使用约瑟夫环数据结构来模拟约瑟夫问题,并通过实验结果分析该数据结构的性能和适用场景。

实验结果表明,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且可以应用于一定范围的实际问题中。

1. 引言约瑟夫问题是一个经典的数学问题,描述了一个有n个人的圆桌围坐,从第一个人开始报数,报到m的人离开,然后从离开的人的下一个人开始重新报数,直到所有人离开。

在本实验中,我们将使用约瑟夫环数据结构来模拟这一问题,并分析其性能和适用场景。

2. 实验方法我们首先定义了一个约瑟夫环的数据结构,并实现了相应的插入、删除等操作。

然后,我们使用不同规模的数据集进行了实验,记录了每次操作的时间开销,并进行了性能分析。

3. 实验结果实验结果表明,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率。

在不同规模的数据集下,其操作时间基本保持在可接受的范围内,并且随着数据规模的增加,性能表现基本保持稳定。

4. 结论约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且可以应用于一定范围的实际问题中。

然而,在处理大规模数据时,仍需进一步优化算法和数据结构,以提高性能和效率。

5. 展望未来,我们将进一步研究约瑟夫环数据结构在实际问题中的应用,并探索其在其他领域的潜在价值。

同时,我们也将继续优化算法和数据结构,以提高其性能和适用范围。

综上所述,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且具有一定的实际应用价值。

通过本实验,我们对该数据结构有了更深入的了解,并为其在实际问题中的应用提供了一定的参考和借鉴。

工作报告之约瑟夫环实验报告总结

工作报告之约瑟夫环实验报告总结

约瑟夫环实验报告总结【篇一:约瑟夫环实验报告】实验报告课程名称:数据结构实验名称:顺序表和链表的应用实验编号:实验一指导教师:一、实验目的(1)掌握线性表的基本操作(插入、删除、查找)以及线性表合并等运算在顺序存储结构、链式存储结构上的实现。

重点掌握链式存储结构实现的各种操作。

(2)掌握线性表的链式存储结构的应用。

二、实验内容与实验步骤(1)实验内容:实现约瑟夫环,约瑟夫环(joseph)问题的一种描述是:编号为1、2、3……n的n个人按照顺时针方向围坐一圈,每人持有一个密码(正整数)。

一开始任选一个正整数作为报数的上限值m,从第一个人开始按照顺时针的方向自1开始顺序报数,报到m时停止报数。

报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。

设计一个程序求出出列顺序。

(2)抽象数据类型和设计的函数描述,说明解决设想。

首先定义一个链表,用其中的data项存储每个人的编号,用password项存储每个人所持有的密码,并且声明一个指针。

之后使用creatlist_cl函数来创建一个循环链表,在其中的data和password中存入编号和密码,最后使最后一个节点的next指向l,使其能够形成循环队列。

定义了函数display来显示链表当中的内容,以确定存储的数据没有错误。

定义了函数delete_l来实现约瑟夫环中依次删除的功能,依次比较,如果某个人所持的密码和m值相等,则删除这个结点,并且输出此时该结点的编号和密码,实现出列的功能。

(3)简短明确地写出实验所采用的存储结构,并加以说明。

该实验我主要采用的是线性表的链式存储结构,首先定义了链表的结构,其中包括data项和password项,分别存储每个人的编号和所持密码,还声明了指向下一个结点的指针,该指针可以连接各个结点,并且将最后一个结点的指针指向第一个结点使之成为一个循环链表。

三、实验环境操作系统:windows 7调试软件名称:vc++版本号:6.0上机地点:综合楼311四、实验过程与分析(1)主要的函数或操作内部的主要算法,分析这个算法的时、空复杂度,并说明设计的巧班级:学号:姓名:组号:实验成绩:批阅教师签字:实验日期:实验时间:妙之处。

数据结构约瑟夫环实习报告

数据结构约瑟夫环实习报告

数据结构约瑟夫环实习报告一、实习题目约瑟夫环(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. 理解并掌握约瑟夫问题的基本原理和解决方法。

2. 学习使用循环链表解决线性问题。

3. 提高编程能力和算法设计能力。

二、实验原理约瑟夫问题(Josephus Problem)是一个著名的数学问题,也称为约瑟夫环问题。

问题描述为:N个人围成一圈,从第一个人开始按顺时针方向报数,每数到M的人出列,然后从下一个人开始继续报数,直到所有人都出列。

我们需要找到一种方法,计算出每个人出列的顺序。

三、实验内容1. 创建一个循环链表,模拟N个人围成一圈。

2. 编写一个函数,实现报数和出列操作。

3. 输出每个人出列的顺序。

四、实验步骤1. 定义一个循环链表节点结构体,包含编号和指向下一个节点的指针。

2. 创建一个循环链表,包含N个节点,节点的编号依次为1到N。

3. 编写一个函数`kill(int m, int n)`,实现报数和出列操作:- 初始化一个指针指向第一个节点。

- 从第一个节点开始,按照报数上限M进行报数,每数到M的人出列。

- 更新指针,指向下一个节点,继续报数。

- 重复上述步骤,直到所有节点都被删除。

4. 输出每个人出列的顺序。

五、实验代码```c#include <stdio.h>#include <stdlib.h>// 定义循环链表节点结构体typedef struct Node {int number; // 节点编号struct Node next; // 指向下一个节点的指针} Node;// 创建循环链表Node create(int n) {Node head = NULL, tail = NULL, temp = NULL; for (int i = 1; i <= n; i++) {temp = (Node)malloc(sizeof(Node));temp->number = i;temp->next = NULL;if (head == NULL) {head = temp;tail = temp;} else {tail->next = temp;tail = temp;}}tail->next = head; // 形成循环链表return head;}// 输出循环链表void printList(Node head) {Node temp = head;do {printf("%d ", temp->number);temp = temp->next;} while (temp != head);printf("\n");}// 解决约瑟夫问题void josephus(int m, int n) {Node head = create(n);Node temp = head, pre = NULL;for (int i = 1; i <= n; i++) {for (int j = 1; j < m; j++) {pre = temp;temp = temp->next;}printf("%d ", temp->number);pre->next = temp->next; // 删除节点 free(temp);temp = pre->next;}printf("\n");}int main() {int m, n;printf("请输入报数上限M: ");scanf("%d", &m);printf("请输入人数N: ");scanf("%d", &n);printf("初始站队为: ");josephus(m, n);return 0;}```六、实验结果与分析通过运行实验代码,可以得到每个人出列的顺序。

约瑟夫环 实验报告

约瑟夫环 实验报告

约瑟夫环实验报告约瑟夫环实验报告引言:约瑟夫环是一个经典的数学问题,它源自于古代传说。

根据传说,古代犹太人被罗马人围困在一个洞穴中,他们决定用一种特殊的方式来决定谁将成为首领。

他们站成一个圆圈,从一个人开始,每隔一个人杀掉一个,直到只剩下一个人。

这个问题被称为约瑟夫环问题,它在数学领域引起了广泛的研究和探讨。

实验目的:本实验旨在通过模拟约瑟夫环问题,探讨其数学规律和解法,并分析实验结果的意义和应用。

实验步骤:1. 首先,我们需要确定参与约瑟夫环的人数n和每次报数的间隔m。

在本次实验中,我们选择了n=10和m=3。

2. 接下来,我们将10个人按顺序排成一个圆圈,并给每个人编号,编号从1到10。

3. 实验开始时,从第一个人开始报数,每次报数到m的人将被淘汰出局。

4. 淘汰的人将离开圆圈,下一个人将从淘汰者的下一个人开始报数,继续进行报数和淘汰的过程,直到只剩下一个人为止。

实验结果:通过模拟实验,我们得到了以下结果:- 第一轮淘汰的人依次为:3、6、9、2、7、1、8、5、10。

- 第二轮淘汰的人依次为:4、9、2、8、5、1、7、6。

- 第三轮淘汰的人依次为:9、8、5、1、7、4、6。

- 第四轮淘汰的人依次为:1、7、4、6、9、5。

- 第五轮淘汰的人依次为:7、4、6、9、5。

- 第六轮淘汰的人依次为:4、6、9、5。

- 第七轮淘汰的人依次为:6、9、5。

- 第八轮淘汰的人依次为:9、5。

- 第九轮淘汰的人依次为:5。

结论:通过实验结果的分析,我们可以得出以下结论:1. 在本次实验中,最后幸存的人是编号为5的人。

2. 根据实验结果,我们可以总结出约瑟夫环问题的一般解法。

假设总人数为n,每次报数的间隔为m,最后幸存的人的编号可以通过递归公式f(n,m)=[f(n-1,m)+m]%n得到。

3. 约瑟夫环问题在数学中具有一定的研究价值和应用意义。

它涉及到递归、数论等数学概念和方法,可以帮助我们更好地理解和应用这些数学知识。

数据结构实验报告约瑟夫环

数据结构实验报告约瑟夫环

数据结构实验报告约瑟夫环约瑟夫环是一个古老而有趣的问题,也是数据结构中一个经典的应用。

它的故事发生在公元前1世纪,当时犹太人正面临罗马的入侵。

为了避免被俘虏,一群犹太士兵决定以一种特殊的方式自杀,而不是被罗马人俘虏。

他们围成一个圈,按照某个规则进行自杀,直到只剩下一个人为止。

这就是著名的约瑟夫环问题。

在这个问题中,我们有n个人,编号从1到n,围成一个圈。

按照一定的规则,从第一个人开始报数,每次报到m的人将被淘汰。

然后,从下一个人开始重新报数,如此循环,直到只剩下一个人为止。

这个问题的解决方法有很多,其中最常见的是使用链表数据结构。

我们可以将每个人表示为一个节点,节点之间通过指针连接,形成一个环形链表。

每次淘汰一个人后,只需要将指针跳过被淘汰的节点,重新连接链表。

为了更好地理解这个问题,我们可以通过一个简单的例子来演示。

假设有10个人,编号从1到10,每次报数到3的人将被淘汰。

首先,我们将这10个人表示为一个环形链表:1->2->3->4->5->6->7->8->9->10->1。

按照规则,第一次报数到3的人是3号,所以我们将3号节点从链表中删除:1->2->4->5->6->7->8->9->10->1。

接下来,从4号节点开始重新报数。

第二次报数到3的人是6号,所以我们再次将6号节点从链表中删除:1->2->4->5->7->8->9->10->1。

以此类推,直到只剩下一个人为止。

通过这个例子,我们可以看到约瑟夫环问题的解决方法非常简单直观。

使用链表数据结构,每次淘汰一个人后,只需要将指针跳过被淘汰的节点,重新连接链表。

这种方法的时间复杂度为O(n*m),其中n为人数,m为报数的次数。

除了链表,还有其他数据结构可以用来解决约瑟夫环问题。

约瑟夫问题实验报告

约瑟夫问题实验报告

约瑟夫问题实验报告(文章一):约瑟夫问题数据结构实验报告中南民族大学管理学院学生实验报告实验项目: 约瑟夫问题课程名称:数据结构年级:专业:信息管理与信息系统指导教师:实验地点:管理学院综合实验室完成日期:小组成员:学年度第(一)、实验目的(1)掌握线性表表示和实现;(2)学会定义抽象数据类型;(3)学会分析问题,设计适当的解决方案;(二)、实验内容【问题描述】:编号为1,2,…,n 的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。

一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自 1 开始顺序报数,报到m 时停止报数。

报m 的人出列,将他的密码作为新的m 值,从他在顺时针方向上的下一个人开始重新从1 报数,如此下去,直至所有人全部出列为止。

试设计一个程序求出出列顺序。

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

【测试数据】:m 的初值为20;密码:3,1,7,2,4,8,4(正确的结果应为6,1,4,7,2,3,5)。

(三)、实验步骤(一)需求分析对于这个程序来说,首先要确定构造链表时所用的方法。

当数到m 时一个人就出列,也即删除这个节点,同时建立这个节点的前节点与后节点的联系。

由于是循环计数,所以才采用循环列表这个线性表方式。

程序存储结构利用单循环链表存储结构存储约瑟夫数据(即n个人的编码等),模拟约瑟夫的显示过程,按照出列的顺序显示个人的标号。

编号为1,2,?,n 的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。

一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1 开始顺序报数,报到m 时停止报数。

报m 的人出列,将他的密码作为新的m 值,从他在顺时针方向上的下一个人开始重新从1 报数,如此下去,直至所有人全部出列为止。

试设计一个程序求出出列顺序。

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

约瑟夫环实验报告

约瑟夫环实验报告

约瑟夫环实验报告约瑟夫环(Josephus problem)是一个非常经典的数学问题,其得名于公元1世纪的犹太历史学家约塞夫斯(Josephus)。

约瑟夫环问题描述如下:n个人围坐成一个圆圈,从一些人开始依次报数,每报到第m个人,该人就被淘汰出圆圈,然后从下一个人重新开始报数。

直到剩下最后一个人时,即为问题的解。

例如,当n=7,m=3时,最后剩下的是4号人。

本次实验的目的是研究约瑟夫环问题的解决方法,并通过编程实现给定n和m的情况下找到最后的获胜者。

首先,我们需要分析问题的特点。

当n=1时,该问题的解即为最后剩下的人;当n>1时,最后剩下的人可以通过前一轮问题的解(剩下n-1个人的情况下)推导出来。

我们可以将解决该问题的方法分为两种:递归法和迭代法。

一、递归法递归法是通过问题的子问题来解决原问题。

对于约瑟夫环问题来说,递归法的解题思路如下:1.当n=1时,问题的解即为1;2.当n>1时,问题的解为(找到n-1个人时的解+m-1)对n取模,即((f(n-1,m)+m-1)%n)+1二、迭代法迭代法通过循环来解决问题,不断更新当前的解,直到问题得到解决。

对于约瑟夫环问题来说,迭代法的解题思路如下:1.初始化一个长度为n的数组a,a[i]=1表示第i个人还在圆圈中,a[i]=0表示第i个人已经被淘汰出圆圈;2. 从第一个人开始计数,每报数到第m个人,则将该人设为已淘汰,并计数器count加1;3. 重复步骤2,直到count=n-1;4.循环遍历数组a,找到最后剩下的人。

为了更加直观地展示实验结果,我们通过Python编写下述代码:```python#递归法解决约瑟夫环问题def josephus_recursive(n, m):if n == 1:return 1else:return (josephus_recursive(n - 1, m) + m - 1) % n + 1#迭代法解决约瑟夫环问题def josephus_iterative(n, m):a=[1]*ncount = 0i=0while count < n - 1:if a[i] == 1:j=0while j < m:if a[(i + j) % n] == 1:j+=1else:j=0i=(i+1)%na[(i-1)%n]=0count += 1for i in range(n):if a[i] == 1:return i + 1#测试递归法解决约瑟夫环问题print(josephus_recursive(7, 3)) # 输出4 #测试迭代法解决约瑟夫环问题print(josephus_iterative(7, 3)) # 输出4 ```通过以上代码,我们可以得到n=7,m=3时,最后剩下的人是4号人。

约瑟夫环问题 实验报告完整版

约瑟夫环问题 实验报告完整版
struct Node
{
int data;//数据域
Node *next;//next指针指向下一个结点
};
3.算法设计
问题要求建立模型,确定存储结构,之后对任意n个人,密码为m,实现约瑟夫环问题,出圈的顺序可以依次输出,也可以用一个数组存储。
设计流程图如图1.1所示。
图1.1设计流程图
(1)创建循环链表
{
p=p->next;
}
q=p->next;
p->next=q->next;
p=p->next;
printf("第%3d个出圈的人是:%3d\n",i,q->value);
free(q);
}
scanf("\n");
p->next=NULL;
}
(3)主程序执行
主程序运行,调用函数,程序接受数据后,输出出圈列数。
}
(2)约瑟夫环报数的算法在运行为循环方式,报数者除非本身已经出去,否则继续顺序报数,其报数循环的代码为
void Joseph(NODE *p,int number,int n)
{
int i,j;
NODE *q=NULL;
for(i=1; i<=number; i++)
{
for(j=1; j<n-1; j++)
由于内容的要求以及问题的方便,用循环链表作为本次实验的抽象数据类型。申请一个结点作为第一个结点,之后调用creat_list函数将后续结点一次插入链接,构造为循环链表。
NODE *link(int number)
{
NODE *head=NULL,*p=NULL,*q=NULL;

约瑟夫环实习报告

约瑟夫环实习报告

实习报告:约瑟夫环实验一、实习背景约瑟夫环问题是一个经典的计算机科学和数学问题,起源于古罗马时期的历史故事。

问题描述了n个人围成一个圆圈,从第一个人开始报数,每数到m个人就将其删除,然后从下一个人重新开始报数,直到圈中只剩下一个人。

本实习报告旨在通过实现约瑟夫环算法,深入理解其原理和应用,并分析不同算法实现的时间和空间复杂度。

二、实习内容1. 算法实现本次实习实现了两种约瑟夫环算法的实现:迭代法和递归法。

迭代法使用循环结构模拟圆圈的过程,每轮删除指定数量的节点,直到只剩下一个节点。

递归法则利用递归函数模拟这个过程,每次递归调用删除指定数量的节点,直到只剩下一个节点。

2. 算法分析在算法分析方面,我们主要从时间复杂度和空间复杂度两个方面进行考虑。

对于迭代法,时间复杂度主要取决于删除节点的次数,每次删除操作的时间复杂度为O(1),因此总的时间复杂度为O(n)。

空间复杂度主要取决于程序的存储空间,由于使用了循环结构,空间复杂度为O(n)。

对于递归法,每次递归调用都会创建一个新的栈帧,因此空间复杂度主要取决于递归深度。

在最坏情况下,递归深度为n-1,因此空间复杂度为O(n)。

时间复杂度同样为O(n),因为每次递归调用都需要进行删除操作。

3. 实验结果我们使用Python语言实现了约瑟夫环算法,并使用Python的time模块测量了不同算法实现的时间。

实验结果显示,在n较小的情况下,迭代法和递归法的运行时间相差不大。

但随着n的增大,迭代法的运行时间逐渐优于递归法。

这是因为递归法在每次递归调用时都会创建新的栈帧,随着递归深度的增加,栈帧的创建和销毁会占用较多的时间。

三、实习心得通过本次实习,我对约瑟夫环问题有了更深入的理解。

在实现算法的过程中,我学会了如何使用循环结构和递归函数模拟圆圈的过程。

在分析算法的过程中,我学会了如何计算时间复杂度和空间复杂度,并能够根据实际情况选择合适的算法。

同时,我也认识到算法优化的重要性。

约瑟夫杯实验报告

约瑟夫杯实验报告

一、实验目的1. 理解并掌握约瑟夫环问题的基本原理。

2. 通过编程实现约瑟夫环问题,加深对循环链表的理解和应用。

3. 提高数据结构与算法的设计和实现能力。

二、实验环境1. 操作系统:Windows 102. 编程语言:Java3. 开发工具:Eclipse三、实验原理约瑟夫环问题是一个著名的数学问题,其基本模型如下:n个人围成一圈,从第一个人开始报数,每数到m的人出列,然后下一个人继续从1开始报数,直到所有人都出列。

该问题可以用循环链表来解决。

循环链表是一种线性链表,其特点是最后一个节点的指针指向链表的头节点,形成一个环。

在约瑟夫环问题中,每个节点代表一个人,节点的指针指向下一个节点,形成一个圆圈。

四、实验步骤1. 创建一个循环链表,用于存储所有人。

2. 添加一个方法,用于模拟报数过程,并输出出列顺序。

3. 添加一个方法,用于输出所有人的编号。

五、实验代码```javapublic class JosephusCircle {// 循环链表节点static class Node {int number; // 人的编号Node next; // 指向下一个节点public Node(int number) {this.number = number;this.next = null;}}// 创建循环链表public static Node createCircle(int n) {Node head = new Node(1);Node current = head;for (int i = 2; i <= n; i++) {current.next = new Node(i);current = current.next;}current.next = head; // 形成循环return head;}// 模拟报数过程public static void simulate(int n, int m) {Node head = createCircle(n);Node current = head;Node pre = null;while (current.next != current) { // 仍有节点在链表中for (int i = 1; i < m; i++) { // 报数m-1次pre = current;current = current.next;}pre.next = current.next; // 移除当前节点System.out.println("出列:" + current.number);current = current.next; // 继续下一个节点}System.out.println("最后出列的人编号:" + current.number); }// 输出所有人编号public static void printNumbers(int n) {Node head = createCircle(n);Node current = head;System.out.print("所有人编号:");while (current.next != current) {System.out.print(current.number + " ");current = current.next;}System.out.println(current.number);}public static void main(String[] args) {int n = 10; // 人数int m = 3; // 报数simulate(n, m);printNumbers(n);}}```六、实验结果1. 当人数为10,报数为3时,出列顺序为:3 6 9 2 5 8 1 4 7 10。

约瑟夫环实习报告(参考)

约瑟夫环实习报告(参考)

题目:编制一个程序模拟约瑟夫问题一﹑需求分析1. 本程序将模拟约瑟夫问题,求出出列的编号,并在每次出列后显示此时的顺序,本程序采用循环链表作为存储结构,无带头结点。

2. 输入可以是文件输入或标准输入,链表长度size>0,各个结点所带的密码值secret>0,第一次的报数m>0,若m<1,将提示更正。

3. 本程序在输入完毕后将先输出刚输入的内容,再提供报数后,开始进行运算,每出列一次将显示出列者和出列后链表顺序。

4. 测试数据:长度7,密码:3,1,7,2,4,8,4,报数初值6;长度-1,密码:3,2,5,6,4;长度5,密码:3,2,5,0,4; 长度5,密码:3,2,5,6,4,报数初值-1,4。

二﹑概要设计采用循环链表表示约瑟夫环1. 循环链表的抽象定义:ADT CycList{数据对象:D={i a ,i b |i a ,i b ∈ I ,i=1,2,…3,n>0}数据关系:R={<i a ,i b >|i a ,i b ∈D,I=1,2…3}基本操作:CreatList(&L,&in)初始条件:输入流有效,输入的值合法,申请空间成功操作结果:构造一个非空的循环链表PrintList(const L)初始条件:循环链表L 已存在操作结果:输出LFun(&L,Secret)初始条件:循环链表L 已存在操作结果:得到出列顺序}2. 本程序包含两个模块:1) 主程序模块2) 循环链表模块三﹑详细设计#include <iostream>using namespace std;//每个人的号码和密码。

struct people{int NO;int pass;}node;template <class Elem>class Link{private:static Link<Elem>* freelist;//静态数据成员的头接点。

约瑟夫环实验报告

约瑟夫环实验报告
#define max 1000//宏定义
class JosephCircle//定义JosephCircle类
{
public://定义成员函数
void input();
bool check();
void ruivate://定义成员变量
int totalNumber;
五、
1.使用了宏定义,在类初始化时定义了数组a[1000],造成内存大量浪费,降低了程序的效率;
2.类的封装不好,程序的可读性比较差;
3.注释描述不清。
六、
通过这次实验,对类和约瑟夫环的数组算法有了深刻的理解,对相关内容有了更熟练的掌握。由于对编程还不是很熟悉,实验过程中出现了很多错误,但调试过后大部分解决了。查阅资料,请教同学,分析问题,解决问题,提高了自己的动手能力。
int beginNumber;
int outNumber;
int a[max];
};
void JosephCircle::input()//输入人数、开始位置编号和第几个出列
{
cout<<"请输入人数: ";
cin>>totalNumber;
cout<<"请输入开始位置编号: ";
cin>>beginNumber;
return false;
}
return true;
}
void JosephCircle::run()//寻找合适的值
{
for(int j = 0; j < totalNumber; j++)//为数组赋值
{
a[j] = j + 1;
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

题目:编制一个程序模拟约瑟夫问题一﹑需求分析1. 本程序将模拟约瑟夫问题,求出出列的编号,并在每次出列后显示此时的顺序,本程序采用循环链表作为存储结构,无带头结点。

2. 输入可以是文件输入或标准输入,链表长度size>0,各个结点所带的密码值secret>0,第一次的报数m>0,若m<1,将提示更正。

3. 本程序在输入完毕后将先输出刚输入的内容,再提供报数后,开始进行运算,每出列一次将显示出列者和出列后链表顺序。

4. 测试数据:长度7,密码:3,1,7,2,4,8,4,报数初值6;长度-1,密码:3,2,5,6,4;长度5,密码:3,2,5,0,4; 长度5,密码:3,2,5,6,4,报数初值-1,4。

二﹑概要设计采用循环链表表示约瑟夫环1. 循环链表的抽象定义:ADT CycList{数据对象:D={i a ,i b |i a ,i b ∈ I ,i=1,2,…3,n>0}数据关系:R={<i a ,i b >|i a ,i b ∈D,I=1,2…3}基本操作:CreatList(&L,&in)初始条件:输入流有效,输入的值合法,申请空间成功操作结果:构造一个非空的循环链表PrintList(const L)初始条件:循环链表L 已存在操作结果:输出LFun(&L,Secret)初始条件:循环链表L 已存在操作结果:得到出列顺序}2. 本程序包含两个模块:1) 主程序模块2) 循环链表模块三﹑详细设计#include <iostream>using namespace std;//每个人的号码和密码。

struct people{int NO;int pass;}node;template <class Elem>class Link{private:static Link<Elem>* freelist;//静态数据成员的头接点。

public:struct people element;Link* next;Link(people elemval,Link* nextval=NULL) {element.NO=elemval.NO;element.pass=elemval.pass;next=nextval;}Link(Link* nextval=NULL){next=nextval;}void* operator new(size_t);// 重载new 函数。

void operator delete(void*);//重载delete函数。

};template <class Elem>class LList{private:Link<Elem> *head;Link<Elem> *tail;Link<Elem> *fence;void init(){head=tail=fence=new Link<Elem>;tail->next=head->next; //生成链表是要把它的头接点和尾接点连接起来构成循环链表。

//因为有一个空的头接点。

所以要把他的尾接点接到头接点的下一个指针。

}void removeall(){while(head!=NULL){fence=head;fence=fence->next;delete fence;}}public:LList(){init();}~LList(){removeall();}bool insert(const people& T); bool remove(Elem&);void getOut(int&,int&);void prev();bool append(const people& T); };template <class Elem>Link<Elem>* Link<Elem>::freelist=NULL;//静态数据成员的初始化。

//重载的实现。

template <class Elem>void* Link<Elem>::operator new(size_t){if(freelist==NULL)return ::new Link;Link<Elem>* temp=freelist;freelist=freelist->next;return temp;}//重载的实现template <class Elem>void Link<Elem>::operator delete(void* ptr){((Link<Elem>*)ptr)->next=freelist;freelist=(Link<Elem>*)ptr;}//插入函数。

此程序并没有用到次函数。

template <class Elem>bool LList<Elem>::insert(const people& T){fence->next=new Link<Elem>(T,fence->next);//通过调用构造函数的初始化。

if(tail==fence){tail=fence->next;tail->next=head->next;}return true;}//从链表的尾插入。

template <class Elem>bool LList<Elem>::append(const people& T){tail=tail->next=new Link<Elem>(T,head->next);//通过调用构造函数的初始化。

return true;}template <class Elem>bool LList<Elem>::remove(Elem& it){if(tail==head)return false;if(fence->next==NULL){it=fence->element.pass;cout<<fence->element.NO<<"-- ";return true;}it=fence->next->element.pass;cout<<fence->next->element.NO<<"-- ";Link<Elem>* temp=fence->next;fence->next=temp->next;if(temp==tail){tail=fence;//当是尾接点的时候要把他的尾指针指向标记指针}delete temp;return true;}//找下一个接点。

template <class Elem>void LList<Elem>::prev(){if(fence->next!=head)fence=fence->next;else{fence->next=head->next;fence=fence->next;}}//程序的主题//template <class Elem>void LList<Elem>::getOut(int &it,int& sum){int sign,n=1;fence=tail;//因为是从报到数的上一个人开始找到的删除点。

所以要记得从head 的上一个接点tail开始。

cout<<"Enter you want to first get out:";cin>>sign;//报数值。

while(sum>0){if(sign>sum&&sign>1) //为避免多次的循环找数通过取模可以节省时间。

sign=sign%sum;if(sign==n||sum==1){remove(it);sign=it;sum--;n=0;//重新做标记从下一个人1开始。

}elseprev();//找下个接点。

n++;}}int main(){LList<int> A;struct people T;int item,it,sum;cout<<"Enter you want to people:"; cin>>sum;for(int i=1;i<=sum;i++){cout<<"enter the--"<<i<<"--pass:"; cin>>item;T.NO=i;T.pass=item;A.append(T);//我这里是从尾插入的。

cout<<endl;}A.getOut(it,sum);return 0;}四﹑调试分析做此题关键点看是否把循环链表真的循环了,还有就是在删除接点的时候.要连接.特别是删除了尾接点.做好这些了,就是在进行报数出列的时候对报数和你做标记的处理.还有就是在当密码数大于个数是要进行取模减少循环次数.节约时间.此程序已经运行过是正确的.五.测试结果输入人数,密码(1)测试数据:size=7;secret=3,1,7,2,4,8,1;第一次报数:6;(2)测试数据:size=-1;第一次报数:无(3)测试数据:size=5;secret=3,2,5,0,4;(4)测试数据:size=5;secret=3,2,5,6,4;第一次报数-1;。

相关文档
最新文档