约瑟夫环
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• • • • • • • • •
• • • • • • • •
• •
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); • }
• 【设计思想】 • 首先,设计实现约瑟夫环问题的存储结构。由于约瑟夫环 本身具有循环性质,考虑采用循环链表,为了统一对表中 任意节点的操作,循环链表不带头结点。循环链表的结点 定义为如下结构类型: • struct Node • { • int number; • Node *next; • }; • 其次,建立一个不带头结点的循环链表并由头指针first指 示。 • 最后,设计约瑟夫环问题的算法。
• if(m<1){cout<<"请输入正整数!";}//号数异常处理 • else • if(m>n){cout<<"死亡密码数字大于游戏人数, 请重新输入!";} • else • { • L=CreateList(L,n,m);//重新给尾指针赋值 • Joseph(L,n,m); • } • } • system("pause"); • }
问题说明
• 据说着名犹太历史学家 Josephus有过以下的 故事:在罗马人占领乔塔帕特后,39 个犹 太人与Josephus及他的朋友躲到一个洞中, 39个犹太人决定宁愿死也不要被敌人到, 于是决定了一个自杀方式,41个人排成一 个圆圈,由第1个人 开始报数,每报数到第 3人该人就必须自杀,然后再由下一个重新 报数,直到所有人都自杀身亡为止。 • 然而Josephus 和他的朋友并不想遵从, Josephus要他的朋友先假装遵从,他将朋友 与自己安排在第16个与第31个位置,于是 逃过了这场死亡游戏。
开始
输入m和n
创建链表
k>n-1 N 移动指针p
Y
删除p后一结点q
指针p后移,k++
输出nቤተ መጻሕፍቲ ባይዱ
结束
#include<iostream> 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);//计算环上所有人数函数
• 使用程式来求解的话,只要将阵列当作环 状来处理就可以了,在阵列中由计数1开始, 每找到三个无资料区就填入一个计数,直 而计数达41为止,然后将阵列由索引1开始 列出,就可以得知每个位置的自杀顺序, 这就是约瑟夫排列,41个人而报数3的约瑟 夫排列如下所示: • 14 36 1 38 15 2 24 30 3 16 34 4 25 17 5 40 31 6 18 26 7 37 19 8 35 27 9 20 32 10 41 21 11 28 39 12 22 33 13 29 23 • 由上可知,最后一个自杀的是在第31个位 置,而倒数第二个自杀的要排在第16个位 置,之前的人都死光了,所以他们也就不 知道约瑟夫与他的朋友并没有遵守游戏规 则了。
• 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 main()//主函数 { Node *L; L=NULL;//初始化尾指针 int n, m; cout<<"请输入游戏人数N:"; cin>>n;//环的长度 if(n<1){cout<<"请输入正整数!";}//人数异常处理 else { cout<<"请输入死亡密码(报到该数即死)M:"; cin>>m;
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); } }