关键词

java使用链表实现约瑟夫环

Java使用链表实现约瑟夫环

什么是约瑟夫环

约瑟夫环(Josephus problem)是一个有名的问题。传说中,约瑟夫和他的39个朋友圈在一个洞穴中,被罗马军队包围。他们决定集体死了,不肯去做罗马的奴隶。约瑟夫是一个退役士兵,提议从一个人开始,每隔三个人就杀掉一个人。由他开始,最后剩下一个人,他可以叫作胜利。现在问你,应该站在哪个位置,才能够成为那个幸存者?

链表的基本概念

链表是一种常见的数据结构,它由若干个节点(node)组成,每个节点包含两部分:数据域和指针域。其中数据域保存节点的数据,指针域保存下一个节点的地址。链表的头指针指向链表的第一个节点,链表最后一个节点的指针域指向空地址(NULL)。

思路

由于约瑟夫环问题中每个人被杀死后需要从圈中删除,所以我们可以用一个链表表示这个圆圈。第一步,我们先将 $n$ 个人的编号从 $1$ 到 $n$ 建立起来,然后将它们构成一个单向循环链表。

第二步,从第 $k$ 个人开始报数,记为 $m$。然后移动 $m-1$ 个节点,对应的节点即为要删除的节点。删除节点后,重新从当前节点开始报数,直到剩下最后一个节点为止。

Java代码实现

class Node {
    public int value;
    public Node next;

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

public class CircleLinkedList {

    public static Node create(int n) {
        Node head = new Node(1);
        Node p = head;
        for (int i = 2; i <= n; i++) {
            p.next = new Node(i);
            p = p.next;
        }
        p.next = head;
        return head;
    }

    public static void josephus(Node head, int k, int m) {
        Node p = head;
        for (int i = 0; i < k - 1; i++) { // 找到起始节点
            p = p.next;
        }
        while (p.next != p) { // 当链表只有一个节点时结束
            for (int i = 0; i < m - 1; i++) {
                p = p.next;
            }
            System.out.print(p.next.value + " "); // 输出要删除的节点的下一个节点
            p.next = p.next.next; // 删除该节点
        }
        System.out.println("\n剩余节点:" + p.value);
    }

    public static void main(String[] args) {
        int n = 10;
        int k = 3;
        int m = 5;
        Node head = create(n);
        System.out.println("链表中节点的编号依次为: ");
        for (int i = 1; i <= n; i++) {
            System.out.print(head.value + " ");
            head = head.next;
        }
        System.out.println("\n按照约瑟夫环的规则,出列的顺序为:");
        josephus(head, k, m);
    }
}

示例说明

示例一

假设有 $n = 5$ 个人,从第 $k = 1$ 个人开始报数,每报数到 $m = 2$ 个人将删除一个人,输出约瑟夫环的过程如下:

链表中节点的编号依次为: 
1 2 3 4 5 
按照约瑟夫环的规则,出列的顺序为:
2 4 1 5 
剩余节点:3

示例二

假设有 $n = 10$ 个人,从第 $k = 3$ 个人开始报数,每报数到 $m = 4$ 个人将删除一个人,输出约瑟夫环的过程如下:

链表中节点的编号依次为: 
1 2 3 4 5 6 7 8 9 10 
按照约瑟夫环的规则,出列的顺序为:
4 8 2 7 3 10 1 9 6 
剩余节点:5

注意:以上示例中生成链表时编号从 $1$ 到 $n$,要输出约瑟夫环的过程还需要遍历整个链表输出每个节点的编号。实际的应用场景中,可以根据业务需求设计节点的数据域。

本文链接:http://task.lmcjl.com/news/13039.html

展开阅读全文