约瑟夫问题的C++代码

合集下载

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++版)程序设计报告
Jose类中的成员函数分别为:
函数
相关说明
Jose(int boys, int interval, int begin=1);
构造函数,主要功能初始化各个参数,校验输出的m、n、s参数为int boys, int interval, int begin=1
void getWinner()const;
//构造函数
//-------------------------------------
BoyRing::BoyRing(int n)
{
if(n<2) throw exception(); //发生错误时自动跳出
pBegin = new Boy[n]; //申请一个新的Boy空间,pBegin指向该空间的开始处
for(int i=1; i<=n; i++)
{
pBegin[i-1].next = &pBegin[i%n];//形成链表
pBegin[i-1].code = i;//给孩子孩子编号
}
pivot = pCurrent = &pBegin[n-1];//各指针初始化
}
//------------------------------------
2详细设计
2.1程序结构
改程序分成三个抽象层次,第一层是应用层,直接指使Jose类对象去完成求解工作;第二层是Jose类层,描述Josephus问题的求解细节;第三层是BoyRing类层,辅助Jose类完成求解过程(上述三层间的关系描述如图J-1,这也是程序模块间的关系)。
图J-1.对象实现中程序模块的相互关系
void disengage();
利用指针实现小孩离队,无参数

约瑟夫环问题源代码(C语言)

约瑟夫环问题源代码(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);}}实验体会:通过对本问题的分析,我进一步熟悉了对各种逻辑表达式的判断和指针的使用。

约瑟夫问题pascal

约瑟夫问题pascal

约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。

在计算机编程的算法中,类似问题又称为约瑟夫环。

又称“丢手绢问题”)据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。

然而Josephus 和他的朋友并不想遵从。

首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。

接着,再越过k-1个人,并杀掉第k个人。

这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。

问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

//详情请见百度百科。

[题目描述]Josephus问题是建立在历史学家Josephus的一个报告的基础之上,该报告讲述了他和40个士兵在公元67年被罗马军队包围期间签定的一个自杀协定,Josephus建议每个人杀死他的邻居,他很聪明的使自己成为这些人中的最后一个,因此获得生还。

21世纪的今天,我们将Josephus问题稍作扩展:设N个人围成一圈,依次从1到N编号,从第S号开始报数,报到K的人出列,求第T个出列的人的编号。

显然,Josephus面对的是N = 40, K = 2, S= 1, T = 40的退化情况。

[数据范围]30%的数据,K = 2100%的数据,1 <= N <= 1000000, 1<= K <= 2147483647, 1 <= S <= N, 1 <= T <= N最简单的推导方法应该是模拟。

C++约瑟夫环的实例代码

C++约瑟夫环的实例代码

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

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

分析:有n个⼈,要想所有的⼈都退出去,只有每个⼈喊到m,才可以退完,所以可以算出,n*m为所有⼈总共报数的总次数。

代码:/** 约瑟夫出圈*/#include <stdio.h>int main(){char peo[100] ;char *p_peo = peo;int i , n , skip , flag[100] = {0} , cnt;int *p_flag = NULL;printf("请输⼊⼈数:");scanf("%d", &n);printf("所有⼈如下:\n");for(p_peo , i = 0 ; p_peo < peo + n ; ++p_peo , ++i){*p_peo = 'a' + i;printf("%c ", *p_peo);}printf("\n");printf("请输⼊报数值:");scanf("%d", &skip);cnt = 0;while(cnt <= n * skip){for(p_peo = peo , p_flag = flag ; p_peo < peo + n ; ++p_peo , ++p_flag){if(*p_flag)continue;cnt++;if(!(cnt % skip)){*p_flag = 1;printf("%c ", *p_peo);}}}printf("\n");return 0;}如有疑问请留⾔或者到本站社区交流讨论,感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

约瑟夫问题C++代码

约瑟夫问题C++代码
#include<iostream>
using namespace std;
struct node
{
int data;
struct node* next;
};
class joseph
{
public:
joseph(); //构造函数
int function(); //用于实现约瑟夫问题的功能函数
private:
node* rear; //尾指针
};
joseph::joseph()
{
cout<<"请输入桌上的人数n"<<endl;
int number;
cin>>number;
while(cin.fail()) //判断输入类型是否匹配
{
cout<<"请输入大于0的数"<<endl;
cin.clear();
cin.ignore(); //若不恰当,清空流
cin>>number;
}
rear =new node;
rear ->
for(int i=number;i>0;i--)
{
s=new node;
s->data=i;
s->next=rear->next;
rear->next=s; //使用头插法进行构造
};
while(s->next!=rear) //构造完毕,删除尾节点,方便后面的操作。
cin>>b;
}
node* s=rear; //工作指针
while(s->next!=s) //终止条件

约瑟夫问题C代码

约瑟夫问题C代码

