JAVA数据结构-04 单向环形链表解决约瑟夫问题

JAVA数据结构-04 单向环形链表解决约瑟夫问题

问题描述:num个人围成一圈,从第start个开始报数,第k个出圈,最后剩下一个,求出圈的顺序。

构建一个单向环形链表

思路:

  • 先创建第一个节点,让这个节点的next指针域指向自己,并形成环形
  • 后面当我们每创建一个新的节点,就把该节点,加入到已有的环形链表即可
  • 遍历时判断遍历一圈结束的条件.temp.next == first

数据节点:

class Child{
    
    
    public int no;
    public Child next;

    public Child(int no) {
    
    
        this.no = no;
    }
    @Override
    public String toString() {
    
    
        return "Child{" +
                "no=" + no +
                '}';
    }
}

构建单向环形链表结构:

class CircleSingleLinkedList{
    
    
    //创建第一个节点
    Child first;
    //添加指定个数的节点
    public void addChile(int num){
    
    
        if(num <1 ){
    
    
            System.out.println("num 错误");
            return ;
        }
        //创建一个单节点环形链表
        first = new Child(1);
        first.next = first;
        //添加指定个数的元素
        Child temp = first;
        for (int i = 2; i <= num ; i++) {
    
    
            Child child = new Child(i);
            temp.next = child;
            child.next = first;
            temp = temp.next;
        }
    }

    //遍历一圈
    public void showList(){
    
    
        if(first == null){
    
    
            System.out.println("链表为空");
            return ;
        }
        Child temp = first;
        while (true){
    
    
            System.out.println(temp);
            if(temp.next == first) break;
            temp = temp.next;
        }
    }
}

根据k值,完成出圈的顺序

思路:

  • 因为单向链表删除节点(出圈)时,需要将指针指向待删除节点的前一个位置.
  • 因此需要创建一个辅助指针temp,指向报数小孩的前一个位置.所以初始化时,temp指向first指针的前一个位置(环形队列的最后一个元素).
    • 再将temp移动start-1个位置,移动到开始报数的元素的前一个位置
  • 当小孩报数时,让temp指针向前移动k-1个单位,到达预删除节点的前一个位置,这时让节点出圈
    • temp.next=temp.next.next;
  • 当链表中只有一个节点,此时temp=temp.next, 此时循环结束,将队列中最后一个节点出圈.
/**
 *
 * @param start 从第几个位置开始
 * @param k    数几下
 * @param num   有多少小孩
 */
public void excuteJosephu(int start,int k,int num){
    
    
    //添加小孩
    addChile(num);
    //
    System.out.println("出圈前队列:");
    showList();
    //初始化:让temp指向 start的前一个位置(队列末尾)
    Child temp = first;
    while (temp.next != first){
    
    
        temp = temp.next;
    }
    for (int i = 0; i < start-1 ; i++) {
    
    
        temp = temp.next;
    }
    //
    System.out.println("开始出圈:");
    while(true){
    
    
        if(temp.next == temp) break; //当链表中只有一个值时结束寻新欢
        for (int i = 0; i <k-1 ; i++) {
    
    
            temp = temp.next;
        }
        //将temp节点的下一个节点出圈
        Child out = temp.next;
        temp.next = temp.next.next;
        System.out.println("出圈节点"+out);
    }
    //将循环链表中最后一个元素出圈
    System.out.println("最后出圈节点"+temp);
}

猜你喜欢

转载自blog.csdn.net/weixin_44634197/article/details/108430655