[Java数据结构-1]用环形链表解决约瑟夫问题

约瑟夫问题为:设编号为1,2,……n得n个人围坐一圈,约定编号为k(k大于等于1并且小于等于n)的人从1开始报数,数到m的那个人出列。它的下一位继续从1开始报数,数到m的人出列,依次类推,直到所有人都出列为止。

1.定义Node类

class Node{
    public int no;//编号
    public Node next;//下一个节点

    public Node(int no){
        this.no = no;
    }

    @Override
    public String toString() {
        return "Node{" +
                "no=" + no +
                '}';
    }
}

2.定义CircleLinkedList类

class CircleLinkedList{
    public Node first;//第一个节点
	
	//构造方法
    public CircleLinkedList(Node first) {
        this.first = first;
        first.next = first;
    }


    /**
     * 添加节点 每次都是将节点插入first节点和其之前的节点之间
     * @param insertNode 插入的节点
     */
    public void add(Node insertNode){
        Node temp = first;

        //寻找first之前的节点,即如果发现temp的下一个节点是first就结束循环
        while (temp.next != first){
            temp = temp.next;
        }
        //这里的temp是first之前的节点
        temp.next = insertNode;
        insertNode.next = first;
    }

}

3.定义CircleLinkedListDemo类

public class CircleLinkedListDemo {
    public static void main(String[] args) {
        //约瑟夫问题
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入n(人数):");
        int n = scanner.nextInt();
        System.out.println("请输入k(从第几个开始报数):");
        int k = scanner.nextInt();
        System.out.println("请输入m(数几个):");
        int m = scanner.nextInt();

        //1.根据n创建循环链表
        CircleLinkedList list = new CircleLinkedList(new Node(1));
        for (int i = 2; i < n+1; i++) {
            list.add(new Node(i));
        }

        //2.定位到第一个数数的人。以及temp之前的节点(为了删除节点)
        Node temp = list.first;
        Node tempLast = list.first;
        for (int i = 1; i < k; i++){
            tempLast = temp;
            temp = temp.next;
        }

        //3.开始数数,删除出队列的人节点
        int countN = 0;//记录出队列的人数,当count==n即结束while循环
        int countM = 1;//记录数数的数字
        while (countN != n) {
            //一、每一轮循环开始之前先进行判断:
            // 1.判断是否出队列人数已满(countN == n) 2.此节点是否符合出队列的要求(countM == m)
            if (countM == m) {
                //删除此节点,输出此节点的编号,并且将countM=0
                System.out.print(temp.no + "->");
                tempLast.next = temp.next;
                countN++;
                countM = 0;
            }

            //二、将temp的值变成下一个节点,然后进行countM++
            tempLast = temp;
            temp = temp.next;
            countM++;
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值