1. 程式人生 > 其它 >約瑟夫環問題——環形連結串列解決

約瑟夫環問題——環形連結串列解決

約瑟夫環問題

約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知 n 個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。. 從編號為 k 的人開始報數,數到 m 的那個人出圈;他的下一個人又從 1 開始報數,數到 m 的那個人又出圈;依此規律重複下去,直到剩餘最後一個勝利者

環形單向連結串列解決

package data_structure.CircleList;

public class Circle1
{
    public static void main(String[] args)
    {
        CircleList circleList = new CircleList();
        circleList.add(8);
        circleList.showBoy();
        circleList.count(3,7,8);
    }
}

class CircleList
{
    //建立first節點,當前沒有編號
    private Boy first = null;

    //新增節點
    public void add(int nums)
    {
        if (nums < 1)
        {
            System.out.println("nums 值不正確");
            return;
        }
        Boy temp = null; //輔助節點
        for (int i = 1; i <= nums; i++)
        {
            //根據編號,建立節點
            Boy boy = new Boy(i);
            //如果是第一個小孩
            if (i == 1)
            {
                first = boy;
                first.setNext(first);//指向自己本身 環
                temp = first;
            } else
            {
                temp.setNext(boy);
                boy.setNext(first); //指向第一個形成環
                temp = boy;
            }

        }
    }

    //遍歷環形連結串列
    public void showBoy()
    {
        if (first == null)
        {
            System.out.println("連結串列為空");
            return;
        }
        Boy temp = first;
        while (true)
        {
            System.out.println("編號 " + temp.getNo());
            if (temp.getNext() == first)//遍歷完畢
            {
                break;
            }
            temp = temp.getNext();
        }
    }

    //根據使用者輸入,計算出出圈順序
    public void count(int statNo, int countNum, int nums)
    {
        if (first == null || statNo < 1 || statNo > nums)
        {
            System.out.println("輸入資料有誤");
            return;
        }

        Boy temp = first;//輔助節點
        //移動temp到first的後面
        while (true)
        {
            if (temp.getNext() == first)
            {
                break;
            }
            temp = temp.getNext();
        }
        //報數前的移動
        for (int i = 0; i < statNo - 1; i++)
        {
            first = first.getNext();
            temp = temp.getNext();
        }
        //開始報數
        while (true)
        {
            if (first == temp)
            {
                break;
            }
            for (int j = 0; j < countNum - 1; j++)
            {
                first = first.getNext();
                temp = temp.getNext();
            }
            //這時first指向的節點就是要出圈的節點
            System.out.println("編號"+first.getNo()+"出圈");
            first = first.getNext();//first 前移
            temp.setNext(first);//temp依然跟在first後面
        }
        System.out.println("最後的一個人編號:"+first.getNo());
    }
}

//建立一個Boy類,表示一個節點
class Boy
{
    private int no; //編號
    private Boy next;//指向下一個節點,預設null

    public Boy(int no)
    {
        this.no = no;
    }

    public int getNo()
    {
        return no;
    }

    public void setNo(int no)
    {
        this.no = no;
    }

    public Boy getNext()
    {
        return next;
    }

    public void setNext(Boy next)
    {
        this.next = next;
    }

}