约瑟夫问题-java

package com.yang.list;

/**
 * 约瑟夫问题:关键在于 如何创建一个单向环形链表和遍历环形链表
 */
public class RingLinkList {

    public static void main(String[] args) {
        Node first=getRingLinklist(41);
        showRingLinkList(first);
        System.out.println();
        System.out.println("出圈的循序为:");
        josephusSolve(first,1,3,41);
    }

    /**
     * 构建单向循环链表
     * @param num:结点数的总数
     * @return :返回单向循环链表的头结点(自己认为的开始的那个结点)
     */
    public static Node getRingLinklist(int num){

        //创建一个结点,定为头结点(这个结点不会移动),先不给初始值,当我们开始循环创建结点时,给予。
        Node first=null;
        //创建一个辅助结点curNode,用于插入新的结点
        Node curNode=null;

        //判断结点数是否有效
        if(num<1){
            System.out.println("结点个数无效。。。");
            return null;
        }
            //循环,构建单向循环链表
           for(int i=1;i<=num;i++){
               //创建结点
               Node node=new Node(i);
               //判断是否为第一个结点
               if(i==1){
                   first=node;
                   first.next=first;
                   curNode=first;
               }else {
                   //插入后面新生成的结点,够成环
                   curNode.next=node;
                   node.next=first;
                   curNode=node;
               }
           }
        return first;
    }

    /**
     * 打印单向循环链表
     * @param first:我们自己认为的头结点
     */
    public static  void showRingLinkList(Node first){
        //定义辅助指针遍历链表
        Node surNode=first;
        //判断是否为空链表
        if(first==null) return;
        //开始遍历
        while (true){
            //输出每个结点的数据
            System.out.print(surNode.item+" ");
            //判断结束条件
            if(surNode.next==first) break;
            else surNode=surNode.next;
        }
    }

    /**
     * 约瑟夫问题解决
     * @param first:我们认为的那个头结点
     * @param startNode:从哪个结点开始报数
     * @param count:每次报多个(意思是多少个数为一个循环)
     * @param num:一共多少个结点
     */
    public static void josephusSolve(Node first,int startNode,int count,int num){
        //判断是否为空链表,设置的count是否合理
        if(first==null||count<1)return;
        //设置一个指针,辅助遍历,它需要指向尾结点(相对于我认为的开始的那个头结点)
        Node last=null;
        //定义一个辅助指针,帮助我们将lastNode指向尾结点
        Node temp=first;
        //指向尾结点
        while (true){

            if(temp.next==first){
                last=temp;
                break;
            }
            temp=temp.next;
        }
        //将first、last移动startNode-1次,让它们到达开始数的位置
        for(int i=0;i<startNode-1;i++){
            first=first.next;
            last=last.next;
        }
        //报数出圈是一个循环的事情,当first=last时,剩下一个结点,循环结束。
        while (true){

            //开始数,移动count-1次
            for(int j=0;j<count-1;j++){
                first=first.next;
                last=last.next;
            }

            //此时first指向的结点就是这一次出圈的结点,先打印这个结点的值,然后让first指向的结点出圈
            System.out.print(first.item+" ");            //打印
            first=first.next;                            //出圈
            last.next=first;
            //判断是否还剩一个结点,是的话,循环结束
            if(first==last) {
                System.out.println(first.item);
                break;
            }
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值