约瑟夫环实习报告
实验报告——约瑟夫环
![实验报告——约瑟夫环](https://img.taocdn.com/s3/m/bc916d5f77232f60dccca102.png)
《数据结构》课程设计报告课程名称:《数据结构》课程设计课程设计题目:约瑟夫环姓名:张光栋院系:计算机学院专业:网络工程年级: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.第一次写时,没有区分出只剩下的一个的情况,导致最终输出出现错误。
约瑟夫环问题实验报告
![约瑟夫环问题实验报告](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/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/bb992f3c227916888486d763.png)
约瑟夫环实验报告总结【篇一:约瑟夫环实验报告】实验报告课程名称:数据结构实验名称:顺序表和链表的应用实验编号:实验一指导教师:一、实验目的(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)主要的函数或操作内部的主要算法,分析这个算法的时、空复杂度,并说明设计的巧班级:学号:姓名:组号:实验成绩:批阅教师签字:实验日期:实验时间:妙之处。
数据结构约瑟夫环实习报告
![数据结构约瑟夫环实习报告](https://img.taocdn.com/s3/m/f2dea3594b7302768e9951e79b89680203d86b2c.png)
数据结构约瑟夫环实习报告一、实习题目约瑟夫环(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值}}```五、实验结果与分析通过以上程序设计,我们可以得到约瑟夫环的出列顺序。
约瑟夫问题实验报告
![约瑟夫问题实验报告](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;}```六、实验结果与分析通过运行实验代码,可以得到每个人出列的顺序。
(完整word版)约瑟夫环课程设计实验报告
![(完整word版)约瑟夫环课程设计实验报告](https://img.taocdn.com/s3/m/8cb50691b8f67c1cfad6b8d2.png)
《数据结构》课程设计报告课程名称:《数据结构》课程设计课程设计题目: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只在约瑟夫环这个函数里用到,其他函数没有特别大的用处。
约瑟夫环 实验报告
![约瑟夫环 实验报告](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/f04b1aa59a89680203d8ce2f0066f5335b816745.png)
数据结构实验报告约瑟夫环约瑟夫环是一个古老而有趣的问题,也是数据结构中一个经典的应用。
它的故事发生在公元前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为报数的次数。
除了链表,还有其他数据结构可以用来解决约瑟夫环问题。
约瑟夫环实验报告
![约瑟夫环实验报告](https://img.taocdn.com/s3/m/3af3f309680203d8ce2f2491.png)
处理命令 }
}
(3)输出链表信息模块
static void PrntList(参数){
定义变量并初始化;
输出命令;
}
(4)删除结点也就是出队模块
static void StatGame(参数){
定义变量并初始化;
While{
开始报数;
输出结果;}}
4.各程序模块之间的层次(调用)关系。
本程序包含以下模块:
(2)创建单循环链表函数模块代码
static void CreatList(circularlist * ppHead, const int n)
{
int i,ikey;
Node *pNew, *pCur;
for(i=1;i<=n;i++)
{
printf("请输入第%d个人所持有的密码:",i);
scanf("%d", &ikey);
#define OK 1
typedef int Status;
typedef double ElemType;
单向循环链表中节点的定义如下所示:
typedef struct LNode
{
int number;
int data;
struct LNode *next;
}LNode, *LinkList;
2.1主
2.2创建单循环链表函数流程图
2.3删除结点函数(出队函数)程序流程图
2.4子
四.
1.调试过程中遇到的问题及解决方法及对设计与实现的回顾讨论和分析
程序的编写和调试基本正常。遇到的问题有:指针的指向的边界问题。当执行输入人数时,输入0程序出现了意想不到的错误,所以再重新设计时加入了对空节点的处理。在链表节点的设计上,最初是仅包含密码和指针,但是后来考虑到链表节点删除时会带来一系列的编号变化,编号难以确定,所以节点设计上又加了一个编号。在单向链表的赋值操作时,原本是以一个不变的L作为头结点,但是这种赋值方法带来了诸多变量设计的问题,所以将L为节点,赋值完成后,再让L指向头结点。程序原本是没有求节点个数的函数,但是在约瑟夫环的实现函数中,节点的个数时时影响着结果的判断,所以加入了该函数。
约瑟夫环实验报告
![约瑟夫环实验报告](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/4bfd87c3e43a580216fc700abb68a98270feac72.png)
约瑟夫环实验报告约瑟夫环实验报告约瑟夫环是一种古老而有趣的数学问题,它源于古代传说中的一个故事。
根据这个故事,约瑟夫是一位犹太人,他和他的朋友们被罗马军队包围在了一个洞穴中。
他们决定宁愿死在洞穴里,也不愿被捕。
于是,他们决定通过一个特殊的方式来决定谁将是第一个自愿去死的人。
约瑟夫提出了一个规则:所有人围成一个圆圈,从某个人开始,每次数到一个固定的数字,该人就会被移除。
然后,继续数下去,直到只剩下一个人。
这个问题被称为约瑟夫环。
为了更好地理解这个问题,我们进行了一次约瑟夫环实验。
我们邀请了十个志愿者参与实验。
首先,我们让他们围成一个圆圈,按照顺时针方向依次编号为1到10。
然后,我们决定每次数到3的人将被移除。
实验开始后不久,我们就发现了一些有趣的现象。
首先,当数到第三个人时,他被移除了。
然后,我们继续数下去,每次数到第三个人,他们也被移除。
但是,当我们数到第九个人时,他并没有被移除。
相反,我们又从第一个人开始数。
这个过程一直持续下去,直到只剩下最后一个人。
通过这个实验,我们发现了约瑟夫环问题的一些规律。
首先,当总人数为奇数时,最后剩下的人的编号总是1。
这是因为每次移除一个人后,剩下的人重新排列,而编号为1的人始终在最后一个位置。
而当总人数为偶数时,最后剩下的人的编号取决于每次数到的数字。
例如,在我们的实验中,当总人数为10时,最后剩下的人的编号是5。
除了这些规律,约瑟夫环问题还有一些有趣的数学性质。
例如,我们可以通过数学推导得出,当总人数为2的幂次方时,最后剩下的人的编号总是1。
这是因为在每次移除一个人后,剩下的人的编号都会向前移动一个位置,而编号为1的人始终在最后一个位置。
通过这次实验,我们不仅更深入地了解了约瑟夫环问题,还发现了一些有趣的数学规律。
这个问题不仅仅是一个数学谜题,它也可以引发我们对数学的思考和探索。
我们相信,通过继续研究约瑟夫环问题,我们可以发现更多有趣的数学性质和规律。
总结起来,约瑟夫环是一个古老而有趣的数学问题,通过实验我们发现了一些规律和性质。
约瑟夫环问题 实验报告完整版
![约瑟夫环问题 实验报告完整版](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/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/7d896dc329ea81c758f5f61fb7360b4c2e3f2a75.png)
程序设计课程设计报告项目名称:约瑟夫环学生姓名:学号:班级:计科1111班指导老师:日期:2013年1月3号1、项目描述约瑟夫问题主要是n个人围坐成一个圈,然后分别给每个参与者编一个号,再定义一个循环数,由玩家自定义起始报数者,当游戏开始时,报数为循环数的人被踢出,其他人继续。
此设计就是通过一位数组、一维结构体数组与循环链表来实现这些功能的。
2、项目的需求分析在软件工程中,需求分析指的是在建立一个新的或改变一个现存的系统或产品时,确定新系统的目的、范围、定义和功能时所要做的所有工作。
需求分析是软件工程中的一个关键过程。
在这个过程中,系统分析员和软件工程师确定顾客的需要。
只有在确定了这些需要后他们才能够分析和寻求新系统的解决方法。
需求按层次分为用户需求和系统需求:用户需求是用自然语言加图的形式给出的、关于系统需要提供哪些服务以及系统操作受到哪些约束的声明;系统需求详细地给出系统将要提供的服务以及系统所受到的约束,系统需求文档有时也称为功能描述,应该是精确的,它可能成为系统买方和软件开发者之间合同的重要内容。
软件系统需求常常分为功能需求和非功能需求:功能需求包括对系统应该提供的服务、如何对特殊输入做出反应,以及系统在特定条件下的行为的描述,在某些情况下,功能需求可能还需声明系统不应该做什么;非功能需求是对系统提供的服务或功能的约束,包括时间约束、开发过程的约束和所受到的标准的约束,非功能需求经常适用于整个系统而不是个别的系统功能或服务,例如性能,可靠性,安全性和可用性等。
非功能需求通常会比个别的功能需求更加关键,它会影响整个系统的体系结构,而不是个别的组件。
例如,为了保证系统的性能需求,就必须合理组织系统使得组件之间的通信量达到最小。
图 1 需求获取和分析的产品2.1、界面需求Microsoft Visual C++ 6.0软件里面实现代码操作,Microsoft Office Word 20032.2、输入输出要求才用C++中的输入输出函数,即cin与cout,而在C中用printf即可。
约瑟夫环实习报告(参考)
![约瑟夫环实习报告(参考)](https://img.taocdn.com/s3/m/49b31436b90d6c85ec3ac6af.png)
题目:编制一个程序模拟约瑟夫问题一﹑需求分析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;//静态数据成员的头接点。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
综合实验约瑟夫环实习报告
一、实习题
约瑟夫(Joeph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
1.需求分析和说明
分析约瑟夫问题:n个人围成圈,每人各持一个密码,任选一个正整数作为报数上限值m,从第一个人开始,数到第m个人,删除并以出列者密码作为新的m值,从下一个人开始进行第二轮操作,直到所有人都出列。
例如n=6, m=3, 处理过程下图。
2.设计
n个人围圈,形成线性关系;处理为逐个删除,故用链式结构合适;又人员围成圆圈,所以此链式结构采用循环方式较好;排号按照一个方向进行,故数据结构采用带头结点的单向循环链表。
假设人员以首次的编号命名,对每个人员采用编号和密码加以描述。
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
存储结构:
typedef struct Node
{
ElemType date; //编号
int mima; //密码
struct Node *next;
}Node,*LinkList;
单向循环链表:
LinkList H; //表头指针
Node *Q,*Pre;//*Q指新建结点,*pre指向当前工作结点
Q=(Node*)malloc(sizeof(Node));
构造函数:
void InitList(LinkList *H); //初始化循环链表
void InPut(LinkList H,int *A);//插入结点
void DelList(LinkList H,int *x, int*a); //删除结点
算法思想:
声明一个Node类型的单向循环链表。
从键盘顺序输入n个人的密码, 建立约瑟夫环。
,定报数上限,计数并逐个读取并删除第m个结点,更新m的数值,重复上述步骤,直到链表为空。
调用关系:
程序任务简单,故设计在一个main()函数内,有主函数调研相关函数操作。
算法实现框架:
声明数据类型的单向循环链表->输入人数N->依次输入N个人的密码用尾插法建立循环链表->输入M的初值->按规则计数并调用删除函数并显示结点的序号释放该结点—>结点的
密码最为新的m值重复上一步操作直至链表元素全部出列
3.用户手册:
运行程序,按照屏幕提示分别输入圈内人数n,正整数m和n个人的密码,之后屏幕将显示按照输入次序排好的人员被逐个删除的次序。
4.调试报告:
时间复杂度分析:
该算法在建立时的时间复杂度为O(n), 删除时时间耗费在逐个数元素上而计数的个数由m确定,m由删除成员的密码确定,m的初值人为确定,最后出列的元素的密码将不起作用;故总删除总的时间为:所有密码(出最后出列的成员的密码)的乘机*m的初值。
复杂度为:O(n*m);时间复杂度也为:O(n*m);
综合建立和删除,算法时间复杂度为:O(n*m)
算法改进思路:
在对元素数数删除过程中,总是要去判断是否是头结点并绕过它,可以改进一下,去掉头结点,由此看来,并非链式结构带有头结点都有益处。
改进后性能可以提高,但时间复杂度依然为:O(n*m)
5.附录
源程序清单
#include<stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct Node
{
ElemType date; //编号
int mima; //密码
struct Node *next;
}Node,*LinkList;
void InitList(LinkList *H); //初始化循环链表
void InPut(LinkList H,int *A);//插入结点
void DelList(LinkList H,int *x, int*a); //删除结点
void main()
{
int m,i=1,x=0,a=0,j,n;
LinkList H; //表头指针
InitList(&H); //初始化
printf("输入几个人:");
scanf("%d",&n); //输入人的个数以控制插入元素次数
InPut(H,&n);
printf("输入M的值:"); //M存储删除结点的代号
scanf("%d",&m);
printf("约瑟夫环的值:");
for(i=1;i<=n;i++) //执行n次删除结点操作把所有元素都删除
H=H->next; //排除头结点干扰
do{
for(i=1;i!=m;i++) //搜索代号为m的点
H=H->next;
DelList(H,&x,&a); //删除结点,用X删除结点的前一结点的编号,用a存储结点的密码,x,a是指针变量
printf("%d\t",x);
m=a;
}while(H->next!=H); //H指向要删除结点的前一个结点
printf("%d",H->date);
free(H);
printf("\n");
}
void DelList(LinkList H,int *x, int*a)
{
Node *k;
k=H->next;
H->next=H->next->next;
*a=k->mima;
*x=k->date;
free(k);
}
void InitList(LinkList *H)
{
(*H)=(LinkList)malloc(sizeof(Node));
(*H)->next=(*H); //初始化环链表
}
void InPut(LinkList H,int *A) //尾插法建循环链表
{
int i,a;
Node *Q,*Pre;
Pre=H;
for(i=1;i<=*A;i++) // A指结点个数
{
printf("第%d个人的密码:",i);
scanf("%d",&a);
Q=(Node*)malloc(sizeof(Node));
Q->mima=a;
Q->date=i; //编号
Pre->next=Q;
Pre=Q;
}
Pre->next=H->next;//pre是最后一个结点指向第一个结点,形成循环
}
测试数据:
m的初值为20;密码:3,1,7,2,4,8,4(正确的结果应为6,1,4,7,2,3,5)。
测试及运行结果:
输入几个人:7
第1个人的密码:3
第2个人的密码:1
第3个人的密码:7
第4个人的密码:2
第5个人的密码:4
第6个人的密码:8
第7个人的密码:4
输入M的值:20
约瑟夫环的值为:6 1 4 7 2 3 5。