Josephus(約瑟夫)問題----分別用循環鏈表和數組實現


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM