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