Josephus(约瑟夫)问题----分别用循环链表和数组实现
2012-10-04 20:04
459 查看
#include<iostream> using namespace std; void Josephus(int n,int m,int k) { int *a=new int [10000],i; int count=0;//计算被退出的人数(n-1) int t=0;//1,2,3..m报数记数变量 for(i=0;i<n;i++) a[i]=i+1; i=k-1; while(count<n-1)//只剩下一个时退出循环 { if(a[i]!=0) t++; if(t==m) { t=0;//记数归0 printf("%4d",a[i]);//依次输出删除的编号 a[i]=0;//给删除的数组赋0 count++;//退出人数加1 } i++; if(i==n) i=0;//报数到末尾后i恢复为0 } for(i=0;i<n;i++) if(a[i]!=0) { printf("\n最后剩余的结点是:%4d\n",a[i]); return; } } int main() { int n,m,k; cout<<"请输入结点的个数:"<<endl; scanf("%d",&n); cout<<"请输入报道报数周期是:"<<endl; scanf("%d",&m); cout<<"请输入从第几个数开始报数:"<<endl; scanf("%d",&k); Josephus(n,m,k); return 0; }
/*用数组实现约瑟夫问题比较上面的更复杂,自己想的,没参考书上的。*/ #include<iostream> using namespace std; void Josephus(int n,int m,int k) { int *a=new int [10000],i; int count=0;//计算被退出的人数(n-1) int t=0;//1,2,3..m报数记数变量 int l=1;//while退出循环条件 for(i=0;i<n;i++) a[i]=i+1; while(l) { for(i=k-1;i<n;i++) { if(a[i]!=0) { t++; if(t==m) { t=0;//记数归0 printf("%4d",a[i]);//依次输出删除的编号 a[i]=0;//给删除的数组赋0 count++;//退出人数加1 } } if(count==n-1) { l=0;//循环终止 break; } } k=1;//非第一次时将i变为从0开始 } for(i=0;i<n;i++) if(a[i]!=0) { printf("\n最后剩余的结点是:%4d\n",a[i]); return; } } int main() { int n,m,k; cout<<"请输入结点的个数:"<<endl; scanf("%d",&n); cout<<"请输入报道报数周期是:"<<endl; scanf("%d",&m); cout<<"请输入从第几个数开始报数:"<<endl; scanf("%d",&k); Josephus(n,m,k); return 0; }
/*用循环链表实现约瑟夫问题*/ #include<iostream> #include<stdlib.h> using namespace std; typedef struct LNode { int data; struct LNode *next; }LNode,*LinkList; void Josephus(int n,int m,int k) { LinkList p,r,list=NULL; int i; for(i=1;i<=n;i++) { p=(LinkList)malloc(sizeof(LNode));//申请一个新的链结点 p->data=i;//存放第i个结点的编号 if(list==NULL) list=p; else r->next=p; r=p; } p->next=list;//至此,建立一个循环链表 p=list; for(i=1;i<k;i++) { r=p; /*请注意,此行不是多余的,因为当k!=1,但m=1时如果没有这条语句,此时删除动作无法完成*/ p=p->next; }//此时p指向第1个出发结点 while(p->next!=p) { for(i=1;i<m;i++) { r=p; p=p->next; }//p指向第m个结点,r指向第m-1个结点 r->next=p->next;//删除第m个结点 printf("%4d",p->data);//依次输出删除结点的编号 free(p);//释放被删除结点的空间 p=r->next;//p指向新的出发结点 } printf("\n最后剩余的结点是:%4d\n",p->data);//输出最后一个结点的编号 } int main() { int n,m,k; cout<<"请输入结点的个数:"<<endl; scanf("%d",&n); cout<<"请输入报道报数周期是:"<<endl; scanf("%d",&m); cout<<"请输入从第几个数开始报数:"<<endl; scanf("%d",&k); Josephus(n,m,k); return 0; }
/*任务: 一群小孩围成一圈,任意假定一个数m,从第一个小孩起,顺时针方向数,每数到第m个小孩时,该小孩便离开。小孩不断离开,圈子不断缩小。最后剩下的一个小孩便是胜者。求胜者的编号? 要求 以面向对象技术进行程序设计 建立环状链表类 程序便于维护与扩张:如易于对小孩数量n和数数间隔m进行变化 改变获胜者数量,使其可设为任意值 可中途增加小孩人数 */ /*结构体实现*/ #include<iostream> #include<stdlib.h> using namespace std; typedef struct LNode { int data; struct LNode *next; }LNode,*LinkList; class Jos { private: int n,m,k,last;//结点个数,报数周期,报数起始数. int index;//标记剩余人数,标记插入时r第一个的指向. LinkList list,r; public: Jos(){list=NULL;r=NULL;} void set(); void Josephus(); void Insert(); void is_add(); void print_Josephus(); }XPY; void Jos:: set()//插入函数 { cout<<"请输入结点的个数:"<<endl; scanf("%d",&n); cout<<"请输入报道报数周期是:"<<endl; scanf("%d",&m); cout<<"请输入从第几个数开始报数:"<<endl; scanf("%d",&k); cout<<"请输入剩余个数:"<<endl; scanf("%d",&last); } void Jos:: Josephus()//建立一个循环链表 { LinkList p; int i; index=n;//结点个数赋初值 for(i=1;i<=n;i++) { p=(LinkList)malloc(sizeof(LNode));//申请一个新的链结点 p->data=i;//存放第i个结点的编号 if(list==NULL) list=p; else r->next=p; r=p; } p->next=list;//至此,建立一个循环链表 } void Jos:: Insert()//循环链表的插入 { LinkList p=(LinkList)malloc(sizeof(LNode)); p->data=n+1; n++;//个数加1 index++;//个数加1 p->next=r->next; r->next=p; r=p; } void Jos:: is_add()//中途添加函数 { printf("是否添加成员(Y/N)\n"); char ch; cin>>ch; while(1) { system("cls"); ch=tolower(ch);//转换为全小写的 if(ch=='y') Insert(); else if(ch=='n') break; else printf("输入有误\n"); system("cls"); printf("是否继续添加成员(Y/N)\n"); cin>>ch; } } void Jos:: print_Josephus()//循环的执行 { LinkList p=list; for(int i=1;i<k;i++) { r=p; /*请注意,此行不是多余的,因为当k!=1,但m=1时如果没有这条语句,此时删除动作无法完成*/ p=p->next; }//此时p指向第1个出发结点 while(index>last) { for(i=1;i<m;i++) { r=p; p=p->next; }//p指向第m个结点,r指向第m-1个结点 r->next=p->next;//删除第m个结点 printf("删除的结点号是:%d\n\n",p->data);//依次输出删除结点的编号 free(p);//释放被删除结点的空间 is_add(); p=r->next;//p指向新的出发结点 index--;//删除结点,个数减1 } while(index--)//胜利者的输出 { printf("\n最后剩余的结点是:%4d\n",p->data);//输出最后一个结点的编号 p=p->next; } } int main() { XPY.set(); XPY.Josephus(); XPY.print_Josephus(); return 0; } /*数组实现*/ #include<iostream> using namespace std; class Jos { private: int *a,length,data; int n,m,k,last;//结点个数,报数周期,报数起始数. public: Jos() { a = new int [1000000]; } void set(); void is_add(); void print_Josephus(); }XPY; void Jos:: set()//插入函数 { cout<<"请输入结点的个数:"<<endl; scanf("%d",&n); cout<<"请输入报道报数周期是:"<<endl; scanf("%d",&m); cout<<"请输入从第几个数开始报数:"<<endl; scanf("%d",&k); cout<<"请输入剩余个数:"<<endl; scanf("%d",&last); } void Jos:: is_add()//中途添加函数 { printf("是否添加成员(Y/N)\n"); char ch; cin>>ch; while(1) { ch=tolower(ch);//转换为全小写的 if(ch=='y') a[n++]=n+1; else if(ch=='n') break; else printf("输入有误\n"); printf("是否继续添加成员(Y/N)\n"); cin>>ch; } } void Jos::print_Josephus() { int i; int count=0;//计算被退出的人数(n-1) int t=0;//1,2,3..m报数记数变量 for(i=0;i<n;i++) a[i]=i+1; i=k-1; while(count<n-last)//只剩下一个时退出循环 { if(a[i]!=0) t++; if(t==m) { t=0;//记数归0 printf("删除的结点为:%4d\n",a[i]);//依次输出删除的编号 a[i]=0;//给删除的数组赋0 count++;//退出人数加1 is_add(); } i++; if(i==n) i=0;//报数到末尾后i恢复为0 } for(i=0;i<n;i++) if(a[i]!=0) printf("\n最后剩余的结点是:%4d\n",a[i]); } int main() { XPY.set(); XPY.print_Josephus(); return 0; }
相关文章推荐
- 约瑟夫问题(Josephus Problem) 用双向循环链表实现
- 循环链表范例(约瑟夫问题) 数组实现
- 约瑟夫问题的数学角度分析 C 数组实现 循环链表实现 递归实现时间复杂度O(logN)
- 约瑟夫问题---数组实现
- 循环链表实现约瑟夫问题
- 循环链表实现约瑟夫问题
- 约瑟夫环,100个人围成圈圈,逢3退出,求最后剩下的人的编号(分别用数组和双向循环链表实现)
- The Second Blog -数组实现约瑟夫问题-C语言
- 利用循环链表实现约瑟夫问题的求解
- Josephus问题(约瑟夫问题)链表的实现
- C语言实现:约瑟夫问题(数组和单链表2种方法)
- 循环链表范例(约瑟夫问题)指针实现
- 约瑟夫问题的数组实现
- 循环链表实现约瑟夫问题,拉丁方阵问题
- C++单向加双向循环链表实现约瑟夫问题
- 用循环链表实现约瑟夫问题
- 约瑟夫问题(循环链表实现)
- C++循环链表实现约瑟夫问题
- POJ 3750 小孩报数问题 (线性表思想 约瑟夫问题 数组模拟运算的 没用循环链表,控制好下标的指向就很容易了)
- 约瑟夫问题简单实现-循环链表