前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >单项环形链表

单项环形链表

原创
作者头像
uglyboy
修改2019-12-23 11:24:27
5120
修改2019-12-23 11:24:27
举报
文章被收录于专栏:用户6831167的专栏

约瑟夫环问题

设编号为1,2,3,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,他的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

思路:

用一个不带头结点的循环链表来处理约瑟夫问题:先构成一个有n个节点单项环形链表,然后由k节点起从1开始计数,到m时,把对应节点从链表中删除,然后再从被删除节点的下一个节点开始从1计数,知道最后一个节点从链表中删除算法结束。

代码示例:

代码语言:javascript
复制
public class Josepfu {
    public static void main(String[] args) {
        SingleCircleLinkedList singleCircleLinkedList = new SingleCircleLinkedList();
        singleCircleLinkedList.Josepfu(1, 2, 5);
    }
}

//创建单项环形链表
class SingleCircleLinkedList {
    //创建一个first节点,当前没有编号
    private Node first;

    /**
     * @param nums 为环形链表添加几个节点
     */
    public void createSingleCircleLinkedList(int nums) {
        if (nums < 1) {
            System.out.println("nums值不正确");
            return;
        }
        Node curNode = null;
        for (int i = 1; i <= nums; i++) {
            //根据编号创建节点
            Node node = new Node(i);
            if (i == 1) {
                first = node;
                first.setNext(first);//构成环
                curNode = first;//让curNode指向第一个节点
            } else {
                curNode.setNext(node);
                node.setNext(first);
                curNode = node;
            }
        }
    }

    /**
     * 遍历当前环形链表
     */
    public void list() {
        if (first == null) {
            throw new RuntimeException("链表为空!");
        }
        Node curNode = first;
        while (true) {
            System.out.println(curNode);
            if (curNode.getNext() == first) {
                break;
            }
            curNode = curNode.getNext();
        }
    }

    /**
     * 根据用户的输入来完成约瑟夫环问题
     *
     * @param startNo  表示从编号几开始数
     * @param countNum 表示数几下
     * @param nums     表示最初有几个人
     */
    public void Josepfu(int startNo, int countNum, int nums) {
        if (nums < 1 || startNo < 1 || startNo > nums) {
            throw new RuntimeException("参数输入有误!");
        }
        createSingleCircleLinkedList(nums);
        Node pre = first;
        //使pre指向first节点的前一个节点
        while (true) {
            if (pre.getNext() == first) {
                break;
            }
            pre = pre.getNext();
        }
        //使first和pre先移动到一开始报数的人那里
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            pre = pre.getNext();
        }
        //当第一个人开始报数时,让first和pre指针同时开始移动countNum-1此,然后first指向的节点出圈
        while (true) {
            if (first == pre) {
                break;
            }
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                pre = pre.getNext();
            }
            //这时first指向的节点就是要出圈的节点
            System.out.println(first);
            first = first.getNext();
            pre.setNext(first);
        }
        //退出循环后,圈中就只剩下一个节点了。
        System.out.println(first);
    }
}

class Node {
    private int no;

    private Node next;

    public Node(int no) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Node getNext() {
        return next;
    }

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

    @Override
    public String toString() {
        return "Node{" +
                "no=" + no +
                '}';
    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 约瑟夫环问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档