1. 程式人生 > >《C++語言基礎》實踐參考——Josephus(約瑟夫環)問題

《C++語言基礎》實踐參考——Josephus(約瑟夫環)問題

【專案-Josephus(約瑟夫環)問題】
n個小孩子圍成一圈,從第一個小孩子開始順時針方向數數字,到第m個小孩子離開,這樣反反覆覆,最終只剩下一個小孩子,求第幾個小孩子留下?
    提示:約瑟夫環即是一個首尾相連的連結串列,在建立好這個環以後,從頭結點開始,每次間隔m孩子刪除一個結點,直至只餘下一個結點(刪除了n-1個)。


    參考下面的程式碼,也可以自行設計類。

//連結串列結點kid,其中number為這個人的編號
struct kid
{
    int number;
    kid *next;
};

//約瑟夫環類
class joseph_ring
{
private:
    int n;//用於存放人數
    int m;//用於存放初始密碼
    kid *head;//連結串列的頭結點,初始化時指向1號孩子
public:
    joseph_ring(int nn, int mm);//建立nn個孩子,間隔為mm的約瑟夫環
    void show();//運算並輸出的成員函式
};
//定義joseph_ring類中的成員函式
……
int main()
{
    int n,m;
    cout<<"n=";
    cin>>n;
    cout<<"m=";
    cin>>m;
    joseph_ring j(n,m);
    j.show();
    return 0;
}
[參考解答]
#include <iostream>
using namespace std;
//連結串列結點kid,其中number為這個人的編號
struct kid
{
    int number;
    kid *next;
};

//約瑟夫環類
class joseph_ring
{
private:
    int n;//用於存放人數
    int m;//用於存放間隔
    kid *head;//連結串列的頭結點
public:
    joseph_ring(int nn, int mm);//建立nn個孩子,間隔為mm的約瑟夫環
    ~joseph_ring();
    void show();//運算並輸出的成員函式
};
//建立nn個孩子,間隔為mm的約瑟夫環
joseph_ring::joseph_ring(int nn, int mm)
{
    n=nn;    //建構函式,把成員變數賦初值
    m=mm;
    kid *p1,*p2; //定義2個臨時指標
    for(int i=1; i<=n; i++)//for迴圈用於初始化環
    {
        p1=new kid;
        p1->number=i;  //編號
        if(i==1)       //如果當前連結串列為空,頭指標指向第一個人
        {
            head=p1;
            p2=p1;
        }
        else     //否則,p2永遠指向尾結點,新建立的結點都插入到p2之後
        {
            p2->next=p1;
            p2=p1;
        }
    }
    p2->next=head;//把連結串列連成一個迴圈連結串列
}

joseph_ring::~joseph_ring()
{
    delete head;
    head=NULL;
}

void joseph_ring::show()  //執行出圈操作
{
    kid *p1,*p2,*p;
    int count;
    p1=head;
    for(int i=1; i<=n-1; i++)//有n個人,所以執行n-1次迴圈,刪除n-1個人
    {
        count=1;  //用count定位到第m個人,迴圈後,p1指向這個人,p2指向這個人的上一個人
        while(count<m)
        {
            p2=p1;  //p2指向前一個
            p1=p1->next;
            count++;
        }
        cout<<p1->number<<"\t";//這指向的是當前要刪除人
        p=p1;//p指向當前這個人
        p2->next=p1->next;//將當前出圈人的直接前驅和直接後繼連線起來
        p1=p1->next;//下次從當前人的下一個人開始數
        delete p;//釋放記憶體
    }
    cout<<endl;
    cout<<"The last one is No. "<<p1->number<<endl;
    head=p1; //環中只剩下了一個結點
}

int main()
{
    int n,m;
    cout<<"n=";
    cin>>n;
    cout<<"m=";
    cin>>m;
    joseph_ring j(n,m);
    j.show();
    return 0;
}