#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; }