迴圈單鏈表完成約瑟夫環.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; } }