1. 程式人生 > >迴圈單鏈表完成約瑟夫環.java

迴圈單鏈表完成約瑟夫環.java

問題描述:約瑟夫環問題的一種描述是:編號為1,2,...,n的n個人按順時針方向圍坐一圈,每人持有一個密碼(正整數)。一開始任選一個正整數作為報數上限值m,從第一個人開始按順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向上的下一個人開始重新從1報數,如此下去,直到所有人全部出列為止。試設計一個程式求出出列順序。

基本要求:利用單向迴圈連結串列模擬此過程,按照出列的順序印出各人的編號。

本人完成這道題的時候,用了兩種方法,一種是建立了一個結點Node類,然後在main方法裡面寫;另一種則從題目要考察的角度,另建立了一個迴圈單鏈表的類。

下面-----艱辛的除錯過程,一開始作為菜雞,概念都很模糊,歷經了兩天的。。崩潰。。終於除錯正確!!!

while(head!=null){     for(int i=1;i<=m-2;i++){         head=head.next;     }     int out=head.next.data1;     m=head.next.data2;     System.out.printf("%d\t",out);     head.next=head.next.next; }

 一開始,寫了這樣

一個死迴圈,把電腦卡死了。當最後只有一個或兩個元素的時候,永遠都無法滿足head!=null

後面只要就是運算結果總有問題。還有符號寫錯的問題,,被自己蠢哭 @[email protected]

教訓:

首先,在設變數名的時候,那些比較相像的,比如p  ,q  ,一定要注意,不要寫反了。

然後,把一個結點用“=”賦值給另一個結點時,比如  Node head=L.head ,當後面的操作讓L.head 改變時,head是沒有改變的,一開始我以為是在別的方法裡面對head的改變,不能影響在main 方法的head的值,但對Java進行理解並測試之後, 像這種 結點類的物件,傳遞給方法時,傳遞的是引用,即指標的指向,所以我一開始的猜想是錯的,我真正的錯誤在於,我寫了Node head=L.head 這條語句之後,在後面對連結串列進行一些操作後,L.head變了,但我在main的迴圈是對head操作的,這裡的head是原來賦值時的head,而不是L.head,而我卻以為可以用賦值之後的head代替L.head

public static Node createlist(int n){     Scanner sc=new Scanner(System.in);     System.out.println("請分別輸入各人的密碼");     int code=sc.nextInt();     Node head=new Node(1,code);     Node p=head;     for(int a=2;a<=n;a++){         p=p.next;         code=sc.nextInt();         p=new Node(2,code);     }     p.next=head;     return head; }

用這種方法是無法建立以head為第一個結點的連結串列的

因為,在一開始,head.next=null;那麼 p=head.next;就相當於p==null;而之後p再怎麼新建或往後連結點,都與head無關了。

所以這樣也是錯誤的建表方式。

下面附上我的兩種方法吧

方法1:

package 連結串列;

import java.util.Scanner;

public class yueSeFuRing {

    public static void main(String[] args) {         Scanner sc=new Scanner(System.in);         //使用者設定一個m的初始值         System.out.println("請設定一個m的初始值");         int m=sc.nextInt();         System.out.println("請輸入人數n的值(n<=30):");         int n=sc.nextInt();                  System.out.println("請分別輸入各人的密碼");//3 1 7 2 4 8 4         int code=sc.nextInt();                //正確的出列順序應為6,1,4,7,2,3,5         Node head=new Node(1,code);         Node p=head;         for(int a=2;a<=n;a++){             code=sc.nextInt();             head.next=new Node(a,code);             head=head.next;         }         head.next=p;         head=p;         //遊戲中         Node out;         while(head!=head.next&&head!=null){                          Node p1=head;             Node t=p1;             for(int i=1;i<m;i++){                 t=p1;                 p1=p1.next;             }             out=p1;             if(out==head){                  while(p1.next!=head){                      p1=p1.next;                  }//迴圈完之後,p1.next=head                  p1.next=p1.next.next;                  head=p1.next;              }                 int out1=out.data1;                 m=out.data2;                 System.out.printf("%d\t",out1);             t.next=out.next;             head=t.next;         }         System.out.print(head.data1);     } } class Node{     public int data1;     public int data2;     public Node next;          public Node(){         this(0,0,null);     }

    public Node(int data1,int data2) {         this(data1,data2,null);     }

    public Node(int data1,int data2, Node next) {         this.data1=data1;         this.data2=data2;         this.next=next;     } }

方法2:

package 資料結構;

import java.util.Scanner;

public class ring {

    public static void main(String[] args) {         Scanner sc=new Scanner(System.in);         //使用者設定一個m的初始值         System.out.println("請設定一個m的初始值");         int m=sc.nextInt();         System.out.println("請輸入人數n的值(n<=30):");         int n=sc.nextInt();         //         list L=new list(n);         Node head=L.head;         Node out;         while(L.head!=L.head.next&&head!=null){                          Node p=L.head;             for(int i=1;i<m;i++){                 p=p.next;             }             out=p;             int out1=out.data1;             m=out.data2;             System.out.printf("%d\t",out1);             L.delect(p);         }         System.out.print(L.head.data1);     } }    

 class list{      Scanner sc=new Scanner(System.in);

    static Node head;      //建立一個迴圈單鏈表     public list(){         head=new Node();     }     public list(int n){                  System.out.println("請分別輸入各人的密碼");//3 1 7 2 4 8 4         int code=sc.nextInt();                //正確的出列順序應為6,1,4,7,2,3,5         head=new Node(1,code);         Node p=head;         for(int a=2;a<=n;a++){             code=sc.nextInt();             head.next=new Node(a,code);             head=head.next;         }         head.next=p;         head=p;     }     //求長度     public  int len(){         Node p=head;         if(head==null)             return 0;         else         {             int i;             for(i=1;p.next!=head;i++){                 p=p.next;             }             return i;         }     }     //判斷是否空表     public boolean isEmpty(){         return head==null;     }          //刪除      void delect(Node p){          if(len()==1){             head=null;           }          else{              if(p==head){                  while(p.next!=head){                      p=p.next;                  }//迴圈完之後,p.next=head                  p.next=p.next.next;                  head=p.next;              }              else{                  Node q=head;                  while(q.next!=p){                      q=q.next;                  }                  q.next=q.next.next;                  head=q.next;              }//之後head為被刪除元素的下一下元素          }      } }

 class Node{         public int data1;         public int data2;         public Node next;                  public Node(){             this(0,0,null);         }

        public Node(int data1,int data2) {             this(data1,data2,null);         }

        public Node(int data1,int data2, Node next) {             this.data1=data1;             this.data2=data2;             this.next=next;         }     }