约瑟夫环问题 实验报告
约瑟夫环实验报告
![约瑟夫环实验报告](https://img.taocdn.com/s3/m/8723c1c782d049649b6648d7c1c708a1284a0a25.png)
约瑟夫环实验报告约瑟夫环是一个经典的数学问题,它涉及到一个有趣的游戏。
这个游戏的规则是:有N个人站成一圈,从某个人开始,每报数到第M个人,就将该人从圈中移出去,再从下一个人开始重新报数,如此循环,直到只剩下一个人为止。
那么,我们将通过实验来探究一下约瑟夫环的性质和一些有趣的现象。
首先,我们设定了一组实验条件。
假设有10个人,从1到10编号,报数为3。
我们选择从编号为1的人开始报数,然后每次报数到第3个人。
接下来,我们按照约瑟夫环的规则进行实验。
实验开始后,我们可以观察到一系列有趣的现象。
首先,被淘汰的人并不会立即离开圈子,而是继续留在原位,但不再参与后续的报数和淘汰。
当每次报数到达M的倍数时,即到了第3个人、第6个人、第9个人等等,这些人就会被逐渐淘汰出圈。
在实验过程中,我们发现了一个有趣的规律。
剩下的人似乎总是固定按照一定的顺序被淘汰。
为了更好地观察这个规律,我们进行了多组实验,并记录了淘汰顺序。
首先,在报数为3的情况下,我们记录了当有10个人时的淘汰顺序。
开始时,第1轮淘汰的是第3个人,然后是第6个人,之后是第9个人。
接着,轮到第2个人被淘汰,然后是第7个人,最后是第1个人。
可见,在这个实验条件下,被淘汰的顺序是3、6、9、2、7、1。
我们可以看到,在最后几轮淘汰时,被淘汰的顺序逐渐回到了初始的编号1。
接着,我们将实验条件略作改变,观察是否会出现相似的淘汰顺序。
这次,我们依然有10个人,报数为4。
开始时,第1轮淘汰的是第4个人,然后是第8个人,之后是第2个人。
接着,轮到第5个人被淘汰,然后是第10个人,最后是第6个人。
通过这次实验,我们可以观察到一些不同之处。
尽管淘汰的顺序在最后几轮回到了初始的编号1,但淘汰的间隔变得更长了,而且整体的淘汰顺序也有了一定的变化。
通过对约瑟夫环实验的多次观察和记录,我们可以总结出一些结论。
首先,淘汰的顺序呈现出周期性,并在最后几轮回到了初始的编号。
其次,在不同的实验条件下,淘汰的规律可能会有所不同。
约瑟夫环问题实验报告
![约瑟夫环问题实验报告](https://img.taocdn.com/s3/m/9bb953a8284ac850ad024282.png)
约瑟夫问题实验报告背景约瑟夫问题(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个数输出到屏幕上三.详细设计首先,设计实现约瑟夫环问题的存储结构。
实验报告 约瑟夫问题
![实验报告 约瑟夫问题](https://img.taocdn.com/s3/m/dc7295650b1c59eef8c7b463.png)
pCur->next = pNew;
pCur = pNew;
printf("结点%d,密码%d\n",pCur->id, pCur->cipher);
}
}
printf("完成单向循环链表的创建!\n");
}
(3)运行"约瑟夫环"问题
static void StartJoseph(NodeType **, int)
exit(-1);
}
pNew->id = iId;
pNew->cipher = iCipher;
pNew->next = NULL;
return pNew;
}
(6)测试链表是否为空,空为TRUE,非空为FALSE
static unsigned EmptyList(const NodeType *pHead)
实验内容
利用循环链表实现约瑟夫环求解。
实验说明
1.问题描述
约瑟夫问题的:编号为1,2,....,N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的M值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。
{
if(!pHead)
{
return TRUE;
}
return FALSE;
}
实验中遇到的问题及解决方法
实验结果如下:
实验总结(结果和心得体会)
约瑟夫环实验报告
![约瑟夫环实验报告](https://img.taocdn.com/s3/m/2bcd8ce9f18583d0486459f7.png)
约瑟夫环问题实验报告一、实验内容本实验利用单向循环链表模拟约瑟夫环问题(编号为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;后,问题解决。
约瑟夫环数据结构实验报告
![约瑟夫环数据结构实验报告](https://img.taocdn.com/s3/m/7d86238edb38376baf1ffc4ffe4733687f21fc78.png)
约瑟夫环数据结构实验报告《约瑟夫环数据结构实验报告》摘要:本实验旨在通过使用约瑟夫环数据结构来模拟约瑟夫问题,并通过实验结果分析该数据结构的性能和适用场景。
实验结果表明,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且可以应用于一定范围的实际问题中。
1. 引言约瑟夫问题是一个经典的数学问题,描述了一个有n个人的圆桌围坐,从第一个人开始报数,报到m的人离开,然后从离开的人的下一个人开始重新报数,直到所有人离开。
在本实验中,我们将使用约瑟夫环数据结构来模拟这一问题,并分析其性能和适用场景。
2. 实验方法我们首先定义了一个约瑟夫环的数据结构,并实现了相应的插入、删除等操作。
然后,我们使用不同规模的数据集进行了实验,记录了每次操作的时间开销,并进行了性能分析。
3. 实验结果实验结果表明,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率。
在不同规模的数据集下,其操作时间基本保持在可接受的范围内,并且随着数据规模的增加,性能表现基本保持稳定。
4. 结论约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且可以应用于一定范围的实际问题中。
然而,在处理大规模数据时,仍需进一步优化算法和数据结构,以提高性能和效率。
5. 展望未来,我们将进一步研究约瑟夫环数据结构在实际问题中的应用,并探索其在其他领域的潜在价值。
同时,我们也将继续优化算法和数据结构,以提高其性能和适用范围。
综上所述,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且具有一定的实际应用价值。
通过本实验,我们对该数据结构有了更深入的了解,并为其在实际问题中的应用提供了一定的参考和借鉴。
约瑟夫环问题报告
![约瑟夫环问题报告](https://img.taocdn.com/s3/m/9d8cd420dd36a32d73758131.png)
约瑟夫环问题一.需求分析1问题描述任务:编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个开始顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。
设计一个程序来求出出列顺序。
2.功能要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各个人的编号。
3.测试数据m的初值设为20,n=7;对应密码依次是:3, 2, 6, 4, 5, 9, 8;正确的出列顺序为6 2 4 3 1 5 7二、概要设计首先,设计实现约瑟夫环问题的存储结构。
由于约瑟夫环问题本身具有循环性质,考虑采用循环链表。
将循环链表的结点定义为如下结构类型:struct node{ //定义一个结构体(结点),其中包含一个数据域和一个指针域int num;int pw;struct node *next;};三、详细设计1 源程序#include<stdio.h>#include<stdlib.h>struct node{ //定义一个结构体(结点),其中包含一个数据域和一个指针域int num;int pw;struct node *next;};struct node *head;void main()// 进入主函数{system("color 1e");printf("\n 信息科学与技术学院电气0910班周涛涛\n\n\n");printf("***系统说明:编号是1,2,……,n的n个人按照顺时针\n");printf("***方向围坐一圈,每个人只有一个密码(正整数)。
");printf("一开始任选一个\n***正整数作为报数上限值m,从第一个仍开始顺时针方向自1开\n***始顺序报数,");printf("报到m时停止报数。
约瑟夫问题实验报告
![约瑟夫问题实验报告](https://img.taocdn.com/s3/m/1af80e9e0d22590102020740be1e650e53eacf07.png)
一、实验目的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;}```六、实验结果与分析通过运行实验代码,可以得到每个人出列的顺序。
约瑟夫斯问题
![约瑟夫斯问题](https://img.taocdn.com/s3/m/c3c0d417524de518974b7d0a.png)
实验一:约瑟夫斯问题实验报告一、问题描述1)问题描述约瑟夫斯(Josephus)问题的一种描述是:编号为1,2,…,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).二、需求分析1.该程序所能实现的功能:将n个数字按照某一特定序列输出,直至全部输出为止。
2.输入的形式及输入值范围:依次输入人数n、每个人的密码及报数上限m值。
3.输出的形式:按照报数上限m及每个人的密码依次输出每个人的编号。
4.测试数据要求:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4。
m初值为6(正确的出列顺序应为6,1,4,7,2,3,5)。
三、概要设计1.主程序流程获取每个人的密码,选定m的初值,调用函数,按照特定要求完成输出操作。
2.核心模块的算法伪码主程序:void main(void){int m;people *s;s=GetData();cout〈<"请输入m的初值:"<〈endl;cin〉〉m;DealData(s,m);}预编译代码:#include〈iostream。
h〉四、详细设计1。
实现每个操作的伪码,重点语句加注释(1)建立“人”的结构体struct people{int data;int num;people *next;};(2)获取每个人的相关数据people *GetData(){i nt n;p eople *p1,*p2,*head;h ead=NULL;c out<<”请输入人数:”;c in〉〉n;c out〈〈”请依次输入每个人的密码:”<〈endl;f or(int i=0;i<n;i++){p1=new (people);cin〉〉p1—>data;p1—>num=i+1;if(head==NULL){head=p2=p1; //建立首结点}else{p2-〉next=p1; //中间结点p2=p1;}}i f(head!=NULL)p2-〉next=head;r eturn(head); //循环链表}2。
约瑟夫环 实验报告
![约瑟夫环 实验报告](https://img.taocdn.com/s3/m/8be73b37a517866fb84ae45c3b3567ec112ddc5d.png)
约瑟夫环实验报告约瑟夫环实验报告引言:约瑟夫环是一个经典的数学问题,它源自于古代传说。
根据传说,古代犹太人被罗马人围困在一个洞穴中,他们决定用一种特殊的方式来决定谁将成为首领。
他们站成一个圆圈,从一个人开始,每隔一个人杀掉一个,直到只剩下一个人。
这个问题被称为约瑟夫环问题,它在数学领域引起了广泛的研究和探讨。
实验目的:本实验旨在通过模拟约瑟夫环问题,探讨其数学规律和解法,并分析实验结果的意义和应用。
实验步骤: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. 约瑟夫环问题在数学中具有一定的研究价值和应用意义。
它涉及到递归、数论等数学概念和方法,可以帮助我们更好地理解和应用这些数学知识。
约瑟夫环上机实验报告
![约瑟夫环上机实验报告](https://img.taocdn.com/s3/m/b8afe27e5b8102d276a20029bd64783e08127d47.png)
约瑟夫环上机实验报告1. 概述约瑟夫环问题是一个经典的数学问题,该问题是以约瑟夫·弗拉维奥(Josephus Flavius)命名的,故称为约瑟夫环。
问题的具体描述如下:在编号为1到n的n 个人围成一个圆圈,从第一个人开始报数,报到m的人出列,然后从出列的下一个开始重新从1到m报数,再次报到m的人再次出列,如此循环下去,直到所有的人都出列为止。
本次实验旨在使用程序实现约瑟夫环的模拟,并观察对于不同的参数n和m,最后剩余的人的编号特点。
2. 实验设计2.1 算法设计本实验中采用循环链表来模拟约瑟夫环,首先构建一个含有n个结点的循环链表,每个结点表示一个人,每个结点的数据域存储该人的编号。
然后根据报数规则,依次遍历链表,当报数为m时,删除对应的结点。
直到链表中仅剩一个结点为止。
2.2 程序实现pythonclass ListNode:def __init__(self, val=0):self.val = valself.next = Nonedef josephus(n, m):if n == 0:return -1构建循环链表dummy = ListNode(-1)cur = dummyfor i in range(1, n + 1):node = ListNode(i)cur.next = nodecur = cur.nextcur.next = dummy.next模拟游戏过程count = 0while cur.next != cur:count += 1if count == m:cur.next = cur.next.nextcount = 0else:cur = cur.nextreturn cur.val3. 实验结果为了观察不同参数n和m对最后剩余的人的编号的影响,我们进行了多组实验。
结果如下:n m 最后剩余的人的编号5 2 310 3 415 4 1420 5 6从实验结果可以看出,最后剩余的人的编号与参数m有关,而与参数n无关。
数据结构实验报告约瑟夫环
![数据结构实验报告约瑟夫环](https://img.taocdn.com/s3/m/bf5113b7f71fb7360b4c2e3f5727a5e9856a2789.png)
数据结构实验报告约瑟夫环约瑟夫环是一个经典的问题,涉及到数据结构中的循环链表。
在本次数据结构实验中,我们将学习如何使用循环链表来解决约瑟夫环问题。
约瑟夫环问题最早出现在古代,传说中的犹太历史学家约瑟夫斯·弗拉维奥(Josephus Flavius)在围攻耶路撒冷时,为了避免被罗马人俘虏,与其他39名犹太人躲进一个洞穴中。
他们决定宁愿自杀,也不愿被敌人俘虏。
于是,他们排成一个圆圈,从第一个人开始,每次数到第七个人,就将他杀死。
最后剩下的人将获得自由。
在这个问题中,我们需要实现一个循环链表,其中每个节点表示一个人。
我们可以使用一个整数来表示每个人的编号。
首先,我们需要创建一个循环链表,并将所有人的编号依次添加到链表中。
接下来,我们需要使用一个循环来模拟每次数到第七个人的过程。
我们可以使用一个指针来指向当前节点,然后将指针移动到下一个节点,直到数到第七个人为止。
一旦数到第七个人,我们就将该节点从链表中删除,并记录下该节点的编号。
然后,我们继续从下一个节点开始数数,直到只剩下一个节点为止。
在实现这个算法时,我们可以使用一个循环链表的数据结构来表示约瑟夫环。
循环链表是一种特殊的链表,其中最后一个节点的指针指向第一个节点。
这样,我们就可以实现循环遍历链表的功能。
在实验中,我们可以使用C语言来实现循环链表和约瑟夫环算法。
首先,我们需要定义一个节点结构体,其中包含一个整数字段用于存储编号,以及一个指针字段用于指向下一个节点。
然后,我们可以实现创建链表、添加节点、删除节点等基本操作。
接下来,我们可以编写一个函数来实现约瑟夫环算法。
该函数接受两个参数,分别是参与游戏的人数和每次数到第几个人。
在函数内部,我们可以创建一个循环链表,并将所有人的编号添加到链表中。
然后,我们可以使用一个循环来模拟每次数到第几个人的过程,直到只剩下一个节点为止。
在每次数到第几个人时,我们可以删除该节点,并记录下其编号。
最后,我们可以返回最后剩下的节点的编号。
约瑟夫环实验报告
![约瑟夫环实验报告](https://img.taocdn.com/s3/m/bca3e48f0d22590102020740be1e650e52eacfbe.png)
约瑟夫环实验报告约瑟夫环(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号人。
约瑟夫环问题 实验报告完整版
![约瑟夫环问题 实验报告完整版](https://img.taocdn.com/s3/m/5b0c897c7e21af45b307a865.png)
{
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;
约瑟夫实验报告
![约瑟夫实验报告](https://img.taocdn.com/s3/m/8859bf47cd1755270722192e453610661ed95ab9.png)
约瑟夫实验报告约瑟夫实验报告约瑟夫实验是一个经典的数学问题,它以约瑟夫斯·弗拉维奥(Josephus Flavius)的名字命名。
约瑟夫是一位古罗马时期的犹太历史学家和将军,他在犹太战争中被困在了一个洞穴里。
为了避免被敌人俘获,他和其他39名战士决定进行一项实验。
实验的规则是这样的:40个人站成一个圆圈,每个人都有一个编号,从1到40。
开始时,约瑟夫被指定为第一个被杀的人,而剩下的人依次按照顺时针方向报数,报数到3的人将被杀死。
然后,从下一个人开始,继续按照同样的规则进行报数,直到只剩下一个人为止。
这个问题的关键在于找到最后一个存活的人的编号。
我们可以通过编写一个简单的程序来解决这个问题。
首先,我们需要创建一个循环链表,其中每个节点都包含一个编号。
然后,我们可以使用一个循环来模拟报数的过程,并在每次报数到3时删除相应的节点。
最后,当链表中只剩下一个节点时,该节点的编号就是最后一个存活的人的编号。
通过对这个问题进行实验,我们可以得出一些有趣的结论。
首先,我们发现无论圆圈中的人数是多少,最后一个存活的人的编号总是1。
这是因为每次删除节点后,剩下的节点会重新排列,而最后一个节点的编号总是1。
其次,我们还发现当圆圈中的人数是2的幂次方时,最后一个存活的人的编号总是2。
这是因为每次删除节点后,剩下的节点会按照一定的规律重新排列,而最后一个节点的编号总是2的幂次方。
这个问题还可以引申出一些其他的数学问题。
例如,我们可以考虑每次报数的步长不是3,而是其他的数字。
我们可以通过修改程序中的报数规则来解决这个问题。
另外,我们还可以考虑圆圈中的人数不是固定的,而是一个变量。
我们可以通过修改程序中的链表长度来解决这个问题。
除了数学问题,约瑟夫实验还可以引发一些关于人性和生存的思考。
在这个实验中,每个人都面临着生与死的抉择。
他们必须决定是坚持到最后,还是在某个时刻选择自杀。
这个实验可以让我们思考人类对生命的珍视和对自身利益的权衡。
约瑟夫环实习报告
![约瑟夫环实习报告](https://img.taocdn.com/s3/m/b38940dccd22bcd126fff705cc17552707225ee7.png)
实习报告:约瑟夫环实验一、实习背景约瑟夫环问题是一个经典的计算机科学和数学问题,起源于古罗马时期的历史故事。
问题描述了n个人围成一个圆圈,从第一个人开始报数,每数到m个人就将其删除,然后从下一个人重新开始报数,直到圈中只剩下一个人。
本实习报告旨在通过实现约瑟夫环算法,深入理解其原理和应用,并分析不同算法实现的时间和空间复杂度。
二、实习内容1. 算法实现本次实习实现了两种约瑟夫环算法的实现:迭代法和递归法。
迭代法使用循环结构模拟圆圈的过程,每轮删除指定数量的节点,直到只剩下一个节点。
递归法则利用递归函数模拟这个过程,每次递归调用删除指定数量的节点,直到只剩下一个节点。
2. 算法分析在算法分析方面,我们主要从时间复杂度和空间复杂度两个方面进行考虑。
对于迭代法,时间复杂度主要取决于删除节点的次数,每次删除操作的时间复杂度为O(1),因此总的时间复杂度为O(n)。
空间复杂度主要取决于程序的存储空间,由于使用了循环结构,空间复杂度为O(n)。
对于递归法,每次递归调用都会创建一个新的栈帧,因此空间复杂度主要取决于递归深度。
在最坏情况下,递归深度为n-1,因此空间复杂度为O(n)。
时间复杂度同样为O(n),因为每次递归调用都需要进行删除操作。
3. 实验结果我们使用Python语言实现了约瑟夫环算法,并使用Python的time模块测量了不同算法实现的时间。
实验结果显示,在n较小的情况下,迭代法和递归法的运行时间相差不大。
但随着n的增大,迭代法的运行时间逐渐优于递归法。
这是因为递归法在每次递归调用时都会创建新的栈帧,随着递归深度的增加,栈帧的创建和销毁会占用较多的时间。
三、实习心得通过本次实习,我对约瑟夫环问题有了更深入的理解。
在实现算法的过程中,我学会了如何使用循环结构和递归函数模拟圆圈的过程。
在分析算法的过程中,我学会了如何计算时间复杂度和空间复杂度,并能够根据实际情况选择合适的算法。
同时,我也认识到算法优化的重要性。
约瑟夫杯实验报告
![约瑟夫杯实验报告](https://img.taocdn.com/s3/m/5a8a967d492fb4daa58da0116c175f0e7dd1197f.png)
一、实验目的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。
约瑟夫问题数据结构实验报告
![约瑟夫问题数据结构实验报告](https://img.taocdn.com/s3/m/f68e1157ae1ffc4ffe4733687e21af45b307fea3.png)
约瑟夫问题数据结构实验报告[正文]1.实验目的本实验的目的是分析约瑟夫问题,并设计合适的数据结构解决该问题。
2.实验背景约瑟夫问题,又称为约瑟夫环,是一个经典的数学问题。
问题描述如下:有n个人围成一圈,从第一个人开始报数,数到第m个人时将其杀死,然后从下一个人开始重新报数,数到第m个人又将其杀死,如此循环进行,直到所有人都被杀死为止。
求出最后一个被杀的人在初始序列中的编号。
3.实验设计为了解决约瑟夫问题,我们需要设计合适的数据结构来表示这个过程。
以下为实验所采用的数据结构:3.1 线性表由于约瑟夫问题是围成一圈的,因此我们选择使用循环链表来表示人围成的圈。
每个节点代表一个人,包含一个成员变量用于存储人的编号。
3.2 算法采用如下算法来解决约瑟夫问题:1.创建一个循环链表,将n个人的编号分别存入节点中。
2.初始化一个指针p指向链表的第一个节点。
3.从第一个人开始报数,每报到第m个人,将该节点从链表中删除。
4.如果链表中只剩下一个节点,此时的节点即为最后一个被杀的人,输出其编号。
4.实验步骤4.1 数据结构设计根据实验设计中的描述,我们编写了一个含有循环链表和节点的数据结构。
```cppstruct ListNode {int number;ListNode next;};```4.2 实现约瑟夫问题算法根据实验设计中的算法描述,我们编写了解决约瑟夫问题的函数。
```cppint josephusProblem(int n, int m) {// 创建循环链表// 初始化指针p// 开始报数并删除节点// 返回最后被杀的人的编号}```4.3 测试与分析我们通过输入不同的n和m值,测试了约瑟夫问题的解决函数,并对实验结果进行了分析。
5.实验结果经过测试,我们得到了约瑟夫问题的解。
6.实验总结通过本实验,我们深入了解了约瑟夫问题,并成功设计了合适的数据结构和算法解决了该问题。
附件本文档无附件。
法律名词及注释1.约瑟夫问题:亦称为约瑟夫环问题,是一个数学难题,起源于古代历史记载,已有几个世纪的历史。
约瑟夫环报数实验报告
![约瑟夫环报数实验报告](https://img.taocdn.com/s3/m/fa6a264a54270722192e453610661ed9ad51559d.png)
一、实验目的1. 理解并掌握约瑟夫环问题的基本概念和解决方法。
2. 熟悉链表数据结构及其操作,提高编程能力。
3. 通过实验加深对数据结构和算法的理解,提高解决实际问题的能力。
二、实验原理约瑟夫环问题是一个经典的数学问题,描述了N个人围成一圈,从某个人开始报数,报到M的人出列,然后从下一个人开始重新报数,如此循环,直到所有人都出列为止。
本实验通过实现单向循环链表来模拟这个过程。
三、实验内容1. 单向循环链表实现:- 定义单向循环链表的节点结构体,包含数据域和指针域。
- 实现创建单向循环链表的函数,从键盘输入N和M,生成包含N个节点的单向循环链表。
- 实现遍历单向循环链表的函数,用于输出链表中的节点信息。
2. 约瑟夫环报数:- 实现报数函数,从链表的第一个人开始报数,报到M的人出列。
- 实现删除节点的函数,将出列的人从链表中删除。
- 实现重新开始报数的函数,从下一个人开始重新报数。
3. 输出结果:- 实现输出出列顺序的函数,将出列的人的编号按顺序输出。
四、实验步骤1. 定义单向循环链表的节点结构体:```ctypedef struct Node {int data; // 数据域struct Node next; // 指针域} Node;```2. 实现创建单向循环链表的函数:```cNode createList(int n) {Node head = NULL;Node tail = NULL;Node tmp = NULL;for (int i = 1; i <= n; i++) {tmp = (Node)malloc(sizeof(Node)); tmp->data = i;tmp->next = NULL;if (head == NULL) {head = tmp;tail = tmp;} else {tail->next = tmp;tail = tmp;}}tail->next = head; // 形成循环链表return tail; // 返回尾节点}```3. 实现遍历单向循环链表的函数:```cvoid printList(Node tail) {Node p = tail->next; // 从头节点开始遍历while (p != tail) {printf("%d ", p->data);p = p->next;}printf("\n");}```4. 实现报数函数:```cvoid josephus(int n, int m) {Node tail = createList(n); // 创建单向循环链表Node p = tail->next; // 从头节点开始报数Node q = NULL; // 记录出列节点的前一个节点 for (int i = 1; i <= n; i++) {for (int j = 1; j < m; j++) {q = p;p = p->next;}q->next = p->next; // 删除出列节点printf("%d ", p->data); // 输出出列节点编号free(p); // 释放出列节点内存p = q->next; // 从下一个人开始报数}printf("\n");}```5. 实现输出出列顺序的函数:```cvoid printOutSequence(int n, int m) {printf("出列顺序为:\n");josephus(n, m);}```五、实验结果与分析1. 实验结果:- 当N=7,M=3时,出列顺序为:6 1 4 7 2 3 5。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
return count==0; } template <class T> bool SqList<T>::Full() const { return count==maxsize; } template <class T> int SqList<T>::Length() const { return count; } template <class T> void SqList<T>::Clear() { count=0; //这里并不是将所有元素删除,而是将元素个数置 0,实际上元素还在,但可以重新输入元素替换原来的元素 } template <class T> bool SqList<T>::SetElem(int position,const T &e) { if(position<1||position>Length()) //范围出错 { cout<<"范围出错,无法赋值!"<<endl; return false; } else { elems[position-1]=e; return true; } }
for(;i<=m;i++) { j++; if(j>len) j=1; while(S.GetElem(j)==0) { j++; if(j>len) j=1; } } if(j==0) j=1; cout<<S.GetElem(j)<<" "; S.SetElem(j,0); flag++; i=1; } cout<<endl; } return 0; } 测试用例:
数据结构课程实验报告实验一
实验题目:顺序表的应用 实验内容:约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按 顺时针方向围坐一圈,m为任意一个正整数。从第一个人开始顺时针方 向自1起顺序报数,报到m时停止并且报m的人出列,再从他的下一个人 开始重新从1报数,报到m时停止并且报m的人出列。如此下去,直到所 有人全部出列为止。要求设计一个程序模拟此过程,对任意给定的m和 n,求出出列编号序列。 一 设计分析: 1、定义一个List类,类中public:申明list(构造线性表);申明 add(向线性表尾加入元素b);申明delete(删除表中下标尾 index);申明display(输出线性表);getend(返回线性表的位置) 2、分别定义1中申明的函数 3、定义baoshu函数,用于执行从1开始计数,到m是输出并删除m,并从 下一个元素开始 从新记数。到表尾时,再从头计数,依次循环输出, 直到表空。 4、定义主函数,输入n、m。并执行相应的函数,并输出结果。 二 程序代码:#include <iostream> #include <cassert> using namespace std; template <class T> class SqList { protected: T *elems; //存放数据的数组 int count; //元素个数 size_t maxsize; //最大元素个数 void Init(size_t ); //初始化顺序表 public: SqList(size_t ); //构造 virtual ~SqList();//析构 bool Empty() const;//判断顺序表是否为空 bool Full() const;//判断顺序表是否已满 void Clear(); //清空顺序表 int Length() const;//求顺序表长度
//表已满
cout<<"表已满,无法增加元素!"<<endl; return false; } else { elems[count]=e; count++; return true; } } template <class T> void SqList<T>::Traverse(void(*Visit)(T &)) { for(int i=1;i<=Length();i++) { (*Visit)(elems[i-1]); } } int main() { while(1) { size_t n; cout<<"环中人数:"; cin>>n; SqList<int> S(n); for(int x=1;x<=n;x++) S.Add(x); int len=S.Length(); int m; cout<<"出列间隔:"; cin>>m; int i=1,j=0,flag=0; cout<<"出列序列:"; while(flag<len) { //加入元素e //表长加1
} SetElem(position,e); return true; } }
//将元素插
template <class T> bool SqList<T>::Delete(int position) { if(position<1||position>Length()) //范围出错 { cout<<"范围出错,无法删除元素!"<<endl; return false; } else if(Empty()) //表为空 { cout<<"表为空,无法删除元素!"<<endl; return false; } else { for(int i=position+1;i<=Length();i++) //从要删除的元素 开始,其后的每一个元素向前移动一位 { T e=GetElem(i); SetElem(i-1,e); } count--; //表长减1 return true; } } template <class T> bool SqList<T>::Add(const T &e) { if(Full()) {
//出列的元素置0以作标识
实验总结: 通过这次实验,对线性表有了更深刻的认识,对相关内容有了更熟练 的掌握。由于对编程还不是很熟悉,实验过程中出现了很多错误,但调 试过后大部分解决了。查阅资料,请教同学,分析问题,解决问题,提 高了自己的动手能力。
template <class T> T SqList<T>::GetElem(int position) { T e; if(position<1||position>Length()) { cout<<"范围出错,无法读取元素!"<<endl; exit(1); } else { e=elems[position-1]; } return e; } template <class T> bool SqList<T>::Insert(int position,const T &e) { if(position<1||position>Length()) //范围出错 { cout<<"范围出错,无法插入!"<<endl; return false; } else if(Full()) //表已满 { cout<<"表已满,无法插入!"<<endl; return false; } else { count++; //表长加1 for(int i=count;i>=position;i--) //从要插入的位置开 始,后面的每一个元素向后移一位 { T temp=GetElem(i-1); //用temp取出要移动的元素 SetElem(i,temp); //移到下一位
bool SetElem(int position,const T &e);//将第position个元素 设为e T GetElem(int position); //读取第position个元素 bool Insert(int position,const T &e);//在第position个位置插 入e bool Delete(int position); //删除第position个位置的元素 bool Add(const T &e); //将e加到表尾 void Traverse(void(*Visit) (T& )); //依次对表中每个元素调用 Visit元素 }; template <class T> void SqList<T>::Init(size_t size) { maxsize=size; if(elems!=NULL) delete []elems; elems=new T[maxsize]; assert(elems!=NULL); count=0; } template <class T> SqList<T>::SqList(size_t size) { elems=NULL; Init(size); } template <class T> SqList<T>::~SqList() { delete [] elems; } template <class T> bool SqList<T>::Empty() const {