环形链表解决约瑟夫问题

环形链表

构造图

在这里插入图片描述

经典应用

约瑟夫问题

设编号为1,2,… n的n个同学围坐在一起形成一个圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,下一个人又从1开始报数,以此类推,直到所有人出列为止,产生一个出队编号。

思路

  • 利用环形链表这种结构模拟n个同学围成一圈
  • 通过链表的删除算法,模拟数到m的那个人出列
  • 剩下最后一个节点则循环结束,无需在移除
class Stu{    //链表节点
    private int data;
    private Stu next;

    public Stu(){}
    public Stu(int data){
        this.data = data;
    }
    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
    public void setNext(Stu next) {
        this.next = next;
    }
    public Stu getNext() {
        return next;
    }
}
class StudentLinked{ //链表

    //根据n构造环形队列,返回入口节点
    public Stu createLinked(int n){
        Stu head = new Stu(1);
        Stu op = head;
        for(int i =2;i<=n;i++){
            Stu stu = new Stu();
            stu.setData(i); //编号
            op.setNext(stu);
            op = stu;
        }
        op.setNext(head);
        return head;
    }
    //移除op对应节点
    public void removeLinked(Stu op,Stu op_pre){
        if(op == null || op_pre == null) throw new RuntimeException("空指针");
        if(op == op_pre) throw new RuntimeException("链表仅剩最后一个节点");
        op_pre.setNext(op.getNext());
        op.setNext(null);
    }
}
public class Test {
		//函数调用
    public static void main(String[] args) {
        StudentLinked lined = new StudentLinked();
        YSF_issue(lined,5,1,3);
    }
  
  	//具体解决函数
    public static void YSF_issue(StudentLinked entrance,int n,int k,int m){
        Stu op = entrance.createLinked(n);
        Stu op_pre = op;
        //确定op指针位置(op:需要删除的那个节点)
        while(op.getNext() != null){
            if(op.getData() == k)break;
            op = op.getNext();
        }
        //确定op_pre指针位置(op_pre:需要删除的那个节点的前一个节点)
        while(op_pre.getNext() != null){
            if(op_pre.getNext() == op) break;
            op_pre = op_pre.getNext();
        }
        //op = op_pre时 则只剩下一个节点
        int pos = 0;
        while(op!=op_pre){
            if(++pos == m){
                System.out.print(op.getData()+"  ");//打印模拟出队
                entrance.removeLinked(op,op_pre);
                op = op_pre.getNext();
                pos = 0;
            }else {
                op_pre = op_pre.getNext();
                op = op.getNext();
            }
        }
        System.out.print(op.getData());//最后一个人出队
    }
}

假设5个同学围成一圈,从k=1这个编号的人开始从1报数,报数等于(m=3)的时候出队,继续下一个从1开始报数。

最终得出一个队列为 3 1 5 2 4

回答: 环形链表约瑟夫问题是指给定一个环形链表,从链表中的某个节点开始,按照一定规则进行报数并删除节点,直到所有节点都被删除。具体的解决方法是使用一个不带头结点的循链表来处理。首先构建一个有n个节点的单循链表,然后从指定的节点开始,按照规定的报数规则进行计数,当计数到达指定数值m时,删除对应的节点。然后从被删除节点的下一个节点重新开始计数,直到最后一个节点被删除,算法结束。遍历环形链表可以通过一个辅助指针curBoy来实现,通过一个while循遍历链表,直到curBoy.next等于链表的头节点结束。生成一个出圈顺序可以通过创建一个辅助指针helper来实现,首先让helper指针移动m-1次,然后将指向的节点出圈。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [用环形链表解决约瑟夫问题](https://blog.csdn.net/yunhech/article/details/107444728)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【数据结构+算法环形链表——约瑟夫(Josephu)问题](https://blog.csdn.net/m0_45097186/article/details/104227805)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值