约瑟夫环(C++)
约瑟夫环的知识点总结
约瑟夫环的知识点总结约瑟夫环这个问题不仅在古代受到了广泛的关注,而且在现代数学中也有着重要的地位。
它涉及到了排列、递推、循环和递归等多个数学概念,并且有着一些有趣的数学特性。
因此,学习约瑟夫环不仅能够增加我们对于数学问题的理解,而且也可以提高我们的数学思维能力。
接下来,我们将从几个方面对约瑟夫环进行深入的讨论。
1. 约瑟夫环的历史约瑟夫环最早出现在约瑟夫斯的《犹太古记》中,他描述了犹太人在与罗马军队的战斗中围攻马萨达城的情景。
根据《犹太古记》的记载,当罗马军队攻陷了马萨达城后,大约960名男子决定宁死不从。
于是,他们站成一个圈,每隔两个人就有一个杀掉,直到最后只剩下一个人。
而这个幸存者恰恰就是约瑟夫斯本人。
因此,这个问题就得名为约瑟夫环。
除了这个故事之外,约瑟夫环在古代数学文献中也有着多次的提及。
例如,中国古代数学家秦九韶在其著作《数书九章》中也提到了这个问题。
他利用递推的方法解出了约瑟夫环的一般解,并推广到了更一般的情况。
自古代以来,约瑟夫环一直受到数学家们的关注,他们提出了很多不同的方法来解决这个问题。
而到了现代,约瑟夫环在计算机科学和密码学中也有着广泛的应用。
因此,约瑟夫环问题可以说是一个古老而又具有重要意义的数学问题。
2. 约瑟夫环的一般解在数学中,我们可以用递推的方法对约瑟夫环进行求解。
假设有N个人站成一圈,编号从0到N-1,而每隔M个人就有一个人出列。
那么一个简单直接的方法就是用递归来求解。
具体来说,我们可以定义一个递归函数f(n, m),表示N个人中最后存活下来的那个人的编号。
那么这个函数的递归关系可以如下定义:f(n, m) = (f(n-1, m) + m) % n其中f(1, m) = 0,表示只有一个人时的情况。
通过递归的方法,我们可以得到约瑟夫环的一般解。
而根据这个递归关系,我们还可以得到一些有趣的数学性质。
例如,我们可以求解约瑟夫环在给定N和M的情况下的解,而不需要实际模拟整个过程。
C实验报告约瑟夫斯环问题
约瑟夫斯(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)。
4.简述每一部分的对象、目的和要求:(1)主函数部分:对象:链表;目的:创建新链表;要求:将该链表初始化。
(2)被调函数部分:对象:结构体;目的:创建循环链表并且模拟约瑟夫斯问题;要求:让链表首尾相接,并且释放原来单链表的头结点空间。
通过该函数的调用,依次输出各结点的编号,并且符合规则。
二.需求分析1.程序所能达到的基本可能:该程序用循环链表来模拟n个人顺时针围坐一圈,用链表中的每一个结点代表一个人,结点结构体中设置两个变量,分别存放其编号以及密码。
在输入初始密码后,对该链表进行遍历,直到遍历到第m个结点,释放其空间,使其出列。
然后用被释放空间结点的密码值作为新的密码值,重复上述过程,直至所有结点被释放空间出列,链表成为空链表。
2.输入输出形式及输入值范围:程序运行后显示提示信息:"Please input a data:",提示用户输入密码信息,在输入达预定次数后自动跳出该循环,同时循环链表创建成功,在主函数中有相应的输出给予检验。
然后程序显示提示信息:"Please input the number m:",提示用户输入初始密码,程序执行结束后会输出相应的出列结点的顺序,亦即其编号。
约瑟夫环c课程设计
约瑟夫环c 课程设计一、教学目标本节课的教学目标是让学生掌握约瑟夫环的原理和实现方法。
知识目标要求学生了解约瑟夫环的定义、算法实现和应用场景;技能目标要求学生能够运用约瑟夫环解决实际问题;情感态度价值观目标要求学生培养对计算机科学的兴趣,提高逻辑思维和编程能力。
二、教学内容本节课的教学内容主要包括约瑟夫环的定义、算法实现和应用场景。
首先,介绍约瑟夫环的定义和背景知识;其次,讲解约瑟夫环的算法实现,包括递归和非递归两种方法;最后,通过实例分析,让学生了解约瑟夫环在实际问题中的应用。
三、教学方法为了达到本节课的教学目标,采用多种教学方法相结合的方式。
首先,运用讲授法,为学生讲解约瑟夫环的基本概念和原理;其次,采用讨论法,让学生分组讨论约瑟夫环的算法实现,促进学生之间的交流与合作;然后,运用案例分析法,分析实际问题中的约瑟夫环应用,提高学生的应用能力;最后,通过实验法,让学生动手编写代码,巩固所学知识。
四、教学资源为了支持本节课的教学内容和教学方法的实施,准备以下教学资源:教材《数据结构与算法》、参考书《计算机算法》、多媒体资料(包括PPT、视频教程等)、实验设备(计算机、网络等)。
这些资源将有助于丰富学生的学习体验,提高教学效果。
五、教学评估为了全面、客观地评估学生的学习成果,本节课采用多元化的评估方式。
平时表现占30%,包括课堂参与度、提问回答等;作业占30%,考察学生对约瑟夫环原理的理解和应用能力;考试占40%,以闭卷形式检验学生的知识掌握和编程能力。
评估过程中,严格遵循公正、公平的原则,确保每位学生的成果得到合理评价。
六、教学安排本节课的教学安排如下:共计4课时,每课时45分钟。
第一课时,介绍约瑟夫环的定义和背景知识;第二课时,讲解约瑟夫环的算法实现;第三课时,分析实际问题中的约瑟夫环应用;第四课时,进行课堂总结和练习。
教学地点安排在教室,以确保学生能够集中精力学习。
七、差异化教学针对不同学生的学习风格、兴趣和能力水平,本节课采取差异化的教学策略。
c课程设计约瑟夫环
c 课程设计约瑟夫环一、教学目标本课程的目标是让学生理解和掌握约瑟夫环的原理及其在计算机科学中的应用。
知识目标包括:了解约瑟夫环的概念、算法实现和数学原理;技能目标涵盖:能够使用至少一种编程语言实现约瑟夫环算法,并进行简单的性能分析;情感态度价值观目标强调:培养学生的逻辑思维能力,激发他们对计算机科学和算法研究的兴趣。
二、教学内容教学内容围绕约瑟夫环的理论基础和实际应用展开。
首先介绍约瑟夫环的基本概念,然后通过编程实践让学生深入理解算法的工作原理。
具体包括:1.约瑟夫环的定义及其在计算机科学中的应用。
2.约瑟夫环算法的不同变体及其实现方法。
3.循环队列的概念及其在约瑟夫环算法中的作用。
4.通过编程练习,掌握至少两种不同的编程语言实现约瑟夫环算法。
三、教学方法为了提高学生的理解能力和实践技能,将采用多种教学方法相结合的方式:1.讲授法:用于解释约瑟夫环的基本概念和数学原理。
2.案例分析法:通过分析具体的约瑟夫环应用实例,加深学生对知识点的理解。
3.实验法:安排实验室实践环节,让学生亲自编写代码实现算法。
4.分组讨论法:鼓励学生在小组内交流想法,共同解决问题,培养团队协作能力。
四、教学资源为了支持课程的顺利进行,将准备以下教学资源:1.教材:《计算机科学基础》相关章节。
2.参考书籍:提供关于算法和数据结构的进阶阅读材料。
3.多媒体资料:制作PPT和视频教程,辅助学生理解复杂概念。
4.编程环境:为学生提供合适的编程环境和在线编程平台。
5.实验设备:确保实验室中每名学生都有足够的机器进行编程实践。
五、教学评估教学评估是衡量学生学习成果的重要手段。
本课程的评估方式包括:平时表现(30%)、作业(20%)、小测验(20%)、实验报告(20%)和期末考试(10%)。
平时表现评估将基于学生的课堂参与、提问和小组讨论;作业将主要是编程练习,旨在巩固课堂所学;小测验将定期进行,以检查学生的理解程度;实验报告将评价学生对实验操作的理解和分析能力;期末考试将涵盖所有课程内容,测试学生的综合理解能力。
约瑟夫环问题(Josephus)源代码讲解
原题:用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。
写出C程序。
(约瑟夫环问题 Josephus)提示:由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍然是围成一个圆圈的,可以使用循环表,由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每一次都指向一个具体的代表一个人的结点而不需要判断,链表不带头结点。
所以,对于所有人围成的圆圈所对应的数据结构采用一个不带头结点的循环链表来描述。
设头指针为p,并根据具体情况移动。
为了记录退出的人的先后顺序,采用一个顺序表进行存储。
程序结束后再输出依次退出的人的编号顺序。
由于只记录各个结点的number值就可以,所以定义一个整型一维数组。
如:int quit[n];n为一个根据实际问题定义的一个足够大的整数。
代码:/******************************************************************** created: 2006/06/14 filename: C:\Documents and Settings\Administrator\桌面\tmpp\josephus.c file path: C:\Documents and Settings\Administrator\桌面\tmpp file base: josephus file ext: c author: A.TNG version: 0.0.1 purpose: 实现 Josephus 环问题用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。
写出C程序。
(约瑟夫环问题 Josephus)*********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> /* 结构体和函数声明 */ typedef struct _node_t { int n_num; struct _node_t *next; } node_t; node_t *node_t_create(int n); node_t *node_t_get(node_t **pn, int m); /* 功能函数实现 */ /* * name: node_t_create * params: * n [in] 输入要构造的链表的个数 * return: * 返回构造成功的环形单向链表指针 * notes: * 构造节点数量为 n 的环形单向链表* * author: A.TNG 2006/06/14 17:56 */ node_t * node_t_create(int n) { node_t *p_ret = NULL; if (0 != n) { int n_idx = 1; node_t *p_node = NULL; /* 构造 n 个 node_t */p_node = (node_t *) malloc(n * sizeof(node_t)); if (NULL == p_node) return NULL; else memset(p_node, 0, n * sizeof(node_t)); /* 内存空间申请成功 */ p_ret = p_node; for (; n_idx < n; n_idx++) { p_node->n_num = n_idx; p_node->next = p_node + 1;p_node = p_node->next; } p_node->n_num = n;p_node->next = p_ret; } return p_ret; } /* * name: main * params: * none * return: * int * notes: * main function * * author: A.TNG 2006/06/14 18:11 */ int main() { int n, m; node_t *p_list, *p_iter; n = 20; m = 6; /* 构造环形单向链表 */ p_list =node_t_create(n); /* Josephus 循环取数 */ p_iter = p_list; m %= n; while (p_iter !=p_iter->next) { int i = 1; /* 取到第 m-1 个节点 */ for (; i < m - 1; i++) { p_iter =p_iter->next; } /* 输出第 m 个节点的值 */ printf("%d\n", p_iter->next->n_num); /* 从链表中删除第 m 个节点 */ p_iter->next = p_iter->next->next; p_iter = p_iter->next; } printf("%d\n", p_iter->n_num); /* 释放申请的空间 */ free(p_list); system("PAUSE"); }。
约瑟夫环问题源代码(C语言)
约瑟夫环问题如下:已知n个人(n>=1)围桌一园桌周围,从1开始顺序编号。
从序号为1的人开始报数,顺时针数到m的那个人出列。
他的下一个人又从1开始报数,数到m的那个人又出列。
依此规则重复下去,直到所有人全部出列。
求解最后一个出列的人的编号。
本次实验是以顺序表求解约瑟夫环问题,程序流程图及程序运行结果如下:输入人数、所报数、第一个报数人编号存储并建立一个约瑟夫环通过循环结构依次查找每次出列的人的编号并输出输出最后一个出列的人的编号程序代码如下:#include<iostream>#include<process.h>#include<stdlib.h>using namespace std;struct Node //循环节点的定义{int number; //编号Node *next;};Node *CreateList(Node *L,int &n,int &m); //建立约瑟夫环函数void Joseph(Node *L,int n,int m); //输出每次出列号数函数Node *DeleteList(Node **L,int i,Node *q); //寻找每次出列人的号数int LengthList(Node *L); //计算环上所有人数函数void main() //主函数{system("color 75"); //设置颜色以美观Node *L;L=NULL; //初始化尾指针int n, m;cout<<"请输入人数N:";cin>>n; //环的长度if(n<1){cout<<"请输入正整数!";} //人数异常处理else{cout<<"请输入所报数M:";cin>>m;if(m<1){cout<<"请输入正整数!";} //号数异常处理else{L=CreateList(L,n,m); //重新给尾指针赋值Joseph(L,n,m);}}system("pause");}Node *CreateList(Node *L,int &n,int &m) //建立一个约瑟夫环(尾插法){Node *q;for(int i=1;i<=n;i++){Node *p;p=new Node;p->number=i;p->next=NULL;if(i==1) L=q=p; //工作指针的初始化 else{q->next=p;q=q->next;}}q->next=L;if(L!=NULL){return(L);} //返回尾指针else cout<<"尾指针异常!"<<endl; //尾指针异常处理}void Joseph(Node *L,int n,int m) //输出每次出列的人{int k;cout<<"请输入第一个报数人:";cin>>k;if(k<1||k>n){cout<<"请输入1-"<<n<<"之间的数"<<endl;}else{cout<<"\n出列顺序:\n";for(int i=1;i<n;i++){Node *q = new Node;if(i==1) q=DeleteList(&L,k+m-1,q); //第一个出列人的号数else q=DeleteList(&L,m,q);cout<<"号数:"<<q->number<<endl;delete q; //释放出列人的存储空间}cout<<"最后一个出列号数是:"<<L->number<<endl; //输出最后出列人的号数}}Node *DeleteList(Node **L,int i,Node *q) //寻找每次出列的人{if(i==1) i+=LengthList(*L); //顺序依次出列情况的处理方式Node *p;p=*L;int j=0;while(j<i-2) {p=p->next;j++;}q = p->next;p->next=p->next->next;*L = p->next;return(q);}int LengthList(Node *L) //计算环上的人数{if(L){cout<<"尾指针错误!"<<endl;} //异常处理else{int i=1;Node *p=L->next;while(p!=L){i++;p=p->next;}return(i);}}实验体会:通过对本问题的分析,我进一步熟悉了对各种逻辑表达式的判断和指针的使用。
约瑟夫环多种程序实现
约瑟夫环问题:约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。
从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
第一种方法:要求将每次出列的人的序号输出,并输出最后一个出列的人。
代码如下://c语言用数组实现约瑟夫环#include<stdio.h>#include<stdlib.h>void main(){int y(int n,int m);int p,q,r;printf("请输入参选人的个数p和开始的位置q:\n");scanf("%d%d",&p,&q);r=y(p,q);printf("最后那个人的初始位置是:%d\n",r);}int y(int n,int m){int i,j=0,s=0,l;int *a=(int *)malloc(sizeof(int));int *b=(int *)malloc(sizeof(int));for(i=0;i<n;i++){a[i]=i+1;}a[n]=-1;for(i=0;j!=n;i++){if(a[i]==-1)i=0;if(a[i]!=0 && a[i]!=-1)s++;if(s==m){b[j]=a[i];a[i]=0;j++;s=0;}}for(i=0;i<n;i++){printf("%5d",b[i]);}printf("\n");l=b[n-1];return l;}第二种方法:只要求出最后出列的那个人的位置即可这种方法利用了约瑟夫环的公式,用到了递归,相对简单。
代码如下,#include<stdio.h>void main(){int y(int n,int m);int a,b,c;scanf("%d%d",&a,&b);c=y(a,b);printf("最后一个数为:%d\n",c);}int y(int n,int m){int x;if(n==1)x=1;else{x=(y(n-1,m)+m)%n;if(x==0) x=n;}return x;}链表#include <stdio.h>#include <stdlib.h>/*定义链表节点类型*/typedef struct node{int data;struct node *next;}LinkList;int main(int argc, char *argv[]){int n,m,k,i;LinkList *head,*back,*front,*temp; head = back = front =NULL;printf("请输入猴子的个数:\n");scanf("%d",&n);printf("请输入从第几个猴子开始:\n"); scanf("%d",&k);printf("请输入喊到几的猴子跳出:\n"); scanf("%d",&m);/*创建循环链表*/for(i = 1;i<n+1;i++){temp = (LinkList *)malloc(sizeof(LinkList)); temp->data = i;if(i==1){head = temp;temp->next = head;back = temp;}else{back->next = temp;temp->next = head;back = temp;}}/*查到编号为k的猴子*/temp = head;for(i = 1;i<k;i++){temp = temp->next;}/* 猴子的总数量*/int total = n;printf("猴子的总数量是:%d\n",n);/*只剩一个节点时停止跳出*/front = head;while(total!=1){/*找到报数为m的猴子*/for( i = 1;i<m;i++){temp = temp->next;}/* 找到报数为m的猴子的前一只猴子*/ while(front->next != temp){front = front->next;}/* 打印猴子报数为m的编号*/printf("%d\n",temp->data);/* 连接m前后两只猴子*/front->next = temp->next;/* 删除报数为m的猴子*/free(temp);total--;temp = front->next;}printf("猴子王的编号为:%d\n",front->data);return 0;}。
约瑟夫环C 代码及实验报告
{
outArray[k]=listArray[j];// 将 该 元 素 放 置 到 出 列 数 组
里,并输出
cout<<outArray[k]<<" ";
k++;
listArray[j]=0; //将出列元素置 0
i=1; //下一个元素从 1 开始重新报数
}
else
i++; //报数编号与出列编号不同时,继续报数
if(a[i]==1) {
j=j+a[i]; if(j==m) {
j=0; a[i]=0; k++; cout<<i<<" "; }
} if(i==n)
i=0; }
}
七、实验心得 李孟琪:该实验利用数组实现线性表,算法简便,但产生很多不必要的消耗,下 一步可以尝试采用单链表,双链表实现该问题。 李春阳:通过利用链表编写约瑟夫环,进一步掌握了约瑟夫环的原理,加深了对 链表使用的理解 雷鹤:这次实验遇到的最大问题是拘泥于基本要求中的利用数组来实现线性表, 并用线性表来实现约瑟夫环问题,在尝试用链表实现后问题变得简单了些;在插 入元素这一步费不少时间,头尾节点的移动关系也需要理解
四、详细设计
程序代码:
#include <iostream>
using namespace std;
main()
{
int n,m,k,j;
//n 为总人数,m 为出列编号
cin>>n>>m;
int *listArray=new int[n]; //将 n 个人放在大小为 n 的数组中
C语言的循环链表和约瑟夫环
C语言的循环链表和约瑟夫环C语言的循环链表和约瑟夫环约瑟夫问题)是一个数学的应用问题,对于学习C语言四非常挺有帮助的,下面是店铺为大家搜集整理出来的有关于C语言的循环链表和约瑟夫环,一起了解下吧!循环链表的实现单链表只有向后结点,当单链表的尾链表不指向NULL,而是指向头结点时候,形成了一个环,成为单循环链表,简称循环链表。
当它是空表,向后结点就只想了自己,这也是它与单链表的主要差异,判断node->next是否等于head。
代码实现分为四部分:1. 初始化2. 插入3. 删除4. 定位寻找代码实现:1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1void ListInit(Node *pNode){int item;Node *temp,*target;cout<<"输入0完成初始化"<<endl; cin="">>item;if(!item)return ;if(!(pNode)){ //当空表的时候,head==NULLpNode = new Node ;if(!(pNode))exit(0);//未成功申请pNode->data = item;pNode->next = pNode;}else{//for(target = pNode;target->next!=pNode;target = target->next);4 15 16 17 18 19 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3temp = new Node;if(!(temp))exit(0);temp->data = item;temp->next = pNode;target->next = temp;}}}void ListInsert(Node *pNode,int i){ //参数是首节点和插入位置Node *temp;Node *target;int item;cout<<"输入您要插入的值:"<<endl; cin="">>item;if(i==1){temp = new Node;if(!temp)exit(0);temp->data = item;for(target=pNode;target->next != pNode;target = target->next);temp->next = pNode;target->next = temp;pNode = temp;}else{target = pNode;for (int j=1;j<i-1;++j) target="target-">next;temp = new Node;if(!temp)exit(0);temp->data = item;temp->next = target->next;target->next = temp;}}void ListDelete(Node *pNode,int i){Node *target,*temp;if(i==1){for(target=pNode;target->next!=pNode;target=target ->next);temp = pNode;//保存一下要删除的首节点 ,一会便于释放6 37 38 39 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5pNode = pNode->next;target->next = pNode;temp;}else{target = pNode;for(int j=1;j<i-1;++j) target="target-">next;temp = target->next;//要释放的nodetarget->next = target->next->next;temp;}}int ListSearch(Node *pNode,int elem){ //查询并返回结点所在的位置Node *target;int i=1;for(target = pNode;target->data!=elem && target->next!= pNode;++i)target = target->next;if(target->next == pNode && target->data!=elem)return 0;else return i;}</i-1;++j)></i-1;++j)></endl;></endl;>5 96 0 6 1 6 2 6 3 6 4 6 5 6 6 67 68 69 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8约瑟夫问题约瑟夫环(约瑟夫问题)是一个数学的'应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。
约瑟夫问题详解(C C++)
如何知道(n-1)个人报数的问题的解?显然,只要知道(n-2)个人的解就行了。(n-2)个人的解 呢?当然是先求(n-3)的情况 ---- 这显然就是一个倒推问题!
递推公式: 令 f[i]表示 i 个人玩游戏报 m 退出最后胜利者的编号,最后的结果自然是 f[n]
递推公式 f[1]=0; f[i]=(f[i-1]+m)%i;
int v; //value,查找的值 int cnt; //count,查找的次数 }hash[HASHLEN]; int addorfind(int v,int cnt) { int t=v%HASHLEN; while(hash[t].v!=-1 && hash[t].v!=v) {
t++; if(t>=HASHLEN)
t=a[i]; a[i]=a[j-1-i]; a[j-1-i]=t; }
t=a[0]; for(i=1;i<j;++i)
a[i-1]=a[i]; a[j-1]=t; t=a[0]; for(i=1;i<j;++i)
t=t*2+a[i]; cout<<t<<endl;
} return 0; }
2244 Eeny Meeny Moo N 个城市轮流断电,求最小的 M 使胜者为城市 2。从城市 1 开始断,相当于循环 N-1 次。
{ long long sk,ssk,i,s,e,tmp,ans;
sk = sqrt((double)K); ssk = K / sk;
for (i = 1, ans = 0; i <= N && i <= ssk; i++) {
约瑟夫环问题的两种解法(详解)
约瑟夫环问题的两种解法(详解)约瑟夫环问题的两种解法(详解)题⽬:Josephus有过的故事:39 个犹太⼈与Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被敌⼈抓。
于是决定了⾃杀⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀。
然后下⼀个重新报数,直到所有⼈都⾃杀⾝亡为⽌。
然⽽Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在第16个与第31个位置,于是逃过了这场死亡游戏。
对于这个题⽬⼤概两种解法:⼀、使⽤循环链表模拟全过程⼆、公式法我们假设这41个⼈编号是从0开始,从1开始报数,第3个⼈⾃杀。
1、最开始我们有这么多⼈:[ 0 1 2 3 4 5 ... 37 38 39 40 ]2、第⼀次⾃杀,则是(3-1)%41=2 这个⼈⾃杀,则剩下:[ 0 1 3 4 5 ... 37 38 39 40 ]3、然后就是从编号为3%41=3的⼈开始从1报数,那么3号就相当于头,既然是头为什么不把它置为0,这样从它开始就⼜是与第1,2步⼀样的步骤了,只是⼈数少了⼀个,这样不就是递归了就可以得到递归公式。
想法有了就开始做:4、把第2步中剩下的⼈编号减去3映射为:[ -3 -2 0 1 2 ... 34 35 36 37 ]5、出现负数了,这样不利于我们计算,既然是环形,37后⾯报数的应该是-3,-2,那么把他们加上⼀个总数(相当于加上360度,得到的还是它)[ 38 39 0 1 2 3 ... 34 35 36 37 ]6、这样就是⼀个总数为40个⼈,报数到3杀⼀个⼈的游戏。
这次⾃杀的是第5步中的(3-1)%40=2号,但是我们想要的是第2步中的编号(也就是最初的编号)那最初的是多少?对应回去是5;这个5是如何得到的呢?是(2+3)%41得到的。
⼤家可以把第5步中所有元素对应到第2步都是正确的。
7、接下来是[ 35 36 37 38 0 1 2... 31 32 33 34 ]⾃杀的是(3-1)%39=2,先对应到第5步中是(2+3)%40=5,对应到第2步是(5+3)%41=8。
C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析
C 语⾔数组实现约瑟夫环问题,以及对其进⾏时间复杂度分析尝试表达本⼈试着去表达约瑟夫环问题:⼀群⼈围成⼀个圈,作这样的⼀个游戏,选定⼀个⼈作起点以及数数的⽅向,这个⼈先数1,到下⼀个⼈数2,直到数到游戏规则约定那个数的⼈,⽐如是3,数到3的那个⼈就离开这个游戏;按这样的规则,剩下⼀个⼈,游戏就结束,这个⼈就为赢家。
(读者可以试着表达,不认同,直接忽略)抽象分析这个⼈就是⼀个数据个体,数据结点,数据元素。
上⾯产⽣的数据结构为:单⽅向循环的链。
可以⽤链表实现,也可以⽤数组来实现。
链表到数组的迁移⼈(数据元素、数据结点、数据个体)结点关系(结构关系结点移动)范型“指针”定义:能够定位到下⼀个结点(变)“指针“移到下⼀个结点拿到下⼀个结点的”指针“即可,⼀般都有作“移动”变量,移动变量变,就相当于移动。
删除结点数组连续的数组元素(基本数据类型,机构体)数组元素⾥⾯保存有下个结点元素的数组元素下标position 。
arrayname 固定的,只要给出position ,就可以算是定位到数组元素≈poisiton []move =array[move]元素内容 = -1(数组的⼤⼩固定)链表离散的链表结点(结构体)结构体⾥⾯保存有下⼀个结点的指针node* nextpoiter 直接定位到结点,在结合常员变量,就可以拿到数据=poiter ->move = move ->next销毁画图分析:代码实现:#include<stdio.h>#include<stdlib.h>/*Function:遍历数组实现的约瑟夫环。
traverse_joseph_circle_array*param:int[] array,int tail*return: void* 假设是⽤数组实现的约瑟夫环链⼀定存在。
* */void traverse_joseph_circle_array (int array[], int tail ){//数组保存的是下个结点的“指针”,只不过这个指针要通过array 才能够拿到结点的元素,因为array 是固定的,只要变换指针就能够变换结点。
约瑟夫(Josephu)环C++课程设计数据结构汇编
前言
塔里木大学信息工程学院课程设计
1.1 背景和意义
数据是计算机化的信息,它是计算机可以直接处理的最基本和最重要的对象。无论是进 行科学计算或数据处理、过程控制以及对文件的存储和检索及数据库技术应用等,都是对数 据进行加工处理的过程。
因此,要设计出一个结构好效率高的程序,必须研究数据的特性及数据间的相互关系及 其对应的存储表示,并利用这些特性结合相关编程技术,运用合适、熟练的方法,才能设计 出符合要求、可操作性强、有利用价值的应用程序。
}
(3).删除操作
同插入操作一样删除操作也是利用的以前对链表的操作加以简单改编而成,在本程序中
(1).构造 Josephu 链表:
由于是应用了类的结构,在 main()函数又有选择语句,直接构造回产生错误所以我在
构 造 最 初 的 Josephu 链 表 时 运 用 了 两 个 函 数 JosephuLink() 函 数 和 putin() 函 数 。
JosephuLink()函数能构造一个空链表而 putin()函数则往其中放入初始值。
从上述分析可见,在 C++中不能用动态分配的一维数组来实现循环队列。如果用户的应 用程序中设有循环队列,则必须为它设定一个最大队列长度;若用户无法预估所用队列的最 大长度,则宜采用链队列。
2.3.2 设计程序
编写本实验设计程序采用 C 语言和 C++想结合的方法,在允许中文环境下运行。本设计
程序下:
约瑟夫(Josephu)问题:已知 N 个人围坐在一张圆桌周围(不妨以 1,2,……,N 对 每一个人依次编号),现在先从序号为 K 的人开始报数,数到 m 的那个人出列,他的下一个 人又从 1 开始数,报数到 m 的人出列……直到所有人都出列为止。
C语言程序设计漫谈之从“约瑟夫问题”谈起
从“约瑟夫问题”谈起约瑟夫问题是一个出现在计算机科学和数学中的问题。
在计算机编程的算法中,类似问题又称为约瑟夫环。
据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
然而Josephus 和他的朋友并不想自杀。
为避免与其他39个决定自杀的犹太人发生冲突,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行,直到仅余15个人为止。
问怎样的排法,才能使每次投入大海的都是非教徒。
【例1】约瑟夫问题。
N个人围成一圈,从某个人开始,按顺时针方向从1开始依次编号。
从编号为1的人开始顺时针“1,2,…M”报数,报到M的人退出圈子。
这样不断循环下去,圈子里的人将不断减少。
由于人的个数是有限的,因此最终会剩下一个人,该人就是优胜者。
输入N和M,输出出圈顺序。
例如,N=6、M=5,出圈的顺序是:5,4,6,2,3,1。
(1)编程思路。
为输出出圈顺序,采用一个数组来进行模拟。
定义int circle[N+1],并按circle[i]=i+1的方式赋予各元素初值。
该值代表两个含义:1)值为0,代表编号i+1的人不再圈中;2)值非0,代表圈中第i个位置的人编号为i+1。
定义变量i代表报数位置的流动,i的初值为0,代表编号为1的人的位置,i的变化方式为:i=(i+1)%(n),即0-->1-->2……->n-1 ->0-->1……。
约瑟夫环说明书
/*Hash链表的删除*/
struct node /*定义线性单链表结点类型*/
{int d; /*定义线性单链表结点数据类型*/
struct node *next;/*结点指针*/
};
#include"stdlib.h"
whasht(h,k,f) /*Hash表的填入*/
int(*f)(); /*Hash码函数*/
关键词:单循环链表;c语言;约瑟夫环;
前
数据结构是研究数据元素之间的逻辑关系的一门课程,以及数据元素及其关系在计算机中的存储表示和对这些数据所施加的运算。该课程设计的目的是通过课程设计的综合训练,培养分析和编程等实际动手能力,系统掌握数据结构这门课程的主要内容。
本次课程设计的内容是用单循环链表模拟约瑟夫环问题,循环链表是一种首尾相接链表,其特点是无须增加存储容量,仅对表的链接方式稍作改变,使表处理更加灵活,约瑟夫环问题就是用单循环链表处理的一个实际应用。通过这个设计实例,了解单链表和单循环链表的相同与不同之处,进一步加深对链表结构类型及链表操作的理解。
return;
}
#include"stdio.h"
whashs(h,k,f)/*Hash表的删除*/
int (*f)(); /*Hash码函数*/
int k; /*关键字*/
struct node *h[]; /*外链Hash表的顺序存储空间*/
{int i,flag;
struct node *p,*q,*s;
int k;
struct node *h[]; /*外链Hash表的Hash表顺序存储空间*/
{int i;
struct node *p;
约瑟夫环c语言代码指针函数,JavaScript使用指针操作实现约瑟夫问题实例
约瑟夫环c语⾔代码指针函数,JavaScript使⽤指针操作实现约瑟夫问题实例本⽂实例讲述了JavaScript使⽤指针操作实现约瑟夫问题的⽅法。
分享给⼤家供⼤家参考。
具体分析如下:实现之前当然要⾃⼰来编写⼀些 JS 数组内部指针的操作函数,就像:reset(), current(), next(), prev(), search(), end() 这些函数,我们都要来⾃⼰实现,因为 JS 没有内置这些神奇的操作函数Array.prototype.pointer = 0;//模拟数组内部指针//Reset 函数,将数组内部指针归位(指向第⼀个元素)var reset = function(arrayObj){if(!(arrayObj instanceof Array)){alert("Reset() 函数参数类型错误!请检查输⼊!");return;}arrayObj.pointer = 0;}//Current 函数,返回数组内部指针指向的当前元素var current = function(arrayObj){if(!(arrayObj instanceof Array)){alert("Current() 函数参数类型错误!请检查输⼊!");return;}return arrayObj[arrayObj.pointer];}//End 函数,将数组内部指针指向最后⼀个元素var end = function(arrayObj){if(!(arrayObj instanceof Array)){alert("End() 函数参数类型错误!请检查输⼊!");return;}arrayObj.pointer = arrayObj.length - 1;return arrayObj[arrayObj.pointer];}//Next 函数,将数组内部指针下移⼀位//如果已经指向最后⼀个元素则返回 FALSEvar next = function(arrayObj){if(!(arrayObj instanceof Array)){alert("Next() 函数参数类型错误!请检查输⼊!"); return;}arrayObj.pointer ++;if(typeof arrayObj[arrayObj.pointer] == 'undefined'){ arrayObj.pointer --;return false;}return true;}//Prev 函数,将数组内部指针上移⼀位//如果已经指向第⼀个元素则返回 FALSEvar prev = function(arrayObj){if(!(arrayObj instanceof Array)){alert("Prev() 函数参数类型错误!请检查输⼊!"); return;}arrayObj.pointer --;if(typeof arrayObj[arrayObj.pointer] == 'undefined'){ arrayObj.pointer ++;return false;}return arrayObj[arrayObj.pointer];}//Unset 函数,删除指定的数组元素var unset = function(index, arrayObj){if(!(arrayObj instanceof Array)){alert("Unset() 函数参数类型错误!请检查输⼊!"); return;}if(typeof arrayObj[index] == 'undefined'){alert("Unset() 函数参数 index 错误!不存在此元素!"); return false;}arrayObj.splice(index, 1);return true;}//Search 函数,通过数组键值返回数组的键名var search = function(value, arrayObj){if(!(arrayObj instanceof Array)){alert("Search() 函数参数类型错误!请检查输⼊!");return;}for(index in arrayObj){if(arrayObj[index] == value){return index;}}return false;}//getKingMonkey 函数,我们的约瑟夫主函数,n 只猴⼦,数到 m function getKingMonkey(n, m){a = new Array();for(i = 1; i <= n; i ++){a[i] = i;}a[0] = 0;unset(0, a);reset(a);while(a.length > 1){for(counter = 1; counter <= m; counter ++){if(next(a)){if(counter == m){unset(search(prev(a), a), a);}}else{reset(a);if(counter == m){unset(search(end(a), a), a);reset(a);}}}}return current(a);}alert("猴⼦⼤王的编号为:" + getKingMonkey(100, 17));希望本⽂所述对⼤家的javascript程序设计有所帮助。
约 瑟 夫 环 问 题 的 三 种 解 法
约瑟夫问题(数学解法及数组模拟)约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。
在计算机编程的算法中,类似问题又称为约瑟夫环。
又称“丢手绢问题”.)据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
然而Josephus 和他的朋友并不想遵从。
首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。
接着,再越过k-1个人,并杀掉第k个人。
这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。
问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
? 以上来自百度百科约瑟夫问题是个很有名的问题:N个人围成一个圈,从第一个人开始报数,第M个人会被杀掉,最后一个人则为幸存者,其余人都将被杀掉。
例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。
约瑟夫问题其实并不难,但求解的方法多种多样;题目的变化形式也很多。
接下来我们来对约瑟夫问题进行讨论。
1.模拟解法优点 : 思维简单。
?缺点:时间复杂度高达O(m*n)当n和m的值较大时,无法短时间内得到答案。
为了叙述的方便我们将n个人编号为:1- n ,用一个数组vis 来标记是否存活:1表示死亡 0表示存活 s代表当前死亡的人数? cnt 代表当前报了数的人数用t来枚举每一个位置(当tn时 t=1将人首尾相连)? 那么我们不难得出核心代码如下:bool vis[1000]; --标记当前位置的人的存活状态int t = 0; --模拟位置int s = 0; --死亡人数int cnt = 0; --计数器if(t n) t = 1;if(!vis[t]) cnt++; --如果这里有人,计数器+1if(cnt == m) --如果此时已经等于m,这这个人死去cnt = 0; --计数器清零s++; --死亡人数+1vis[t] = 1 --标记这个位置的人已经死去coutt" "; --输出这个位置的编号}while(s != n);接下来我们来看另一种更为高效快速的解法数学解法我们将这n个人按顺时针编号为0~n-1,则每次报数到m-1的人死去,剩下的人又继续从0开始报数,不断重复,求最后幸存的人最初的编号是多少?我们只需要将最后求得的解加1就能得到原来的编号。
约瑟夫环的简单实现(C++链表)
约瑟夫环的简单实现(C++链表)约瑟夫环(Joseph Circle) 编号为1,2,...,n的n个⼈按顺时针⽅向围坐⼀圈,每⼈持有⼀个密码(正整数)。
现在给定⼀个随机数m>0,从编号为1的⼈开始,按顺时针⽅向1开始顺序报数,报到m时暂停。
报m的⼈出圈,同时留下他的密码作为新的m值,从他在顺时针⽅向上的下⼀个⼈开始,重新从1开始报数,如此下去,直⾄所有的⼈全部出列为⽌。
对应的密码为顺序为:4 8 9 15 22 1 31 #include <iostream>2using namespace std;34 typedef struct Node5 {6int e;7struct Node* next;8 }Node, *Linklist;9//Linklist ⼀个节点的指针10void initlist(Linklist &head)11 {12int n;13 Linklist head_ptr,tail_ptr,temp;14 head = (Linklist)malloc(sizeof(Node));15 head->next = nullptr;16 head_ptr = head;17 tail_ptr = head;18 cout << "输⼊需要节点个数:";19 cin >> n;20for (int i = 0; i < n; i++)21 {22 temp= (Linklist)malloc(sizeof(Node));23 temp->next = nullptr;24 tail_ptr->next= temp ;25 cout << "第" << i + 1 << "个节点:";26 cin >> temp->e;27 tail_ptr=tail_ptr->next ;28 }2930 }3132void show(Linklist list)33 {34 Linklist p = list;35 p = p->next;36while (p != nullptr)37 {38 cout << p->e << endl;39 p = p->next;40 }41 }4243void remove(Linklist list)44 {45int n;46 printf("输⼊需要删除的节点:");47 cin >> n;48 Linklist p=list;49while (p->next->e != n)50 {51 p = p->next;52 }53 Linklist t = p->next;54 p->next = p->next->next;55free(t);56 printf("删除结果:\n");57 show(list);5859 }6061void insert(Linklist& list) {62int n,i=0;63 Linklist t = (Linklist)malloc(sizeof(Node));64 Linklist p = list;65 printf("输⼊插⼊的节点元素:");66 cin >> t->e ;67 printf("输⼊插⼊的位置:");68 cin >> n;69 p = p->next;70while (1)71 {72if (i == n - 1)73 {74break;75 }76 p = p->next;77 i++;78 }79 t->next = p->next;80 p->next = t;81 printf("插⼊结果:\n");82 show(list);8384 }8586void JosehpInit(Linklist list) //⽤来构建⼀个循环链表,假设每个节点的e就是该节点的密码,头节点也存放⼀个密码87 {88 Linklist p; //list就是该链表的头节点的地址89 list->e = 3; //假设头节点作为⼀号节点,约瑟夫环开始的第1个节点,并将它的密码设置成3,循环列表的输⼊从第⼆号节点开始,⼀号是头节点,写在程序中90 p = list;91while (p->next != nullptr) { p = p->next; }92 p->next = list;//list为头节点,将头节点和尾结点连起来9394 }9596void JosehpImpl(Linklist list)97 {98 Linklist p = list,t=nullptr;99int m=4; //假设初始的密码是5,这⾥要定义成4(密码-1)100while (p->next!=p)101 {102 p = p->next;103 m--;104if (m == 1)//此时p指针的下⼀个⼈就是将要出去的⼈105 {106 t = p->next; //⼀定要注意先后顺序在这卡了半天看不出⽑病107108 m = p->next->e; //先将key替换为将要出去的⼈的密码109 cout << p->next->e << endl;110 p->next = p->next->next;111free(t);112 }113114 }115 cout << p->e;116 }117118int main()119 {120 Linklist list;121 initlist(list);122 JosehpInit(list);123 JosehpImpl(list);124return0;125 }。
约瑟夫环的C语言数组的实现
if(8l=。o)8l=i;产如果汁算之后的sl的值为0,则说明当前该人 出圈+,
w=p[sl一11;严把B1人的信息存入W变量中吖 for(j=s1;j<=i-l;j++)p[j-1]=p[j];,.把sl以后的所有人向前平移 一个位置吖 p[i—iN-w;p把w中8l的信息存入有i个数的敷组P中吖 l
作者简介:羽文锋(1978一),男,山东邦城人,助教。项士研览生,研究方向为 软件工程、程序设计.同络工程。
【责任编辑:王尊】
74
万方数据
约瑟夫环的C语言数组的实现
作者: 作者单位: 刊名:
英文刊名: 年,卷(期): 被引用次数:
刘文锋 菏泽学院计算机与信息工程系,山东,菏泽,274015
科技信息 SCIENCE & TECHNOLOGY INFORMATION 2010,""(21) 0次
科技信约瑟夫环的c语言数组的实现刘文锋菏泽学院计算机与信息工程系山东菏泽274015摘要本文给出了使用c语言教组解决约瑟走环的一种方法
2010年第2l期
OIT论坛。
科技信■
约瑟夫环的C语言数组的实现
刘文锋 (菏泽学院计算机与信息工程系 山东菏泽274015)
【摘要】本文给出了使用C语言教组解决约瑟走环的一种方法,.并得倒了预期的结果。 【关键词】约瑟夫环;数组;c语言
sl=s;//从第s个人开始报数 for(i=1;i<=100;i++)p[i-1]=i;,.把100个人的信息存人数组P