约瑟夫问题(单向循环链表经典例题)

1. 约瑟夫问题的简介及实现思路
  • Josephu(约瑟夫、约瑟夫环)问题:

    设编号1,2,…,n 的 n 个人围坐一圈,约定编号为 k (1 <= k <= n)的人从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

  • 大致实现思路:

    1. 将所有人添加到循环链表中
    2. 然后由k结点起从1开始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除,算法结束
  • 实现图解:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3RLbGKVh-1583408688359)(C:\Users\Despicable_Me\Desktop\1583408091(1)].jpg)

  • 单向循环链表的实现:

    请见上篇博客

  • 玩家类的实现:

    public class GamePlayer {
        private String name;
        private int age;
    
        public GamePlayer(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "GamePlayer{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
2. 约瑟夫问题的代码实现:
import java.util.Scanner;

public class Josephus {
    public static void main(String[] args) {
        //循环链表
        CircularLinkedList list = new CircularLinkedList();

        //先来十个玩游戏的人
        GamePlayer player1 = new GamePlayer("玩家一", 10);
        GamePlayer player2 = new GamePlayer("玩家二", 11);
        GamePlayer player3 = new GamePlayer("玩家三", 12);
        GamePlayer player4 = new GamePlayer("玩家四", 13);
        GamePlayer player5 = new GamePlayer("玩家五", 14);
        GamePlayer player6 = new GamePlayer("玩家六", 15);
        GamePlayer player7 = new GamePlayer("玩家七", 16);
        GamePlayer player8 = new GamePlayer("玩家八", 17);
        GamePlayer player9 = new GamePlayer("玩家九", 18);
        GamePlayer player10 = new GamePlayer("玩家十", 19);

        //把这十个人存到结点里,并加入到链表里
        CircularNode node0 = new CircularNode(player1);
        list.add(node0);
        CircularNode node1 = new CircularNode(player2);
        list.add(node1);
        CircularNode node2 = new CircularNode(player3);
        list.add(node2);
        CircularNode node3 = new CircularNode(player4);
        list.add(node3);
        CircularNode node4 = new CircularNode(player5);
        list.add(node4);
        CircularNode node5 = new CircularNode(player6);
        list.add(node5);
        CircularNode node6 = new CircularNode(player7);
        list.add(node6);
        CircularNode node7 = new CircularNode(player8);
        list.add(node7);
        CircularNode node8 = new CircularNode(player9);
        list.add(node8);
        CircularNode node9 = new CircularNode(player10);
        list.add(node9);

        Scanner sc = new Scanner(System.in);
        System.out.println("请输入从第几个人开始游戏...(1-10)");
        int k = sc.nextInt();
        System.out.println("请输入报数的数字...");
        int m = sc.nextInt();
        //模拟一个计数器
        int count = 1;
        //如果圈内还有两个人及两个人以上,那么游戏继续
        while (list.getSize()!=1){
            //首先求出要出列的人对应的索引
            int index = (m+k-2)%list.getSize();
            //根据索引拿到该索引对应的玩家信息
            GamePlayer player = (GamePlayer) list.getByIndex(index).data;
            //根据索引删掉此索引对应的玩家,表明他已出列
            list.delByIndex(index);
            System.out.println("第"+(count++)+"个玩家已出列,他是:"+player);
            //修改 k 的值,下次从已出列的下一个人开始计数
            k = index+1;
        }
        //求出最后一个出列的玩家
        GamePlayer lastPlayer = (GamePlayer) list.getByIndex(0).data;
        //删除最后一个玩家,表示他也已经出列
        list.delByIndex(0);
        System.out.println("第10个玩家已出列,他是:"+lastPlayer);

    }
}
3. 结果展示:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值