约瑟夫问题C代码 1/*Joseph Problem2 *利⽤单循环链表解决约瑟夫问题。

3 *问题描述:将n个数链接成⼀个环,从第m个开始,每次从1计数到s时4 * 将s删除。

从下⼀个开始再次从1计数⾄s时删除s。

直到全5 * 部删除为⽌。

6 * */7 #include<stdio.h>8 #include<stdlib.h>910 typedef struct Node{11int data;12struct Node* next;13 }Node;14 typedef struct Node* LinkList;1516void CreateJosephLoop(LinkList *L,int number){17//创建Joseph环,在头结点中放⼊了元素1.18 *L = (LinkList)malloc(sizeof(struct Node));19if(!(*L)){20 printf("Error:malloc:0!\n");21 exit(1);22 }23 (*L)->next = (*L);24 (*L)->data = 1;25int i;26 LinkList new;27 LinkList tail = *L;28for(i = 1; i < number; i++){29new = (LinkList)malloc(sizeof(struct Node));30if(!new){31 printf("Error:malloc:1+i");32 exit(1);33 }34new->data = i+1;35new->next = tail->next;36 tail->next = new;37 tail = new;38 }39 }40void JosephProblem(int loopSize,int from,int stepBy){41//loopSize:Joseph环的⼤⼩42//form:从from开始43//stepBy:每次计数到stepBy时删除stepBy所指向的元素44 LinkList L;45 CreateJosephLoop(&L,loopSize);46int seekStart = 1;47while(seekStart < from){48 L = L->next;49 seekStart += 1;50 }51while(L->data != L->next->data){52int i = 1;53 LinkList temp;54for(i = 1;i < stepBy - 1; ){55 L = L->next;56 i++;57 }58 temp = L->next;59 printf("%d-->",temp->data);60 L->next = L->next->next;61 L = L->next;62free(temp);63 }64 printf("%d\n",L->data);65 }66int main(){67 JosephProblem(10,3,4);68 JosephProblem(41,1,3); 69return0;70 }。

约瑟夫问题详解(CC++)

约瑟夫问题详解(CC++)

约瑟夫问题详解(CC++)Josephus 约瑟夫问题假设n个竞赛者排成一个环形,依次顺序编号1,2,…,n。

从某个指定的第1号开始,沿环计数,每数到第m个人就让其出列,且从下一个人开始重新计数,继续进行下去。

这个过程一直进行到所有的人都出列为止。

最后出列者为优胜者。

无论是用链表实现还是用数组实现来解约瑟夫问题都有一个共同点:要模拟整个游戏过程,不仅程序写起来比较麻烦,而且时间复杂度高达O(nm),当n,m非常大(例如上百万,上千万)的时候,几乎是没有办法在短时间内出结果的。

注意到原问题仅仅是要求出最后的胜利者的序号,而不是要模拟整个过程。

因此如果要追求效率,就要打破常规,实施一点数学策略。

为了讨论方便,先把问题稍微改变一下,并不影响原意:问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。

求胜利者的编号。

我们知道第一个人(编号一定是m%n-1) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m%n的人开始): k k+1 k+2 ... n-2, n-1, 0, 1, 2, ... k-2并且从k开始报0。

现在我们把他们的编号做一下转换:k --> 0k+1 --> 1k+2 --> 2......k-2 --> n-2变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x 是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?变回去的公式很简单:x'=(x+k)%n如何知道(n-1)个人报数的问题的解?显然,只要知道(n-2)个人的解就行了。

(n-2)个人的解呢?当然是先求(n-3)的情况---- 这显然就是一个倒推问题!递推公式:令f[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n]递推公式f[1]=0;f[i]=(f[i-1]+m)%i; (i>1)有了这个公式,我们要做的就是从1-n顺序算出f[i]的数值,最后结果是f[n]。

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

#include<iostream>
using namespace std;
struct Node//定义节点的结构类型
{
int data;
Node* next;
};
class CircularLinkedList//循环链表类
{
public:
CircularLinkedList(){first=new Node;first->next=NULL;}
CircularLinkedList(int n);//构建一个附有值的循环链表
~CircularLinkedList();
int Josephus(int num);//约瑟夫函数
private:
Node* first;
};
CircularLinkedList::CircularLinkedList(int n)
{
first=new Node;
Node * r=first;
for(int i=1;i<=n;i++)
{
Node* s=new Node;
s->data=i;
s->next=NULL;
r->next=s;
r=s;
} //头插法初始化链表
r->next=first; //最后一个元素的next志指向头结点}
CircularLinkedList::~CircularLinkedList()
{
Node* p=first,*q;
while(p->next!=first)//p指向最后一个结点时结束循环
{
q=p;
p=p->next;
delete q;
}
delete p;//删除头结点
}
int CircularLinkedList::Josephus(int num)
{
Node* p=first,*q;
if(num<=0)
throw "输入错误!";
while(first->next->next!=first)
{
for(int i=1;i<num;i++) //p向后移动num位,指向要删除的元素的前一个结点
{
p=p->next;
if(p==first) //若循环过程中出现p指向头结点,则跳过头结点
{
p=p->next;
}
}
if(p->next==first) //若循环结束后p指向最后一个元素,则要跳过头结点,并让头结点的next指向要删除元素的下一个
{
p=first;
q=p->next;
p->next=q->next;
//first->next=q->next;
cout<<q->data<<" ";
delete q;
}
else
{
q=p->next;
p->next=q->next;
cout<<q->data<<" ";
delete q;
}
}
cout<<endl;
cout<<"最后一个数为:";
return first->next->data;
}
void main()
{
int n,m;
cout<<"请输入约瑟夫问题的人数和间隔人数:";
cin>>n>>m;
cout<<"依次删除:"<<endl;
CircularLinkedList Josephus1(n);//创建的对象调用第二个构造函数
cout<<Josephus1.Josephus(m)<<endl;
}。

相关文档
最新文档