数据结构:约瑟夫环实验报告
约瑟夫环问题 实验报告
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、需求分析1:用一个循环链表实现n个人按顺时针排成一圈,每个人看作一个节点,每个节点都是一个结构体类型,包含三个域: 序号域(data), 密码域(key),指向下一个人的指针域(next).2:程序开始时由用户任意输入人数n及一个正整数作为报数上限值m,一个正整数作为密码最大值,判断所输密码是否在范围内。
然后为依次每一个人指定一个密码3:初始密码为用户外部输入的密码m, 从第一个人开始按顺市针方向自1开始报数.,报道m的时停止,报m的人出列,将他的密码作为新的密码值(m), 从他在顺针方向的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止.4:本程序最终结果为n 的人的出列顺序5:测试数据: m的初值为1; n =5(即有5个人)57个人的密码依次为:1,2,3,4,5.首先没的值为1,正确的出列顺序应为1,2,4,3,5。
2概要分析(1)抽象数据类型的定义:为实现上述程序的功能,可以用整数存储用户的输入。
并将用户输入的值存储于线性表中。
算法的基本思想:约瑟夫环问题中的数据是人所在的位置,而这种数据是存在“第一元素、最后元素”,并且存在“唯一的前驱和后继的”,符合线性表的特点。
由于需要模拟约瑟夫环的出列问题,可以采用顺序表来实现线性表,完成出列顺序的输出。
核心算法主要分为两步:1、确定需要删除的位置,2、设置并删除该位置。
已知报数间隔m,我们可以把当前位置加上m获得需要删除的位置,如果获得的位置超过顺序表中实际元素的总长度,则可以通过减去数组的实际长度来修正(即模拟环状计数)。
然后把顺序表中的当前指向位置设置为该位置,继而删掉该位置。
反复进行上述确定位置和删除位置的操作,直到顺序表为空。
(2)主程序的流程:程序由三个模块组成:(1)输入模块:无提示语句,直接输入总人数n和报数次数m,中间用逗号隔开。
(2)构造链表并输入每个人信息模块:(3)主要处理出列的函数:分别在DOS下和文件中,按移除元素的顺序依次显示其位置。
约瑟夫环-数据结构
实验二:Joseph(约瑟夫环)实验报告实验描述:编号为1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(报数上限)。
任意输入一个正整数作为报数上限值k(1<=k<=n),从第一个人开始顺时针方向报数,报到k时停止报数。
报k的人出列,然后从他下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。
设计一个程序来求出出列顺序。
实验原理:先构造一个不带头结点的单循环链表,然后定义两个节点指针,第一个指针指向第一个节点,另一个指针指向第二个节点,并且使两个节点后移,每当结点计数到某一结点时,将他的前驱结点接到他的后继结点,再将此结点删除。
如此循环,直到两个节点重合(只有一个节点)时,循环结束。
实验过程:1.基本算法以及分析:1创建结点Node链表都是由一个个结点组成,由于结点的不同,组成的链表也不同。
因此需要创建链表结点。
结点结构体如下:2建立单循环链表每当结点计数到某一结点时,将他的前驱结点接到他的后继结点,再将此结点删除。
如此循环下去,直到最后变为空的单循环链表为止。
3程序的执行过程:程序有主函数开始,首先输入创建约瑟夫环节点数以及密码(报数上限)。
然后,开始调用JosephuNode *Creat_Node函数,利用单循环链表建立起约瑟夫环,函数结尾return head; 将约瑟夫环的头指针返回,并将它赋值head,然后主函数继续调用Josephu函数,通过将head和Password引入函数,以建立两个嵌套循环输出并得到结果。
2.程序源代码:#include <stdio.h>#include <malloc.h>typedef struct Node{int Index;struct Node *next;}JosephuNode;void main(){JosephuNode *Creat_Node(int numbers);void Josephu(JosephuNode *head,int Password);int numbers, Password;JosephuNode *head;printf("\n输入约瑟夫环问题的人数和起始密码:");scanf("%d,%d", &numbers, &Password);head=Creat_Node(numbers);printf("\n输出结果如下\n");Josephu(head,Password);}JosephuNode *Creat_Node(int numbers) // 使用单循环链表创建约瑟夫环{int i,pass;JosephuNode *head, *tail;head = tail = (JosephuNode *)malloc(sizeof(JosephuNode)); //申请头结点for (i = 1; i <numbers; i++){tail->Index = i;tail->next = (JosephuNode *)malloc(sizeof(JosephuNode));tail = tail->next; //指针指向下一个结点}tail->Index = i;tail->next = head; //建立循环return head;}void Josephu(JosephuNode *head,int Password) //数据结构{int i,j;JosephuNode *rear;for (i = 1; rear != head; i++){for (j = 1; j <Password; j++){rear = head;head = head->next;}rear->next = head->next;printf("\n第%d个出局的人的编号是:%d",i,head->Index);free(head);head = rear->next;}j=head->Index;printf("\n最后一个出局的人的编号是:%d\n ",j);free(head);}。
数据结构约瑟夫环实验报告
《数据结构与算法设计》约瑟夫环实验报告——实验一专业:物联网工程班级:物联网1班学号:15180118姓名:刘沛航一、实验目的1、熟悉VC环境,学习使用C语言利用链表的存储结构解决实际的问题。
2、在编程、上机调试的过程中,加深对线性链表这种数据结构的基本概念理解。
3、锻炼较强的思维和动手能力和更加了解编程思想和编程技巧。
二、实验内容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、概要设计为了解决约瑟夫环的问题,我们可以建立单向环表来存储每个人的信息(该人的编号以及其下一个人的编号),及结点,人后通过查找每个结点,完成相应的操作来解决约瑟夫问题。
(1) 抽象数据类型定义ADT Joh{数据对象:D={|,1,2,,,0}i i a a ElemSet i n n ∈=≥K数据关系:R1=11{,|,,1,2,,}i i i i a a a a D i n --<>∈=K基本操作:create(&J, n)操作结果:构造一个有n 个结点的单向环表J 。
show(J)初始条件:单向环表J 已存在。
操作结果:按顺序在屏幕上输出J 的数据元素。
calculate( J,s,n)初始条件:单向环表J 已存在,s>0,n>0,s<环表结点数。
操作结果:返回约瑟夫环的计算结果。
}ADT Joh(2)宏定义#define NULL 0#define OK 1#define ERROR -1(3)主程序流程(4)程序分为下述模块:1)主函数模块——执行输入调用其他的功能函数2)创建环表模块——创建单向环表3)计算处理模块——计算出要出列的标号并输出4)显示模块——输出建立好的环表调用关系如下:2、详细设计(1)数据类型设计typedef int ElemType; //元素类型typedef struct {ElemType data;struct Joh *next;}Joh, *LinkList,*p; //结点类型,指针类型(2)操作算法Status create(LinkList &J,int n){//创建一个有n个结点的单向环表if(n<=0)return ERROR; //n<0错误J=(LinkList)malloc(sizeof(J));J->data=1;J->next=J;//建立第一个结点for(int i=n;i>1;--i){p=(LinkList)malloc(sizeof(J));p->data=i;p->next=J->next;J->next=p;//插入到表头}return OK;}//createvoid show(LinkList J){//主要的操作函数//顺序输出环表J的结点p=J;printf("%d ",p->data);p=p->next;while(p!=J){ //循环终止条件printf("%d ",p->data);p=p->next;}}//showvoid calculate(LinkList J,int s,int n){p=J;Joh *head=p; //声明结点while(p->data!=s){p=p->next;head=p;}//寻找起始结点while(p->next!=p){ //终止条件for(int i=0;i<n-1;i++){head=p; //保存前置节点p=p->next;}printf("%d ",p->data);head->next=p->next; //删除已输出结点p=head->next;}if(n!=1)printf("%d\n",p->data);elseprintf("\n");}//calculate(3)主函数代码int main(){//主函数Joh *J;int m,s,n;printf("The num of node is:");scanf("%d",&m);create(J,m); //创建单向环表Jshow(J); //输出J的数据printf("\n");printf("The first node which you want is:");scanf("%d",&s);printf("The internal which you want is:");scanf("%d",&n);calculate(J,s,n); //计算并输出结果return 0;}//main四、程序调试分析1、细节决定成败,编程最需要的是严谨,如何的严谨都不过分,往往检查了半天发现错误发生在某个括号,分号,引号,或者数据类型上。
北邮数据结构实验-约瑟夫环
北邮数据结构实验-约瑟夫环数据结构实验报告实验名称:实验1——约瑟夫环学生姓名:班级:班内序号:学号:日期:1.实验要求实验目的:通过利用循环链表实现约瑟夫问题的求解进行实现,掌握如下内容:1.熟悉C++语言的基本编程方法,掌握集成编译环境的调试方法2.学习指针、模板类、异常处理的使用3.掌握线性表的操作的实现方法4.学习使用线性表解决实际问题的能力实验内容:利用循环链表实现约瑟夫问题的求解。
约瑟夫问题如下:已知n个人(n>=1)围坐一圆桌周围,从1开始顺序编号。
从序号为1的人开始报数,顺时针数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规则重复下去,直到所有人全部出列。
请问最后一个出列的人的编号。
2. 程序分析2.1 存储结构首先构建结点的结构体,包括结点的编号number和指向后继元素的指针*next。
然后构建循环链表储存每一个结点。
2.2 关键算法分析1、关键算法:插入:用尾插法构建循环链表,建立一个尾指针r用来保存最后一个结点的地址,插入每一个节点后,r指向新插入的结点。
用for循环来给每一个结点的number赋值。
插入的步骤:1.建立新指针s;2.在for循环中给s赋值;3.将r指针指向s;4.修改尾指针r=s5.在全部结点插入后,将终端结点指向第一个指针,r->next=front->next。
约瑟夫环算法实现:1.因为每次循环都有一个人出列,最后只剩一个人,因此要进行n-1次循环,用for循环实现。
2.同时定义一个指针p=front->next,每次循环front和p均后移m-1个,使p指向每次循环的第m个人,front指向第m-1个人。
并输出出列的人的number,即p->number。
3.让front->next=p->next,删除p。
4.继续进行循环2、代码详细分析:约瑟夫环算法步骤:①定义一个指针p=front->next,每次循环front和p均后移m-1个,使p指向每次循环的第m个人,front指向第m-1个人。
约瑟夫环数据结构实验报告
约瑟夫环数据结构实验报告《约瑟夫环数据结构实验报告》摘要:本实验旨在通过使用约瑟夫环数据结构来模拟约瑟夫问题,并通过实验结果分析该数据结构的性能和适用场景。
实验结果表明,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且可以应用于一定范围的实际问题中。
1. 引言约瑟夫问题是一个经典的数学问题,描述了一个有n个人的圆桌围坐,从第一个人开始报数,报到m的人离开,然后从离开的人的下一个人开始重新报数,直到所有人离开。
在本实验中,我们将使用约瑟夫环数据结构来模拟这一问题,并分析其性能和适用场景。
2. 实验方法我们首先定义了一个约瑟夫环的数据结构,并实现了相应的插入、删除等操作。
然后,我们使用不同规模的数据集进行了实验,记录了每次操作的时间开销,并进行了性能分析。
3. 实验结果实验结果表明,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率。
在不同规模的数据集下,其操作时间基本保持在可接受的范围内,并且随着数据规模的增加,性能表现基本保持稳定。
4. 结论约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且可以应用于一定范围的实际问题中。
然而,在处理大规模数据时,仍需进一步优化算法和数据结构,以提高性能和效率。
5. 展望未来,我们将进一步研究约瑟夫环数据结构在实际问题中的应用,并探索其在其他领域的潜在价值。
同时,我们也将继续优化算法和数据结构,以提高其性能和适用范围。
综上所述,约瑟夫环数据结构在解决约瑟夫问题方面具有良好的性能和效率,并且具有一定的实际应用价值。
通过本实验,我们对该数据结构有了更深入的了解,并为其在实际问题中的应用提供了一定的参考和借鉴。
约瑟夫环数据结构实验报告
约瑟夫环数据结构实验报告约瑟夫环数据结构实验报告引言约瑟夫环是一种经典的数学问题,它涉及到一个有趣的数据结构。
本次实验旨在通过实现约瑟夫环数据结构,深入理解该问题,并探索其在实际应用中的潜力。
本报告将介绍实验的设计和实现过程,并分析实验结果。
实验设计在本次实验中,我们选择使用链表来实现约瑟夫环数据结构。
链表是一种非常灵活的数据结构,适合用于解决约瑟夫环问题。
我们设计了一个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值}}```五、实验结果与分析通过以上程序设计,我们可以得到约瑟夫环的出列顺序。
数据结构实验报告_约瑟夫环
typedef struct Node
{
int num;
int key;
struct Node *next;
}Node,*LinkList;
void main()
{
int n,m;
cout<<"请输入人数:";
cin>>n;
while(n<=0){
cout<<"人数不合法,请重新输入:";
{
cout<<p->num<<"号的密钥为"<<p->key<<endl;
p=p->next;
}
cout<<endl;
for(i=1;i<=n;i++)
{
for(int k=1;k<m;k++)
p=p->next;
q=p->next;
m=q->key;
cout<<"第"<<i<<"个出列的是"<<q->num<<"号"<<endl;
数据结构实验
题目:约瑟夫环
一、问题描述
用循环单链表实现约瑟夫环。
二、概要设计及存储表示
建立不带头结点的循环单链表,通过循环语句实现结点指针的传递及结点的删除,并输出删除的节点顺序。
每个结点分别存储一个序号及一个密钥两个变量,以及指向下一结点的指针。
三、调试分析
1.结点建立时发现错误,忘记结点应存储两个数据。
数据结构实验报告(杨辉三角-约瑟夫环)
数据结构实验报告实验一杨辉三角形(Pascal’s triangle)一、需求分析1.输入的形式和输入值的范围本程序中,需输入的杨辉三角级数level为正整数,由键盘输入,以回车结束2.输出的形式通过屏幕输出杨辉三角3.程序所能达到的功能用户从键盘输入需要的杨辉三角级数,从屏幕输出杨辉三角4.测试数据输入:5输出: 1 11 2 11 3 3 11 4 6 4 11 5 10 10 5 1二、概要设计以链队列结构实现该实验1.抽象数据类型定义ADT Queue {数据对象:D = { ai | ai∈ElemSet , i = 1,2,…,n,n≥0 }数据关系:R1={<ai-1,ai> | ai-1 , ai∈D, i=2,…,n}约定其中ai端为队列头,an端为队列尾基本操作:InitQueue ( &Q )操作结果:构造一个空队列QDestroyQueue ( &Q )初始条件:队列Q已存在操作结果:队列Q被销毁,不再存在ClearQueue ( &Q )初始条件:队列Q已存在操作结果:将Q清为空队列QueueEmpty ( Q )初始条件:队列Q已存在操作结果:若Q为空队列,则返回TRUE,否则FALSEQueueLength ( Q )初始条件:队列Q已存在操作结果:返回Q的元素个数,即队列长度GetHead ( Q , &e )初始条件:Q为非空队列操作结果:用e返回Q的队头元素EnQueue ( &Q , e )初始条件:队列Q已存在操作结果:插入元素e为Q的新队尾元素DeQueue ( &Q , &e )初始条件:Q为非空队列操作结果:删除Q的队头元素,并用e返回其值QueueTraverse ( Q , visit( ) )初始条件:Q已存在且非空操作结果:从队头到队尾,依次对Q的每个数据元素调用函数visit( )。
数据结构实验报告约瑟夫环
数据结构实验报告约瑟夫环约瑟夫环是一种经典的数学问题,它源于古代传说中的故事。
根据传说,约瑟夫是一位犹太历史学家,他和他的朋友们被罗马军队包围在一个洞穴里。
为了避免被俘虏,他们决定自杀,但是他们决定以一个特殊的方式来做。
他们围成一个环,从一个人开始,每隔一个人就杀死一个,直到只剩下一个人。
约瑟夫是最后一个幸存者。
这个问题可以用数据结构来解决,其中最常用的方法是使用循环链表。
循环链表是一种特殊的链表,它的最后一个节点指向第一个节点,形成一个环。
在解决约瑟夫环问题时,我们可以使用循环链表来模拟这个环。
首先,我们需要创建一个循环链表,并将所有的人依次添加到链表中。
然后,我们需要设置一个计数器,用来记录当前的位置。
接下来,我们需要遍历链表,每次遍历到计数器所指向的位置时,将该节点从链表中删除,并将计数器加一。
当计数器的值等于要删除的位置时,我们就将该节点删除,并将计数器重置为1。
重复这个过程,直到链表中只剩下一个节点为止。
通过使用循环链表,我们可以很方便地解决约瑟夫环问题。
这种方法的时间复杂度为O(n*m),其中n表示初始链表的长度,m表示要删除的位置。
由于每次删除一个节点后,链表的长度会减少,所以实际上的时间复杂度会小于O(n*m)。
除了使用循环链表,还可以使用数组来解决约瑟夫环问题。
我们可以创建一个长度为n的数组,然后将所有的人依次添加到数组中。
接下来,我们需要设置一个计数器,用来记录当前的位置。
然后,我们需要遍历数组,每次遍历到计数器所指向的位置时,将该人从数组中删除,并将计数器加一。
当计数器的值等于要删除的位置时,我们就将该人删除,并将计数器重置为1。
重复这个过程,直到数组中只剩下一个人为止。
与循环链表相比,使用数组解决约瑟夫环问题的方法更加简单。
但是,数组的长度是固定的,所以如果要解决的问题规模很大,可能会导致内存的浪费。
此外,数组的删除操作需要移动其他元素,所以时间复杂度较高。
综上所述,约瑟夫环问题是一个经典的数学问题,可以通过使用循环链表或数组来解决。
约瑟夫问题数据结构实验报告
约瑟夫问题数据结构实验报告实验概述本实验旨在通过实现约瑟夫问题的求解算法,深入理解链表数据结构的应用,以及算法的时间复杂度分析。
实验将通过编写程序来模拟约瑟夫问题,并测试不同规模下的时间性能,从而验证算法的准确性和效率。
实验目的●理解约瑟夫问题的定义和求解算法●掌握链表数据结构的基本操作●理解算法的时间复杂度分析方法实验内容1·约瑟夫问题约瑟夫问题是一个经典的数学问题,描述如下:n个人围成一圈,从第一个人开始报数,报到m的人出圈,然后从出圈的下一个人重新开始报数,直到剩下最后一个人。
2·数据结构设计为了解决约瑟夫问题,我们可以使用循环链表来表示n个人围成的圈。
链表节点的数据域存储每个人的编号,指针域指向下一个人。
3·算法设计约瑟夫问题的求解算法如下:1·创建一个循环链表,并初始化n个人的编号。
2·从第一个人开始,依次报数m次,直到找到第m个人。
3·将第m个人从链表中删除。
4·重复步骤2和3,直到只剩下最后一个人。
4·程序实现下面是约瑟夫问题求解算法的主要实现步骤:1·定义一个循环链表的结构,并实现链表的初始化操作。
2·实现算法的主函数,用于接收输入参数n和m,并调用其他函数进行求解。
3·实现一个函数,用于模拟报数过程,并返回每次报数的人的编号。
4·实现一个函数,用于删除链表中指定位置的节点。
5·实现一个函数,用于遍历链表,输出剩下的最后一个人的编号。
实验结果及分析在实验中我们分别测试了5个人和10个人的情况,对比了不同m值下的运行时间,并绘制了相应的曲线图。
实验结果表明,约瑟夫问题的求解算法在不同规模下的时间复杂度为O(nm),其中n为人数,m为报数值。
随着m值的增大,算法的运行时间也呈指数级增长。
附件本文档所涉及的附件包括:●源代码文件●实验结果数据文件●曲线图文件法律名词及注释本文档没有涉及法律名词及注释。
数据结构实验报告约瑟夫环
数据结构实验报告约瑟夫环约瑟夫环是一个经典的问题,涉及到数据结构中的循环链表。
在本次数据结构实验中,我们将学习如何使用循环链表来解决约瑟夫环问题。
约瑟夫环问题最早出现在古代,传说中的犹太历史学家约瑟夫斯·弗拉维奥(Josephus Flavius)在围攻耶路撒冷时,为了避免被罗马人俘虏,与其他39名犹太人躲进一个洞穴中。
他们决定宁愿自杀,也不愿被敌人俘虏。
于是,他们排成一个圆圈,从第一个人开始,每次数到第七个人,就将他杀死。
最后剩下的人将获得自由。
在这个问题中,我们需要实现一个循环链表,其中每个节点表示一个人。
我们可以使用一个整数来表示每个人的编号。
首先,我们需要创建一个循环链表,并将所有人的编号依次添加到链表中。
接下来,我们需要使用一个循环来模拟每次数到第七个人的过程。
我们可以使用一个指针来指向当前节点,然后将指针移动到下一个节点,直到数到第七个人为止。
一旦数到第七个人,我们就将该节点从链表中删除,并记录下该节点的编号。
然后,我们继续从下一个节点开始数数,直到只剩下一个节点为止。
在实现这个算法时,我们可以使用一个循环链表的数据结构来表示约瑟夫环。
循环链表是一种特殊的链表,其中最后一个节点的指针指向第一个节点。
这样,我们就可以实现循环遍历链表的功能。
在实验中,我们可以使用C语言来实现循环链表和约瑟夫环算法。
首先,我们需要定义一个节点结构体,其中包含一个整数字段用于存储编号,以及一个指针字段用于指向下一个节点。
然后,我们可以实现创建链表、添加节点、删除节点等基本操作。
接下来,我们可以编写一个函数来实现约瑟夫环算法。
该函数接受两个参数,分别是参与游戏的人数和每次数到第几个人。
在函数内部,我们可以创建一个循环链表,并将所有人的编号添加到链表中。
然后,我们可以使用一个循环来模拟每次数到第几个人的过程,直到只剩下一个节点为止。
在每次数到第几个人时,我们可以删除该节点,并记录下其编号。
最后,我们可以返回最后剩下的节点的编号。
约瑟夫环实验报告
约瑟夫环实验报告约瑟夫环(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号人。
约瑟夫环问题 实验报告完整版
(2)约瑟夫环报数的算法在运行为循环方式,报数者除非本身已经出去,否则继续顺序报数,其报数循环的代码为
void Joseph(NODE *p,int number,int n)
{
int;=number; i++)
{
for(j=1; j<n-1; j++)
(2)基本要求
建立模型,确定存储结构。
对任意n个人,密码为m,实现约瑟夫环问题。
出圈的顺序可以依次输出,也可以用一个数组存储。
(3)思考:
采用顺序存储结构如何实现约瑟夫环问题?
如果每个人持有的密码不同,应如何实现约瑟夫环问题?
2.数据结构设计
由于约瑟夫环问题本身具有循环性质,考虑采用循环链表,为了统一对表中任意结点的操作,循环链表不带头结点。将循环链表的结点定义为如下结构类型:
5.运行测试与分析
(1)输出提示,如图1.2所示。
(2)根据提示,输入圈内人数n和每个人持有的密码m如图1.3所示。
(3)输出结果如图1.4所示
分析
6.实验收获及思考
通过该实验,我进一步增强了对于链表的理解,也对链表的操作和实现更为熟悉,熟练掌握了如何实现置空表、求表的长度、取结点、定位运算、插入运算、删除运算、建立不带头结点的单链表(头插入法建表)、建立带头结点的单链表(尾插入法建表),输出带头结点的单链表等操作。同时,锻炼了实际操作时的动手能力。
{
p=p->next;
}
q=p->next;
p->next=q->next;
p=p->next;
printf("第%3d个出圈的人是:%3d\n",i,q->value);
约瑟夫环设计实验报告
一、实验目的1. 理解并掌握约瑟夫环问题的基本原理和解决方法。
2. 熟悉循环链表在数据结构中的应用,并能够运用其解决实际问题。
3. 提高编程能力和算法设计能力,培养逻辑思维和问题解决能力。
二、实验内容1. 实验背景约瑟夫环问题是一个经典的数学问题,描述了N个人围成一圈,按照一定的规则进行报数,最终确定出列顺序的过程。
该问题在计算机科学、通信等领域有广泛的应用。
2. 实验原理本实验采用循环链表作为数据结构来模拟约瑟夫环问题。
循环链表是一种线性表,其特点是最后一个节点的指针指向第一个节点,形成一个环。
在本实验中,我们将每个节点表示为一个人,节点的数据域存储该人的编号。
3. 实验步骤1. 初始化循环链表:首先创建一个循环链表,包含N个节点,节点编号依次为1, 2, ..., N。
2. 设置报数上限:从键盘输入一个正整数M,作为报数上限。
3. 模拟报数过程:a. 从链表头节点开始,按照顺时针方向进行报数。
b. 当报数达到M时,将当前节点出列,并将M的值设置为该节点的数据域。
c. 将指针指向下一个节点,继续进行报数。
d. 重复步骤b和c,直到链表中只剩下一个节点。
4. 输出出列顺序:按照出列的顺序,将每个节点的编号打印出来。
4. 实验代码```c#include <stdio.h>#include <stdlib.h>typedef struct Node {int number;struct Node next;} Node;// 创建循环链表Node createList(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 printOrder(Node head) {Node temp = head;while (temp->next != temp) {printf("%d ", temp->number); temp = temp->next;}printf("%d\n", temp->number);}int main() {int n, m;printf("请输入人数: ");scanf("%d", &n);printf("请输入报数上限: ");scanf("%d", &m);Node head = createList(n);printOrder(head);// 释放内存Node temp;while (head->next != head) {temp = head;head = head->next;free(temp);}free(head);return 0;}```5. 实验结果与分析通过运行实验代码,可以得到约瑟夫环问题的出列顺序。
约瑟夫问题数据结构实验报告
约瑟夫问题数据结构实验报告[正文]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.约瑟夫问题:亦称为约瑟夫环问题,是一个数学难题,起源于古代历史记载,已有几个世纪的历史。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实验报告题目:约瑟夫环姓名:学号:专业班级:指导教师:课题工作时间:一.需求分析1.约瑟夫环(Joseph)问题的一种描述是:设有编号1,2,3。
n(n>0)的N个人围成一个圈,每个人持有一个密码(正整数)。
开始时从第k(1<=k<=n)个人按顺时针方向自1开始顺序报数,报到m(m为第K个人的密码)的人出圈,再以这个人顺时针方向上的下一个人的密码为m,并开始重新从1报数。
如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
2.演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,有用户在键盘上输入演示程序中规定的运算命令,相应的输入数据和运算结果显示在其后。
3.测试数据(1)m=20, n=7, 结果依次为为3,1,7,2,4,8,4(2)m=20,n=1(3)m=20,n=0前面一组为常规数据,后面两组为边缘数据二、概要设计本程序是多文件程序,构成的函数有int main() 主函数,输出出队序列int initsuiji() 随机数产生初始化int suiji(int x,int y) 随机数产生函数int InitList(SqList &L) 初始化顺序表int ListInsert(SqList &L,int i,ElemType e) 在顺序表中插入元素int ListDelete(SqList &L,int i,ElemType &e) 删除顺序表中的元素int shunxu(int number) 顺序存储算法JosephuNode *Creat_Node(int numbers) 创建单循环链表void Josephu(JosephuNode *head,int Password) 添加元素信息int lianbiao(int number) 链表算法其中,void main()是最主要的函数,分别执行两种算法,并在执行的同时按照出列顺序输出元素信息(编号,密码),并在结尾输出两种算法执行所用的时间长短。
三、详细设计头文件#include <stdio.h>#include <malloc.h>#include <stdlib.h>#include <time.h>#include<iostream>typedef struct{int number;int password;}ElemType;typedef struct Node{int Index;int Password;struct Node *next;}JosephuNode;typedef struct{ElemType *elem;int length;int listsize;}SqList;#define LISTINCREMENT 10#define LIST_INIT_SIZE 100#define OK 1;#define ERROR 0;main.c#include"JosephuNode.h"int shunxu(int number);int lianbiao(int number);JosephuNode *head, *tail;ElemType temp;extern int ListInsert(SqList &L,int i,ElemType e); int m;SqList J;int initsuiji(){time_t t;srand((unsigned) time(&t));return 0;}int suiji(int x,int y){int k;k=rand()%(y-x+1)+x;return k;}JosephuNode *Creat_Node(int number){head = tail = (JosephuNode *)malloc(sizeof(JosephuNode)); //申请头结点return 0;}//Creat_Nodeint InitList(SqList &L){//初始化顺序表LL.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));if(!L.elem) return ERROR;L.length=0; //空表长度为0L.listsize=LIST_INIT_SIZE; //初始存储容量return OK;}int main(){int number,t_sx,t_lb,i,k;initsuiji();printf("输入人数:\t");scanf("%d",&number);InitList(J);Creat_Node(number);k=suiji(1,5);m=k;ListInsert(J,i,temp); //将节点插入顺序表for(i=0;i<number-1;i++){temp.password=suiji(1,100);temp.number=i+1;ListInsert(J,i,temp); //将节点插入顺序表tail->Index =i+1;tail->Password=temp.password; //产生当前结点所带密码tail->next = (JosephuNode *)malloc(sizeof(JosephuNode)); //申请一个新结点tail = tail->next;}//fortemp.password=suiji(1,100);temp.number=i+1;ListInsert(J,i,temp); //将节点插入顺序表tail->Index = i+1;tail->Password=temp.password;tail->next = head; //将尾结点指针指向表头printf("%d",m);t_sx=shunxu(number);m=k; //将m的值重置为初始值t_lb=lianbiao(number);printf("顺序存储法用时%dms\n",t_sx);printf("链表法用时%dms\n",t_lb);return 0;}shunxu.c#include"JosephuNode.h"using namespace std;extern ElemType temp;extern SqList J;extern int m;int ListInsert(SqList &L,int i,ElemType e){//在顺序表中第i个位置之前插入新的数据元素eElemType *base,*q,*p;if(i<0||i>L.length) return ERROR; // i值不合法if(L.length>=L.listsize){if(!(base=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType))))return ERROR; //存储分配失败L.elem=base; //新基地址L.listsize+=LISTINCREMENT; //增加存储容量}q=L.elem+i; //q为插入位置for(p=L.elem+L.length;p>=q;--p) //插入位置及之后的元素右移 *(p+1)=*p;*q=e; //插入e L.length++; //表长加1return OK;}int ListDelete(SqList &L,int i,ElemType &e){//在顺序表中删除第i个元素,并用e返回其值ElemType *p,*q;if(i<0||i>L.length-1) return ERROR; // i值不合法p=L.elem+i; // p为被删除元素的位置e=*p; //被删除元素的值赋给e q=L.elem+L.length-1; // q为表尾元素的位置 for(++p;p<=q;++p) //被删除元素之后的元素左移*(p-1)=*p;L.length--; //表长减1return OK;}int shunxu(int number){int i,p=0,j=1;clock_t start,end;start=clock();while(J.length>0){p--;for(i=0;i<m;i++) //报数m次找到出列的编号p=(p+1)%J.length;ListDelete(J,p,temp);m=temp.password; //获取新的m值printf("第%d个出局的玩家编号是%d\t",j,temp.number);printf("密码是%d\n",temp.password);j++;}//whileend=clock();return(end-start);}lianbiao.c#include"JosephuNode.h"using namespace std;extern int m;extern JosephuNode *head, *tail;///////////////////////////////////////////////// 约瑟夫环void Josephu(JosephuNode *head,int password){int i,j;for (i = 1; tail != head; ++i){for (j = 1; j <password; ++j){tail = head;head = head->next;}tail->next = head->next;printf("\n\t\t第%d个出局的人的编号是:%d\t密码是:%d",i,head->Index,head->Password);password=head->Password; //使用出局的人的密码free(head);head = tail->next;}printf("\n\t\t第%d个出局的人的编号是:%d\t密码是:%d\n",i,head->Index,head->Password);free(head);} //Josephu/////////////////////////////////////int lianbiao(int number){clock_t start,end;int password;start=clock();password=m;printf("%d",password);Josephu(head,password);end=clock();return(end-start);}四.运行与结果五.调试及收获1.在n比较小和N比较大时(N在500以内和10以上)链表法更快,当N的值很大(数千,甚至数万)时,链表法和顺序存储法的时间差距越来越大。