1. 程式人生 > >約瑟夫環問題 java程式碼實現(高效率)

約瑟夫環問題 java程式碼實現(高效率)

<pre name="code" class="java">//約瑟夫問題
package com.test;
public class test {
public static void main(String[] args)  {
            CycLink cycLink= new CycLink(5,2,3);
            
    }
}
class ChildNode{
     int Num;//編號
     ChildNode nextChildNode=null;//指向下一個結點
     ChildNode preChildNode=null;
     public ChildNode(int num){
         this.Num=num;
     }
}
class CycLink{//環形連結串列
    //先定義一個指向連結串列第一個結點的引用,指向第一個結點的引用,不能動
    ChildNode TofirstChildNode=null;
    ChildNode temp=null;
    int len=0;//共有多少個結點
    int k=0;//從第幾個人開始數數
    int m=0;//數m下
    int n=1;//第n個人出局
    //設定連結串列大小
    public CycLink(int len,int k,int m){
         this.len=len;//設定環形連結串列大小
         this.k=k;//設定從第幾個人開始數數
         this.m=m;//設定數m下
         creatLink();
         showLink();
         play();
    }
    //開始約瑟夫規則遊戲
    private void play(){
        ChildNode cursor=this.TofirstChildNode;
        //1.先開始找到開始數數的人
        for(int i=1;i<k;i++){
            cursor=cursor.nextChildNode;
        }
        while(this.len!=1){
        //2.數m下,找到了要刪除的結點
        for(int j=1;j<m;j++){
            cursor=cursor.nextChildNode;
            //其實沒人引用了,那麼過會兒就會被GC回收
        }
        //3.將數到m的結點,退出圈
         System.out.println("第"+this.n+"次出局的人編號是:"+cursor.Num);
         cursor.preChildNode.nextChildNode=cursor.nextChildNode;//刪除操作
         cursor.nextChildNode.preChildNode=cursor.preChildNode;//刪除操作
         //讓cursor指向下一個開始數數的人,這個動作很重要,不然遊標就不動了
         cursor=cursor.nextChildNode;
         this.len--;//出圈一個人,
         this.n++;
        }
        //最後一個剩下的結點
        System.out.println("最後還在桌子上坐著的人編號:"+cursor.Num);
    }
    //初始化環形連結串列
    private void creatLink(){
        for(int i=1;i<=len;i++){
            if(i==1){
            //建立第一個結點
            ChildNode ch=new ChildNode(i);
            this.TofirstChildNode=ch;
            temp=ch;
           }
            else{
                //建立最後一個結點
                if(i==len){
                    ChildNode ch=new  ChildNode(i);
                    temp.nextChildNode=ch;
                    ch.preChildNode=temp;
                    temp=ch;
                    temp.nextChildNode=this.TofirstChildNode;
                    this.TofirstChildNode.preChildNode=ch;
                }
                else{
                //繼續建立結點
                 ChildNode ch=new  ChildNode(i);
                 temp.nextChildNode=ch;
                 ch.preChildNode=temp;
                 temp=ch;
               }
            }
        }
    }
    //列印環形連結串列
    private void showLink(){
        //定義一個遊標
       ChildNode cursor=this.TofirstChildNode;
       do{
           System.out.println("參員編號為:"+cursor.Num);
           cursor=cursor.preChildNode; 
       }
       while(cursor!=this.TofirstChildNode);
    }
}

執行結果: