java简易实现约瑟夫问题(易懂)

该博客演示了一个Java程序,实现了一个环形链表的数据结构,并提供了添加节点、列出所有节点以及按照特定规则移除节点的功能。核心操作包括创建环形链表、遍历打印链表以及执行'报数出圈'的游戏逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class Test_CircleList {
    public static void main(String[] args) {
        CircleList c = new CircleList();
        c.addBoy(5);
        c.list();
        c.popBoy(1,2,5);
    }
}


class Boy{
    private int id;
    private Boy next;
    public Boy(){}
    public Boy(int id){
        this.id = id;
    }

    public void setNext(Boy next) {
        this.next = next;
    }

    public Boy getNext() {
        return next;
    }

    @Override
    public String toString() {
        return "Boy{"+"id="+id +'}';
    }
}



class CircleList{
    private Boy first = new Boy();

    /**
     * @param nums 小孩数量
     */
      public void addBoy(int nums){
          Boy temp = new Boy();
          if(nums<1){
              System.out.println("无意义!");
          }else{
          while(true){
              for(int i =1;i<=nums;i++){
                  Boy note = new Boy(i);
                  // 注意:这里头节点(first)不为空   环形数组是要空出一个变量  这里不需要
           
                  if(i == 1){
                      first = note;
                      note.setNext(first);  // next指向调整为指向头元素
                      temp = first;
                  }else{
                      temp.setNext(note);
                      temp = note;
                      note.setNext(first);    // next指向调整为指向头元素
                  }
              }
              break;
          }
          }
      }


      public void list(){
          Boy temp = first;
          while(true){
              System.out.println(temp);
              if(temp.getNext() == first){
                  break;
              }else{
                  temp = temp.getNext();
              }
          }
      }

    /**
     *
     * @param startno  指定的第一个小孩的位置
     * @param countNum  要传递的次数
     * @param nums  小孩的总人数
     */

      public void popBoy(int startno,int countNum,int nums){
          //先判断有没有执行的必要
          if(startno<1||startno>nums||first==null){
              System.out.println("出错了");
              return;
          }
          //辅助节点很重要,因为是单链表,所以需要使用一个辅助接点就对接前一个元素
          Boy temp = first;
          //将辅助节点进行遍历,对接到first元素的前一个元素
          for(int i =0;i<nums;i++){
              if(temp.getNext()==first){
                  break;
              }else{
                  temp = temp.getNext();
              }
          }
          //将两个节点移动到指定的开始小孩的元素上  
          //first在指定的元素上 temp在他的前一个元素上 这里的重点是执行n-1次
          for(int i =0;i<startno-1;i++){
              first = first.getNext();
              temp = temp.getNext();
          }
          //如果temp和first指向同一个元素,那么就代表只剩下最后一个环形链表元素
          while(true){
              if(temp == first){
                  break;
              }
              //这里同样是只移动N-1次
              for(int j=0;j<countNum-1;j++){
                  first = first.getNext();
                  temp = temp.getNext();
                  }

              System.out.println("出圈的小孩编号为:"+first);
              //将出圈小孩删除的操作  
              //就是将temp(也就是first的前一个元素)的next域指向出圈小孩的下一个小孩
              first = first.getNext();
              temp.setNext(first);


              }
          System.out.println("最后一个小孩编号为:"+first);
          }
      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值