约瑟夫环的循环链表实现

合集下载

C语言用循环单链表实现约瑟夫环

C语言用循环单链表实现约瑟夫环

C语⾔⽤循环单链表实现约瑟夫环⽤循环单链表实现约瑟夫环(c语⾔),供⼤家参考,具体内容如下源代码如下,采⽤Dev编译通过,成功运⾏,默认数到三出局。

主函数:main.c⽂件#include <stdio.h>#include "head.h"#include "1.h"int main(){Linklist L;int n;printf("请输⼊约瑟夫环中的⼈数:");scanf("%d",&n);Createlist(L,n);printf("创建的约瑟夫环为:\n");Listtrave(L,n);printf("依次出局的结果为:\n");Solution(L,n);return 0;}head.h⽂件:#include "1.h"#include <stdio.h>#include <stdlib.h>typedef int Elemtype;typedef struct LNode{Elemtype data;struct LNode *next;}LNode,*Linklist;void Createlist(Linklist &L,int n){Linklist p,tail;L = (Linklist)malloc(sizeof(LNode));L->next = L;//先使其循环p = L;p->data = 1;//创建⾸节点之后就先给⾸节点赋值,使得后⾯节点赋值的操作能够循环tail = L;for(int i = 2;i <= n;i++){p = (Linklist)malloc(sizeof(LNode));p->data = i;p->next = L;tail->next = p;tail = p;}printf("已⽣成⼀个长度为%d的约瑟夫环!\n",n);}void Listtrave(Linklist L,int n)//遍历函数{Linklist p;p = L;for(int i = 1;i <= n;i++){printf("%3d",p->data);p = p->next;}printf("\n");}int Solution(Linklist L,int n){Linklist p,s;p = L,s = L;int count = 1;while(L){if(count != 3){count++;p = p->next;//进⾏不等于3时的移位}else{Linklist q;q = p;//⽤q保存p所指的位置,⽅便进⾏节点的删除if(s->next->data == s->data)//当只有⼀个元素的时候{printf("%3d\n",s->data);free(s);return OK;}else//当有两个及两个以上的元素的时候{count = 1;//先将count重置为1printf("%3d",p->data);//再打印出出局的值while(s->next != p){s = s->next;//将s移位到p的前驱节点处}p = p->next;//使p指向⾃⼰的下⼀个节点s->next = p;//进⾏删除free(q);}}}}1.h⽂件:#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2运⾏结果:以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

约瑟夫生死游戏(C++)数据结构实现

约瑟夫生死游戏(C++)数据结构实现

一:【内容与要求】约瑟夫游戏的大意是:每30 个旅客同乘一条船,因为严重超载,加之风高浪大,危(wei)险万分;因此船长告诉乘客,惟独将全船一半的旅客投入还中,其余人材干避免遇难。

无奈,大家只得允许这种办法,并议定30 个人围成一圈,由第一个人数起,挨次报数,数到第9人,便把他投入大海中,然后再从他的下一个人数起,数到第9 人,再将他扔进大海中,如此循环地进行,直到剩下15 个乘客为止。

问哪些位置是将被扔下大海的位置。

二:概要设计利用链表循环来解决。

首先,就必须先定义一个链表,按照所需要的长度进行定义,然后令其为指针指向头指针,即完成为了一个循环链表的创建。

接下来先打印链表输出。

其次,就是算法实现,需要利用指针来进行,数据域标记人员编号,先用一个指针循环查找,找到第一个需要删除的人,标记为1,先输出节点数,再进行删除。

挨次循环查找,直到被删除的节点数量为总人数的一半的时候则结束。

