约瑟夫环问题(用单循环链表实现)

约瑟夫(Joeph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。试设计一个程序求出出列顺序。

【基本要求】利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号

public class Node {
    int data;            //用来存放每个人手中的数字
    int num;             //用来存放每个人的位置
    Node next;

    public Node() {
    }

    public Node(int data) {
        this.data = data;
    }
}
public class List {
    public static void del(int totalPerson,int[] numbs, int m){
        Node head=new Node();             //新建一个头结点
        Node cur=head;
        Node p=head;
        int i;
        int k=0;
        int[] temps=new int[totalPerson];             //用来存放出列的顺序

        for(i=0;i<totalPerson;i++){                   //把每个人手持的数字放进链表
            Node node=new Node(numbs[i]);             //存放第n个人手中的数据的结点
            cur.next=node;                            //cur连接node
            cur=node;                                 //cur指向node
            cur.num=i+1;                              //给cur.num赋值
        }
        cur.next=head.next;                           //最后一个结点指向头结点的next,头结点不存放数据

        while(p.next!=p){                             //如果p和p.next没在同一个位置,说明出列还没有完成
                for (i = 0; i < m - 1; i++) {         //从0开始,p指向想要出列的前一个位置
                    p = p.next;
                }

                m = p.next.data;                      //更新m的值,把要出列的人手里的数据赋给m
                temps[k]=p.next.num;
                p.next=p.next.next;                   //断开出列的人
                k++;
        }
        temps[totalPerson-1]=p.num;                   //链表的最后一个结点

        System.out.println("出列的顺序是:");
        for(i=0;i<totalPerson;i++){
            System.out.print(temps[i]+" ");
        }}}
import java.io.*;

public class ListTest {
    public static void main(String[] args) throws IOException{
        String inputStr;
        int totalPerson = 0;
        int m=0;
        boolean mark=false;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        do {
            try {
                System.out.println("请输入总游戏人数:");
                inputStr = in.readLine();
                totalPerson = Integer.parseInt(inputStr);
                if (totalPerson <= 0) {
                    throw new NegativeIntegerException();
                }
                mark=true;
            } catch (NumberFormatException | NegativeIntegerException e) {
                System.out.println("非法输入!!!请输入一个正整数!");
            }
        }while(!mark);

        mark=false;
        int[] numbs = new int[totalPerson];
        do {
            try {
                System.out.println("请输入每个人手上持有的数字,敲回车隔开:");
                for (int i=0;i<totalPerson;i++) {
                    inputStr = in.readLine();
                    numbs[i] = Integer.parseInt(inputStr);
                    if (numbs[i] <= 0) {
                        throw new NegativeIntegerException();
                    }
                }
                mark = true;
            } catch (NumberFormatException | NegativeIntegerException e) {
                System.out.println("非法输入!!!请输入一个正整数!");
            }
        }while (!mark);

        mark=false;
        do {
            try {
                System.out.println("请输入首次上限值m:");
                inputStr = in.readLine();
                m = Integer.parseInt(inputStr);
                if (m <= 0) {
                    throw new NegativeIntegerException();
                }
                mark = true;
            } catch (NumberFormatException | NegativeIntegerException e) {
                System.out.println("非法输入!!!请输入一个正整数!");
            }
        }while(!mark);

        List.del(totalPerson,numbs,m);
    }
    private static class NegativeIntegerException extends Throwable {
    }
}

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值