循环单链表完成约瑟夫环.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

后面只要就是运算结果总有问题。还有符号写错的问题,,被自己蠢哭 @-@

教训:

首先,在设变量名的时候,那些比较相像的,比如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;
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_41635653/article/details/83047419