三:程序执行流程图否三:详细代码结构1. 链表的创建(1) 创建头节点Josephring(){head=new Node;//为头结点申请空间head->no=1;//为数据域赋值head->next=head;//形成循环链表}(2) 循环插入链表void Josephring::CreateJosephus(int n){Node*s=head;//标记头结点totalnum=n;for(int i=2;i<=n;i++){ Node*w=new Node;//新建一个节点w->no=i;w->next=head;s->next=w;s=w;//S 作为尾指针}}首先申请一个节点,并且W 指针指向它,然后从2 开始赋值,此时先令新节点的W 指针指向头结点,再令S 指针指向它,挨次循环插入创建。

2. 打印输出链表void Josephring::show(){cout<<head->no<<"\t";//先输出头节点Node*q=head->next;while(q!=head){cout<<q->no<<"\t";q=q->next;}}先打印输出头结点,然后循环判定,将不等于头结点的全部输出。

C++单链表实现约瑟夫环

C++单链表实现约瑟夫环

#include <iostream.h>#include <stdlib.h>struct Member//定义结构体{int number;int password;Member *next;};class Joseph{public:Member *frist;//头指针int size;Joseph(void);~Joseph(void);int Size(void) const;//返回长度Member *Index(int i);//定位void Create(int i);//构造循环单链表int Delete(int i);//删除结点并返回number的值};Joseph::Joseph(){//frist=new Member;Member *p=new Member;frist=p;size=0;}Member *Joseph::Index(int i){if(i==0)return frist;Member *p=frist->next;int j=1;while(j<i){p=p->next;j++;}return p;}int Joseph::Size(void)const{return size;}void Joseph::Create(int i){for(int j=1;j<=i;j++){Member *p=Index(j-1);Member *q=new Member;q->number=j;p->next=q;size++;};//Member *p=Index(i);//p->next=frist;}Joseph::~Joseph(void){Member *p,*q;p=frist;while(size!=0){q=p;p=p->next;delete q;size--;}size=0;frist=NULL;}int Joseph::Delete(int i){Member *s,*p=Index(i-1);s=p->next;p->next=p->next->next;int x=s->number;cout<<x<<" ";int y=s->password;delete s;size--;return y;}void main(void){Joseph jos;int i;cout<<"Please input number of people :"<<endl;cin>>i;jos.Create(i);int frist;//设初始值cout<<"Please input the frist number :"<<endl;cin>>frist;for(int k=1;k<=i;k++)//用循环输入每个人的密码{cout<<"please input No."<<k<<"`s password:"<<endl;Member *b=jos.Index(k);cin>>b->password;}cout<<"The final is :"<<endl;int l=frist%i;if (l==0) l=i;for(int b=i-1;b>0;b--){frist=jos.Delete(l);l=(frist+l-1)%b;int e=jos.Size();if(l==0)l=e;}jos.Delete(l);cout<<endl;}。

约瑟夫环问题实验报告

约瑟夫环问题实验报告

约瑟夫问题实验报告背景约瑟夫问题(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个数输出到屏幕上三.详细设计首先,设计实现约瑟夫环问题的存储结构。

实验报告 约瑟夫问题

实验报告 约瑟夫问题
pNew->next = pCur->next;
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;
}
实验中遇到的问题及解决方法
实验结果如下:
实验总结(结果和心得体会)

C++编写的 约瑟夫环问题 代码

C++编写的 约瑟夫环问题 代码

程序源代码:#include <stdio.h>#include <malloc.h>#include<conio.h>#include <stdlib.h>#include<ctime>#define NULL 0typedef struct Node{int m;//密码int n;//序号struct Node *next;}Node,*Linklist;Linklist create(int z) //生成循环单链表并返回,z为总人数{int i,mm;Linklist H,r,s;H=NULL;printf("请按顺序依次为每个人添加密码:");for(i=1;i<=z;i++){printf("\ninput cipher=");scanf("%d",&mm);s=(Linklist)malloc(sizeof(Node));s->n=i;s->m=mm;printf("%d号的密码%d",i,s->m);if(H==NULL)//从链表的第一个节点插入{H=s;r=H;}else//链表的其余节点插入{r->next=s;r=s;//r后移}//for结束r->next=H;/*生成循环单链表*/return H;}void search(Linklist H,int m0,int z)//用循环链表实现报数问题{int count=1;//count为累计报数人数计数器int num=0;//num为标记出列人数计数器Linklist pre,p;p=H;printf("出列的顺序为:");while(num<z){do{count++;pre=p;p=p->next;}while(count<m0);{pre->next=p->next;printf("%d ",p->n);m0=p->m;free(p);p=pre->next;count=1;num++;}//while结束}void clean(){int system(const char *string);int inquiry;printf("请问需要清除上一次操作记录吗(1.清屏/2.不清屏)...?\n"); scanf("%d",&inquiry);if(inquiry ==1)system("cls");}void text(){int m0,z,i, choose,k=1; //k用来阻止第一次进入程序清屏操作Linklist H;bool chooseFlag=false;while(1){if(k!=1)clean();k++;while(!chooseFlag){printf(" ……………………欢迎进入约瑟夫环问题系统…………………… \n"); printf( "* 1.输入约瑟夫环数据 * \n"); printf(" * 2.什么是约瑟夫环 * \n"); printf(" * 3.退出系统 * \n"); printf("........................................................ \n"); printf("请输入相应的数字进行选择: ");scanf("%d",&choose);for(i=1;i<=4;i++){if(choose==i) { chooseFlag=true; break;}else chooseFlag=false;}if(!chooseFlag) printf("Error Input!\n");} //end while(!chooseFlag)if(choose==1) //if 开始{printf("Input how many people in it:");//z为总人数scanf("%d",&z);if(z<=30){H=create(z);//函数调用printf("\nInput the start code m0=");scanf("%d",&m0);search(H,m0,z);printf("\n\n\n");}else{printf("超过最大输入人数\n");break;}}else if(choose==2){printf("\n约瑟夫环问题:设有n个人,其编号分别为1,2,3,…,n,安装编号顺序顺时针围坐一圈。

约瑟夫环问题

约瑟夫环问题

约瑟夫环问题问题描述:有n个⼈,编号分别从0到n-1排列,这n个⼈围成⼀圈,现在从编号为0的⼈开始报数,当报到数字m的⼈,离开圈⼦,然后接着下⼀个⼈从0开始报数,依次类推,问最后只剩下⼀个⼈时,编号是多少?分析:这就是著名的约瑟夫环问题,关于来历不再说明,这⾥直接分析解法。

解法⼀:蛮⼒法。

我曾将在⼤⼀学c语⾔的时候,⽤蛮⼒法实现过,就是采⽤标记变量的⽅法即可。

解法⼀:循环链表法。

从问题的本质⼊⼿,既然是围成⼀个圈,并且要删除节点,显然符合循环链表的数据结构,因此可以采⽤循环链表实现。

解法三:递推法。

这是⼀种创新的解法,采⽤数学建模的⽅法去做。

具体如下:⾸先定义⼀个关于n和m的⽅程f(n,m),表⽰每次在n个编号0,1,...,n-1中每次删除的报数为m后剩下的数字,在这n个数字中,第⼀个被删除的数字是(m-1)%n,为了简单,把(m-1)%n记作k,那么删除k之后剩下的数字为0,1,2,...,k-1,k+1,...,n-1并且下⼀次删除的数字从k+1开始计数,这就相当于剩下的序列中k+1排在最前⾯,进⽽形成k+1,..,n-1,0,1,2,...,k-1这样的序列,这个序列最后剩下的数字应该和原序列相同,由于我们改变了次序,不能简单的记作f(n-1,m),我们可以记作g(n-1,m),那么就会有f(n,m)=g(n-1,m).下⼀步,我们把这n-2个数字的序列k+1,..,n-1,0,1,2,...,k-1做⼀个映射,映射的结果是形成⼀个从0到n-2的序列。

k+1对0,k+2对1,......,n-1对n-k-2,0对n-k-1,1对n-k,....,k-1对n-2这样我们可以把这个映射定义为p,则p(x)=(x-k-1)%n,它表⽰如果映射前的数字是x,映射后为(x-k-1)%n,从⽽这个映射的反映射问为p-1(x)=(x+k+1)%n由于映射之后的序列和原始序列具有相同的形式,都是从0开始的序列,所以可以⽤函数f来表⽰,即为f(n-1,m),根据映射规则有:g(n-1,m)=p-1[f(n-n,m)]=[f(n-1,m)+k+1]%n,最后把之前的k=(m-1)%n带⼊式⼦就会有f(n,m)=g(n-1,m)=[f(n-1,m)+m]%n.这样我们就可以得出⼀个递推公式,当n=1时,f(n,m)=0;当n>1时,f(n,m)=[f(n-1,m)+m]%n;有了这个公式,问题就变得多了。

环表实现约瑟夫环

环表实现约瑟夫环

实验内容与要求采用单向环表实现约瑟夫环。

请按以下要求编程实现:①从键盘输入整数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。

#include <stdio.h>#include <stdlib.h>#include<iostream.h>typedef struct node //定义结点类型{int num; // 用来对每个结点进行编号标序struct node *next; //递归定义}LNode,*Linkls;void create(int m,Linkls &head){Linkls p;head=(LNode*)malloc(sizeof(LNode)); //申请头结点的存储空间head->next=head; //让链表成为一个空的循环链表for(int i=m;i>1;i--){if(!(p=(LNode*)malloc(sizeof(LNode)))) exit(-1); //申请存储空间p->num=i; //标记每个结点的顺序p->next=head->next;head->next=p;}head->num=1;}//Createint main(){int n,i,s,m,j=1;LNode *head,*p,*q;printf("请输入开始的总人数m:\n");scanf("%d",&m);printf("开始计数的位置s:\n");scanf("%d",&s);printf("输入要进行数的数字:\n");scanf("%d",&n);//输入数据create(m,head);//产生一个以head为头结点,有m个元素的循环链表printf("进行依次删除操作:\n");for(i=1,p=head;i<s;i++)p=p->next;while(m--){for(i=1;i<n-1;i++)p=p->next;q=p->next;printf("第%02d次出局的数:%d\n",j++,q->num);//输出数到的数字,后面进行删除p->next=q->next;p=p->next;free(q);//释放q所指的空间}printf("By 北理工电气一班:\n邓南化(20091589)\n");return 0;}。

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

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

约瑟夫环数据结构实验报告约瑟夫环数据结构实验报告引言约瑟夫环是一种经典的数学问题,它涉及到一个有趣的数据结构。

本次实验旨在通过实现约瑟夫环数据结构,深入理解该问题,并探索其在实际应用中的潜力。

本报告将介绍实验的设计和实现过程,并分析实验结果。

实验设计在本次实验中,我们选择使用链表来实现约瑟夫环数据结构。

链表是一种非常灵活的数据结构,适合用于解决约瑟夫环问题。

我们设计了一个Josephus类,其中包含了创建环、添加元素、删除元素等操作。

实验实现1. 创建环在Josephus类中,我们首先需要创建一个循环链表。

我们使用一个头节点来表示环的起始位置。

在创建环的过程中,我们可以选择指定环的长度和起始位置。

2. 添加元素在创建环之后,我们可以通过添加元素来向约瑟夫环中插入数据。

我们可以选择在环的任意位置插入元素,并且可以动态地调整环的长度。

3. 删除元素根据约瑟夫环的规则,每次删除一个元素后,下一个元素将成为新的起始位置。

我们可以通过删除元素的操作来模拟约瑟夫环的运行过程。

在删除元素时,我们需要考虑环的长度和当前位置。

实验结果通过实验,我们得出了以下结论:1. 约瑟夫环数据结构可以有效地模拟约瑟夫环问题。

通过创建环、添加元素和删除元素的操作,我们可以模拟出约瑟夫环的运行过程,并得到最后剩下的元素。

2. 约瑟夫环数据结构具有一定的应用潜力。

除了解决约瑟夫环问题,该数据结构还可以用于其他类似的问题,如任务调度、进程管理等。

3. 约瑟夫环数据结构的时间复杂度较低。

由于约瑟夫环的特殊性质,我们可以通过简单的链表操作来实现该数据结构,使得其时间复杂度较低。

结论本次实验通过实现约瑟夫环数据结构,深入理解了该问题,并探索了其在实际应用中的潜力。

通过创建环、添加元素和删除元素的操作,我们可以模拟出约瑟夫环的运行过程,并得到最后剩下的元素。

约瑟夫环数据结构具有一定的应用潜力,并且具有较低的时间复杂度。

通过本次实验,我们对数据结构的设计和实现有了更深入的理解,并为将来的研究和应用奠定了基础。

C语言的循环链表和约瑟夫环

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分别表示)围坐在一张圆桌周围。

约瑟夫环上机实验报告

约瑟夫环上机实验报告

约瑟夫环上机实验报告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无关。

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

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

数据结构实验报告约瑟夫环约瑟夫环是一个经典的问题,涉及到数据结构中的循环链表。

在本次数据结构实验中,我们将学习如何使用循环链表来解决约瑟夫环问题。

约瑟夫环问题最早出现在古代,传说中的犹太历史学家约瑟夫斯·弗拉维奥(Josephus Flavius)在围攻耶路撒冷时,为了避免被罗马人俘虏,与其他39名犹太人躲进一个洞穴中。

他们决定宁愿自杀,也不愿被敌人俘虏。

于是,他们排成一个圆圈,从第一个人开始,每次数到第七个人,就将他杀死。

最后剩下的人将获得自由。

在这个问题中,我们需要实现一个循环链表,其中每个节点表示一个人。

我们可以使用一个整数来表示每个人的编号。

首先,我们需要创建一个循环链表,并将所有人的编号依次添加到链表中。

接下来,我们需要使用一个循环来模拟每次数到第七个人的过程。

我们可以使用一个指针来指向当前节点,然后将指针移动到下一个节点,直到数到第七个人为止。

一旦数到第七个人,我们就将该节点从链表中删除,并记录下该节点的编号。

然后,我们继续从下一个节点开始数数,直到只剩下一个节点为止。

在实现这个算法时,我们可以使用一个循环链表的数据结构来表示约瑟夫环。

循环链表是一种特殊的链表,其中最后一个节点的指针指向第一个节点。

这样,我们就可以实现循环遍历链表的功能。

在实验中,我们可以使用C语言来实现循环链表和约瑟夫环算法。

首先,我们需要定义一个节点结构体,其中包含一个整数字段用于存储编号,以及一个指针字段用于指向下一个节点。

然后,我们可以实现创建链表、添加节点、删除节点等基本操作。

接下来,我们可以编写一个函数来实现约瑟夫环算法。

该函数接受两个参数,分别是参与游戏的人数和每次数到第几个人。

在函数内部,我们可以创建一个循环链表,并将所有人的编号添加到链表中。

然后,我们可以使用一个循环来模拟每次数到第几个人的过程,直到只剩下一个节点为止。

在每次数到第几个人时,我们可以删除该节点,并记录下其编号。

最后,我们可以返回最后剩下的节点的编号。

约瑟夫环问题的两种解法(详解)

约瑟夫环问题的两种解法(详解)

约瑟夫环问题的两种解法(详解)约瑟夫环问题的两种解法(详解)题⽬: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。

循环队列之约瑟夫环问题

循环队列之约瑟夫环问题

循环队列之约瑟夫环问题约瑟夫问题 约瑟夫环(约瑟夫问题)是⼀个数学的应⽤问题:已知n个⼈(以编号1,2,3...n分别表⽰)围坐在⼀张圆桌周围。

从编号为k的⼈开始报数,数到m的那个⼈出列;他的下⼀个⼈⼜从1开始报数,数到m的那个⼈⼜出列;依此规律重复下去,直到圆桌周围的⼈全部出列。

通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。

循环队列求解(链式)#include<stdio.h>#include<stdlib.h>//循环队列//typedef int ElemType;typedef struct QueueNode{int data;struct QueueNode *next;}QueueNode;typedef struct Queue{QueueNode *front;QueueNode *rear;}Queue;void InitQueue(Queue *q){q->front=q->rear=NULL;}void EnQueue(Queue *q , int value){QueueNode *temp=(QueueNode*)malloc(sizeof(QueueNode));temp->data=value;if(q->rear==NULL){temp->next=temp;q->rear=q->front=temp;}else{temp->next=q->rear->next;q->rear->next=temp;q->rear=temp;}}//enter a element from the tailvoid DeQueue(Queue *q, int *value){QueueNode *temp=(QueueNode*)malloc(sizeof(QueueNode)); if(q->rear==NULL){return;}// It's nullelse if(q->rear->next==q->rear){*value=q->front->data;free(q->rear);q->rear=q->front=NULL;}//It just has one nodeelse{*value=q->front->data;temp=q->front;q->front=temp->next;q->rear->next=q->front;}//more one nodefree(temp);}//delete a element from the headint main(){Queue *q=(Queue*)malloc(sizeof(Queue));int i,m,n,count,temp;printf("请输⼊⼈数n和循环要报的数m(两数之间留个空格)\n"); scanf("%d%d",&n,&m);for(i=1;i<=n;i++)EnQueue(q,i);printf("出圈序列:\n");while(q->front){ count=1;while(count<m){q->front=q->front->next;q->rear=q->rear->next;count++;}count=1;DeQueue(q,&temp);printf("%d ",temp);}putchar('\n');}简单解法#include <stdio.h>int josephus(int n, int m) {if(n == 1) {return0;}else {return (josephus(n-1, m) + m) % n;}}int main() {int n, m;while (scanf("%d", &n) == 1) {if (!n) {break;}scanf("%d", &m);int result = josephus(n, m);printf("%d\n", result+1);}return0;}。

数据结构——约瑟夫环

数据结构——约瑟夫环

数据结构——约瑟夫环今⽇⼀⾔:谢谢你,成为我前进的理由。

——《⾔叶之庭》数据结构 —— 约瑟夫环这是⽤链表实现的,约瑟夫环的规则是:总数为N的同学围成⼀个圆环,并将这些同学从1开始编号,游戏开始时,约定好⼀个数字K,从1号同学开始轮着叫号,当叫到K号时,该同学淘汰,下⼀位同学从1开始重新叫号,只要叫到K号即淘汰,留下来的最后⼀位同学赢得游戏。

C语⾔实现/*********************************************************************************** 约瑟夫环* create: 2020年5⽉24⽇ 22点22分* author: LOS(⼩鱼)** *******************************************************************************/#include<stdio.h>#include<stdlib.h>/********************************************************************************** 链表需要********************************************************************************/typedef struct Elem{int value;struct Elem *prev,*next;}Elem;struct{Elem elems[200];int size;} Elems; // 全部的链表数据存储在这⾥(不销毁, 但会覆盖)// 定义链表结构typedef struct {struct Elem *first;struct Elem *last;int size;} LinkList;// 初始化链表void initLinkList( LinkList *list ){list->size = 0;}// 获取表长int getSizeL(LinkList *list){return list->size;}void addFirst(LinkList *list,Elem *elem){if( !getSizeL(list) ){list->first = elem;list->last = elem;}else {elem->next = list->first;list->last->next = elem;list->first->prev = elem;list->first = elem;}list->size++;}// 添加元素void addLast(LinkList *list,Elem *elem){if( !getSizeL(list) ){list->first = elem;list->last = elem;} else {elem->prev = list->last;elem->next = list->first;list->last->next = elem;list->first->prev = elem;list->last = elem;}list->size++;}Elem * getElem(LinkList *list, int index){int i ;Elem *elem;// 逐项访问if ( index > list->size/2 ){elem = list->last;for ( i = list->size-1 ; i >= index ; i-- ){if( i == index ){return elem;}elem = elem->prev;}} else {elem = list->first;for ( i = 0 ; i <= index ; i++ ){if( i == index ){return elem;}elem = elem->next;}}}// 移除元素void removeIndexL(LinkList *list, int index){ int i;Elem *elem = list->first;int flag = 0;for ( i = 0 ; i <= index ; i++ ){if( i == index ){elem->prev->next = elem->next;elem->next->prev = elem->prev;if( list->first == elem ){list->first = elem->next;}if( list->last == elem ){list->last = elem->prev;}flag = 1;}elem = elem->next;}if(!flag) printf("没能完成任务\n"); list->size--;}void removeElemL(LinkList *list, Elem *e){ int i;Elem *elem = list->first;int flag = 0;for ( i = 0 ; i < list->size ; i++ ){if( elem == e ){elem->prev->next = elem->next;elem->next->prev = elem->prev;list->first = elem->next;}if( list->last == elem ){list->last = elem->prev;}flag = 1;}elem = elem->next;}if(!flag) printf("没能完成任务\n");list->size--;}/********************************************************************************** 链表需要********************************************************************************/Elem *createElem( int value ){Elem *p = Elems.elems+Elems.size;p->value = value;Elems.size++;if( Elems.size == 200 ) Elems.size = 0; // 注意不能超过200,否则数据错误return p;}void main(){LinkList list;int n,k,i,count;printf("请输⼊参与游戏的总⼈数:");scanf("%d",&n);fflush(stdin);printf("请输⼊淘汰的间隔数:");scanf("%d",&k);fflush(stdin);initLinkList(&list);for ( i = 0 ; i < n ; i++ ){Elem *elem = createElem(i+1);addLast(&list,elem);}printf("游戏开始......\n");count = 0;while(list.size>1){count = (count+k-1)%list.size;printf("%d号同学被淘汰.\n",getElem(&list,count)->value);removeIndexL(&list,count);}printf("最后的赢家是 --> %d号同学!\n",st->value);}运⾏结果请输⼊参与游戏的总⼈数:10请输⼊淘汰的间隔数:3游戏开始......3号同学被淘汰.6号同学被淘汰.9号同学被淘汰.2号同学被淘汰.7号同学被淘汰.1号同学被淘汰.8号同学被淘汰.5号同学被淘汰.10号同学被淘汰.最后的赢家是--> 4号同学!--------------------------------Process exited after 2.205 seconds with return value 27请按任意键继续. . .。

用顺序表解决约瑟夫环问题

用顺序表解决约瑟夫环问题

⽤顺序表解决约瑟夫环问题⼀、实验题⽬:约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个⼈按顺时针⽅向围坐⼀圈,m为任意⼀个正整数。

从第⼀个⼈开始顺时针⽅向⾃1起顺序报数,报到m时停⽌并且报m的⼈出列,再从他的下⼀个⼈开始重新从1报数,报到m时停⽌并且报m的⼈出列。

如此下去,直到所有⼈全部出列为⽌。

要求设计⼀个程序模拟此过程,对任意给定的m和n,求出出列编号序列。

实验要求:⽤顺序表实现。

⼆、设计分析:⾸先创建了⼀个顺序表,并且⽤数组存每个⼈的编号,出列的时候将此编号置为0,代表此位置的⼈已经出列,循环查询编号不为0的元素,并⽤变量j记下当前是第⼏个⼈,当j==m的时候,代表此位置是第m个⼈,输出并将编号置为0,⽤k记录出列⼈的下⼀位的索引,并将数组长度-1,再进⾏新⼀轮的循环,直到所有⼈都出列。

三、程序代码:#include<iostream>#include<cstdlib>using namespace std;const int MaxSize=100;typedef struct Node{int data[MaxSize];int length;}List;void CreateList(List *&L,int n){L=(List *)malloc(sizeof(List*));for(int i=1;i<=n;i++){L->data[i]=i;}L->length=n;}void DispList(List *&L,int m){int len=L->length;int j=0,k=1;while(L->length){for(int i=1;i<=len;i++){if(L->data[k]){j++;}if(j==m){cout<<L->data[k]<<" ";L->data[k]=0;L->length--;j=0;k=(k+1)%(len+1)?(k+1)%(len+1):1;break;}k=(k+1)%(len+1)?(k+1)%(len+1):1;}}}int main(){int m,n;cin>>m>>n;List *L;CreateList(L,n);DispList(L,m);return 0;}。

约瑟夫环设计的知识点

约瑟夫环设计的知识点

约瑟夫环设计的知识点约瑟夫环(Josephus problem)是一个经典的数学问题,它的背后涉及到一些有趣的数学原理和设计思想。

本文将介绍约瑟夫环的背景、问题描述和解决方法,并介绍一些与约瑟夫环相关的知识点。

背景介绍:约瑟夫环问题最早出现在古代历史中,据说是由犹太历史学家弗拉维奥·约瑟夫斯(Flavius Josephus)提出的。

故事的背景是在公元1世纪犹太战争时,罗马军队包围了一个围城的犹太人民。

为了避免被俘或杀害,一群犹太人决定形成一个“死亡圈”,按照一定规则轮流自杀,直到最后一个人留下。

他们选择了一个合适的位置,每次报数到某个固定的数字时将当前的人杀掉,直到只剩下最后的一个人。

问题描述:现在我们将这个问题抽象为数学问题。

假设有n个人,从1到n编号,围成一个圆圈。

从编号为1的人开始报数,每次报到m的人将被淘汰出局,然后从下一个人重新开始报数。

重复这个过程,直到只剩下一个人。

问题的关键是确定最后剩下的人的编号。

解决方法:对于约瑟夫环问题,有很多种解决方法。

下面介绍其中两种常用的方法:1. 数学公式法:我们可以通过数学公式来解决约瑟夫环问题。

根据数学推导,对于给定的n和m,最后剩下的人的编号可以通过以下公式计算得出:f(n,m) = (f(n-1,m) + m) % n其中f(n,m)表示n个人中最后剩下的人的编号。

2. 循环链表法:另一种常用的解决约瑟夫环问题的方法是使用循环链表。

我们可以用一个循环链表模拟这个过程,每次找到要删除的节点并删除,直到只剩下一个节点为止。

这种方法的好处是时间复杂度较低,可以快速找到要删除的节点。

与约瑟夫环相关的知识点:除了约瑟夫环问题本身,还有一些与之相关的知识点,让我们更深入地了解这个问题。

以下是其中几个重要的知识点:1. 约瑟夫环的应用:约瑟夫环在现实生活中有一些应用。

例如,可以用来解决任务分配的问题。

假设有n个任务需要分配给m个人完成,可以通过构建一个约瑟夫环来确定每个任务分配给哪个人。

约瑟夫环问题的两种解法(循环链表和公式法)

约瑟夫环问题的两种解法(循环链表和公式法)

约瑟夫环问题的两种解法(循环链表和公式法)问题描述这⾥是数据结构课堂上的描述:N people form a circle, eliminate a person every k people, who is the final survior?Label each person with 0, 1, 2, ..., n - 1, denote(表⽰,指代) J(n, k) the labels of surviors when there are n people.(J(n, k)表⽰了当有 n 个⼈时幸存者的标号)First eliminate the person labeled k - 1, relabel the rest, starting with 0 for the one originally labeled k.0 1 2 3 ... k-2 k-1 k k+1 ... n-1... k-2 0 1 ...Dynamic programmingJ(n, k) = J(J(n - 1, k) + k) % n, if n > 1,J(1, k) = 0⽤中⽂的⽅式简单翻译⼀下就是 (吐槽:为啥课上不直接⽤中⽂呢?淦!) 有 n 个⼈围成⼀圈,从第⼀个⼈开始,从 1 开始报数,报 k 的⼈就将被杀死,然后从下⼀个⼈开始重新从 1 开始报数,往后还是报 k 的⼈被杀掉,杀到最后只剩⼀个⼈时,其⼈就为幸存者。

(上⾯的英⽂是从 0 开始的,是因为我们写程序时使⽤了数组,所以下标从 0 开始)解决⽅案循环链表⽅法算法思路很简单,我们这⾥使⽤了循环链表模拟了这个过程:节点 1 指向节点 2,节点 2 指向节点 3,...,然后节点 N 再指向节点 1,这样就形成了⼀个圆环。

如图所⽰,n 取 12,k 取 3,从 1 开始报数,然后依次删除 3, 6, 9, 12:#include<stdio.h>#include<stdlib.h>typedef struct Node // 节点存放⼀个数据和指向下⼀个节点的指针{int data;struct Node *next;} *NList; // NList为指向 Node 节点的指针// 创建⼀个节点数为 n 的循环链表NList createList(int n){// 先创建⼀个节点NList p, tmp, head;p = (NList)malloc(sizeof(struct Node));head = p; // 保存头节点p->data = 1; // 第⼀个节点for (int i = 2; i <=n ; i++){tmp = (NList)malloc(sizeof(struct Node));tmp->data = i;p->next = tmp;p = tmp;}p->next = head; // 最后⼀个节点指回开头return head;}// 从编号为 1 的⼈开始报数,报到 k 的⼈出列,被杀掉void processList(NList head, int k){if (!head) return;NList p = head;NList tmp;while (p->next != p){for (int i = 0; i < k - 1; i++){tmp = p;p = p->next;}printf("%d 号被杀死\n", p->data);tmp->next = p->next;free(p);p = NULL; // 防⽌产⽣野指针,下同p = tmp->next;}printf("幸存者为 %d 号", p->data);free(p);p = NULL;}int main(){NList head = createList(11);processList(head, 3);return 0;}测试结果:易知,这个算法的时间复杂度为O(nk),显然,这不是⼀个好的算法。

约瑟夫环设计实验报告

约瑟夫环设计实验报告

一、实验目的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. 实验结果与分析通过运行实验代码,可以得到约瑟夫环问题的出列顺序。

约瑟夫环问题详解

约瑟夫环问题详解

约瑟夫环问题详解很久以前,有个叫Josephus的⽼头脑袋被门挤了,提出了这样⼀个奇葩的问题:已知n个⼈(以编号1,2,3...n分别表⽰)围坐在⼀张圆桌周围。

从编号为k的⼈开始报数,数到m的那个⼈出列;他的下⼀个⼈⼜从1开始报数,数到m的那个⼈⼜出列;依此规律重复下去,直到圆桌周围的⼈全部出列这就是著名的约瑟夫环问题,这个问题曾经风靡⼀时,今天我们就来探讨⼀下这个问题。

这个算法并不难,都是纯模拟就能实现的。

思路⼀:⽤两个数组,mark[10000]和num[10000],mark这个数组⽤来标记是否出队,num这个⽤来存值,然后每次到循环节点的时候就判断mark是否为0(未出队),为0则输出num[i],并标记mark[i]=1,直到所有的num都出队。

附上C++代码:#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<cctype>#include<cmath>#include<algorithm>using namespace std;char num[1000];bool mark[1000];int main(){while(true){memset(mark,0,sizeof(mark));int n;int k,m;int i,j;int del=k-1;cin>>n>>k>>m;for(i=0;i<n;++i){cin>>num[i];}int cnt=n;for(i=cnt;i>1;--i){for(int j=1;j<=m;){del=(del+1)%n;if(mark[del]==0)j++;}cout<<num[del]<<" ";mark[del]=1;}for(i=0;i<n;++i){if(mark[i]==0)break;}cout<<endl<<"The final winner is:"<<num[i]<<endl;}return 0;}思路⼆:⽤⼀个数组就可,每次到了循环节点了就将num[i]输出,然后将后⾯的值往前移动⼀位,直到所有的节点出列。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

约瑟夫环的循环链表实现#include <stdio.h>#include <stdlib.h>#define NUMBER 13 //可以通过输入确定人的个数#define NEXT 8 //确定报数的间隔数#define LENGTH sizeof(MEN)#define NULL 0struct men{int number;struct men *pMen;};typedef struct men MEN;/********************************************/ /* 约瑟夫环的循环链表实现 *//********************************************/ void main(){MEN *pOne = NULL, *pTwo = NULL, *pHead =NULL;int client;/** 创建环形链表*/pHead = pOne = pTwo = (MEN *)malloc(LENGTH);pHead->number = 1;for (client = 2; client <= NUMBER; client++){pOne = (MEN *)malloc(LENGTH);pTwo->pMen = pOne;pOne->number = client;pTwo = pOne;}pOne->pMen = pHead;/** 进行操作*/pTwo = pHead;pOne = pTwo->pMen;while(pOne->pMen != pTwo){for(client = 0; client < NEXT - 2;client++){pTwo = pOne;pOne = pOne->pMen;}// if(pOne == pHead)//对于单向链表的头指针删除问题已经不存在// pHead = pOne->pMen;// elsepTwo->pMen = pOne->pMen;pOne = NULL;free(pOne);pOne = pTwo->pMen;pOne = pOne->pMen;pTwo = pTwo->pMen;//保持初始状态}printf("%d\n", pOne->number);}对于每一位都有一个位权的实现:#include <stdio.h>#include <stdlib.h>#define LENGTH sizeof(MEN)#define NULL 0struct men{int number;int code;struct men *pMen;};typedef struct men MEN;////////////////////////////////////////////////////////////////////////// // 约瑟夫环的循环链表实现////////////////////////////////////////////////////////////////////////// void main(){MEN *pOne = NULL,*pTwo = NULL,*pHead = NULL;int client;int NUMBER = 13; //设置默认的人数int NEXT = 3; //选出的人数间隔的初始间隔数// 输入人数//printf("请输入游戏的人数:");scanf("%d", &NUMBER);//// 创建环形链表//pHead = pOne = pTwo = (MEN *)malloc(LENGTH); if (pHead == NULL){printf("头结点空间分配出错!");return;}//// 初始这个链表,对头结点进行赋值//pHead->number = 1;printf("请输入第1位的密码:");scanf("%d", &pHead->code);for (client = 2; client <= NUMBER; client++){pOne = (MEN *)malloc(LENGTH);if(pOne == NULL){printf("空间分配出错!");return;}pTwo->pMen = pOne;pOne->number = client;printf("请输入第%d位的密码:", client);scanf("%d", &pOne->code);pTwo = pOne;}pOne->pMen = pHead;printf("\n被选出的次序:\n");//// 进行操作//pTwo = pHead;pOne = pTwo->pMen;while(pOne->pMen != pTwo)for(client = 0; client < NEXT - 2;client++){pTwo = pOne;pOne = pOne->pMen;}// if(pOne == pHead)//对于单向链表的头指针删除问题已经不存在// pHead = pOne->pMen;// elsepTwo->pMen = pOne->pMen;//// 释放不用的结点//printf(" %d ", pOne->number);NEXT = pOne->code;pOne = NULL;free(pOne);pOne = pTwo->pMen;pOne = pOne->pMen;pTwo = pTwo->pMen;//保持初始状态}printf("%d", pTwo->number);printf("\n最后留下的是:%d\n", pOne->number);}#include "stdio.h"#include "stdlib.h"#define S sizeof(struct node)struct node{int num;struct node *next;};typedef struct node NODE;NODE *createlinklist(int n){NODE *head,*p,*q;int i=1;head=p=(struct node*)malloc(sizeof(struct node));p->num=i;for(i=2;i<=n;i++){q=(struct node*)malloc(sizeof(struct node));if(q==0) return(0);p->next=q;p=q;p->num=i;}p->next=head; /*使链表尾指向链表头形成循环链表*/return head;}void printlinklist(NODE *p,int n){int i;NODE *q = p;if(NULL == q->next){printf("the list is NULL!");return;}printf("所有玩家的信息列表:\n");for(i=1;i<=n;i++){if(NULL == q){printf("the list is NULL!");return;}printf("%d ",p->num);p=p->next;}printf("\n");}void joseph(NODE *p,int n,int m){int i,j;NODE *q;for(i=1;i<n;i++){for(j=1;j<=m-1;j++){p=p->next;}q=p->next;p->next = q->next;printf("%d ",q->num);free(q);}printf("\n最后剩余的是第%d号.\n",p->num); p->next=NULL;}void main(){NODE *head;int n,m;printf("请输入人数N:\n");scanf("%d",&n);printf("输入K:\n");scanf("%d",&m);head=createlinklist(n);printlinklist(head,n);printf("依次被选出的是:\n");joseph(head,n,m);}。

相关文档
最新文档