java单向链表详解约瑟夫问题

/*
* 环形链表【这里展示单环形链表】
* 无非就是每添加一个节点到最后。head节点的pre指向最后一个节点
* 或者是: 最后每添加一个节点的next域都会指向head节点
* 这里利用环形链表解决 约瑟夫问题::
* ---> 设有n的人围成一个环。约定编号为k(1<=k<=n)的人从1开始报数。数到m的那个人出列。出列的下一个人继续从k开始报数
* ---> 直到只有最后一个人。拿到由此产生的一个出列编号的 序列!
* n  k  m
* */
public class AnnualLinkedList {
    public static void main(String[] args) {
        ManagerAnnualNode ma = new ManagerAnnualNode();
        int n=125;
        //添加n个 人/数据
        for(int i=1;i<=n;i++){
           ma.addNode(new AnnualNode(i));
        }

        int[] arr=ma.ergodic(n,10,20);
        for(int data:arr){
            System.out.print(data+"-->\t");
        }
    }
}
/*
* 默认输入的数据遵守规则
* */
class  ManagerAnnualNode{
    final static Scanner sc=new Scanner(System.in);
    private AnnualNode head=null;//第一个节点
    private AnnualNode lastNode=null;//辅助指针
    //环形添加 因为设定为是不带头节点的单向环形链表。所以要对它的第一个节点进行特殊处理
    public void addNode(AnnualNode node){
        if(head==null){
            head=node;
            head.next=head.next;//集成显示是自身给自身赋值 也可以head.next=node。但是我觉得这样写更加直观
        }else {
            //标记上一次节点的next域为添加的node
            lastNode.next=node;
            //最后一个节点永远指向head节点
            node.next=head;
        }
        //标记每一次添加的节点。
        lastNode=node;
    }
    
    //求出所有出来的顺序
    public int[] ergodic(int n,int k,int m){
        int[] arr=new int[n];
        //找到从指定编号k的开始【因为是单向环形链表 所以要 是k-1的那一个编号  不然不好删除节点
        AnnualNode kNode=first(k);
        int count=1;
        int index=0;
        while (true){
            //不管怎么样每循环一次都需要指向下一个节点
            kNode=kNode.next;
            count++;
            //满足m条件表示该出链表了
            if(count==m){
                arr[index++]=kNode.next.id;
                //从链表中删除已经出列的节点
                kNode.next=kNode.next.next;
                count=1;
            }
            //当只剩下一个数的时候就会成立这个条件
            if(kNode==kNode.next){
                arr[index++]=kNode.id;
                break;
            }
        }
        return arr;
    }
    //找到满足条件的前一个节点
    public AnnualNode first(int id){
        if(head==null){
            System.out.println("没有数据可以遍历");
            return null;
        }
        AnnualNode tmp=head;
//        AnnualNode judge=head;
        while (true){
            if(tmp.next.id==id)break;
             tmp=tmp.next;
//             if(judge==head)throw new RuntimeException("不存在这个数据");//默认认为这个数一定存在
        }
        return tmp;
    }
}
class AnnualNode{
    int id;
    AnnualNode next;
    public AnnualNode() {}
    public AnnualNode(int id) {
        this.id = id;
    }
}

记录

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值