约瑟夫环(java环形单链表实现)

问题来历:

约瑟夫问题是个有名的问题:有序号1,2…n个程序员围成一个大圈圈,从编号为K(1<=k<=n)的程序员从1开始报数,数到m的那个程序员出列,可以去挑选对象(真对象,不New不Joke),他的下一位程序员又从1开始报数,数到m的人又出列挑选对象,美滋滋~,依次类推,到最后一个程序员不给对象,只给了一堆bug,并在程序上线的时候祭了天。。。额。。是一个凄美的爱情故事!

思路分析:

构建一个单向环形链表实现:
1.先创建第一个节点,让first指向该节点,并形成环状;
2.后续我们每创建一个新的节点,就把该节点加入到已有的环形链表中;
3.遍历环形链表,先让一个辅助指针cur,指向first节点,然后遍历环形链表,cur.next==first时结束;

出圈顺序分析:
1.需要创建一个辅助指针cur,事先指向环形链表的最后这个节点;
2.程序员报数前,先让first和cur移动k-1次;
3.程序员报数时,让first和cur移动m-1次;
4.这是first指向的节点出圈;

代码实现:

 
public class Josepfu {
    public static void main(String[] args) {
        CircleLinkedList circleLinkedList= new CircleLinkedList();
        circleLinkedList.isAdd(5);
       // circleLinkedList.isShow();
        circleLinkedList.isCount(1,2,5);
      }
 }
//创建一个环形的单项链表
class CircleLinkedList{
      //创建一个first节点
      private Programmer first=null;
      //添加程序员,构成一个环形链表
      public void isAdd(int nums){
          if(nums<1){
              System.out.println("输入值不正确");
              return ;
          }
          Programmer cur =null;  //辅助指针
          //用for循环创建环形链表 
    for (int i = 1; i <=nums ; i++) {
        Programmer programmer = new Programmer(i);
        if(i==1){  //如果为第一个程序员
            first=programmer;
            first.setNext(first);  //一个节点本身构成一个环
            cur = first;  //辅助指针指向第一个程序员
        }else{
            cur.setNext(programmer);
            programmer.setNext(first);  //形成环状
            cur=programmer; //指针后移
        }
    }
}
//遍历环形链表
public void isShow(){
      //先判断链表是否为空
    if(first==null){
        System.out.println("起锅烧油,请放入程序员~");
        return ;
    }
    //first不能动,需要一个辅助变量
    Programmer cur=first;
    while(true){
        System.out.printf("程序员的编号 %d \n",cur.getNo());
        if(cur.getNext()==first){ //遍历完成
             break;
        }
        cur=cur.getNext();
    }
}
//根据输入,计算程序员出圈顺序
/**
 * @param startNo  从第几个程序员开始数
 * @param countNum   数几下
 * @param nums   最初程序员个数
 */
public void isCount(int startNo,int countNum,int nums){
      if(first==null||startNo<1||startNo>nums){
          System.out.println("参数错误");
          return;
      }
      //创建辅助变量帮助程序员出圈,事先指向环形链表的最后一个节点
      Programmer cur =first;
      while(true){
            if(cur.getNext()==first){  //向环形链表的最后一个节点
                 break;
            }
            cur =cur.getNext();
      }
     //程序员报数前,先让first和cur指针同时移动startNo-1次
    for (int i = 0; i 

效果图:
约瑟夫环(java环形单链表实现)_第1张图片

你可能感兴趣的:(java)