单向循环列表解决约瑟夫(Josepfu)环问题

思路:

核心代码:

public class CircleSingleLinkedList {
    private Person first = null;// 第一个节点

    // 创建一个单项循环列表
    public void add(int nums){
        // 校验一下数据是否合理
        if(nums < 1){
            System.out.println("输入的数据不合理。。");
            return;
        }

        Person cur = null;// 辅助指针,指向当前的节点
        // 创建节点
        for (int i = 1; i <= nums ; i++) {
            // 创建节点
            Person person = new Person(i);

            // 判断节点是否是第一个节点
            if(i == 1) {
                // 添加节点
                first = person;
                first.setNext(person);// 构成环
                cur = first;// 指向当前指针
            }else {
                cur.setNext(person);// 将cur的指向刚刚创建的节点
                person.setNext(first);// 将刚刚创建的节点的next指向第一个节点
                cur = person;// 将cur的指针向后移一位
            }
        }
    }

    // 遍历所有的节点
    public void show() {
        // 判断是否为空
        if(first == null){
            System.out.println("链表为空。。。");
            return;
        }
        Person cur = first;
        while(true){
            System.out.println("编号:"+cur);
            if (cur.getNext() == first) {
                break;// 遍历完毕
            }
            cur = cur.getNext();// cur指向下一个节点
        }
    }

    // 出圈
    /*
    * startNo : 开始的编号
    * countNum : 隔几个输出一次
    * nums : 一共有几个
    */
    public void leave(int startNo,int countNum,int nums){
        if(first == null || startNo > nums || nums < 1) {// 判断是否合法
            System.out.println("参数出入有误");
            return;
        }

        // 将helper指针放在first之前
        Person helper = first;
        for (int i = 0; i < nums ; i++) {
            if(helper.getNext() == first){// 已经找到位置了
                break;
            }
            helper = helper.getNext();
        }
        // 将first和helper移动到指定的位置上去 -- 根据用户输出入的startNo来确定的
        for (int i = 0; i < startNo -1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }

        // 根据countNum来让出圈
        while(true) {
            if(helper == first){// 圈中只有一个节点
                break;
            }
            for (int i = 0; i < countNum - 1; i++) {// 每次循环都是要确定出圈的节点 first即为要出圈的节点
                first = first.getNext();
                helper = helper.getNext();
            }
            // 出圈
            System.out.printf("出圈的节点序号:%d\n",first.id);
            first = first.getNext();
            helper.setNext(first);
        }
        // 以上的出圈会留下最后一位
        System.out.printf("最后一位节点的序号:%d\n",first.id);
    }

}

 节点:

public class Person {
    public int id;
    public Person next;

    public Person(int id) {
        this.id = id;
    }

    public Person getNext() {
        return next;
    }

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

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

测试:

 public static void main(String[] args) {
        CircleSingleLinkedList linkedList = new CircleSingleLinkedList();
        linkedList.add(125);

        linkedList.show();

        linkedList.leave(1,21,125);
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值