约瑟夫环是个很经典的问题,其中一个简单的实现方式使用环形链表。在这篇文章中,将用环形链表简单的解决这个问题。
我们首先来看一个环形的链表结构
在这个结构中我们定义了一个并不存储数据的虚拟头结点。然后把链表收尾相连,这样就形成了一个环形的循环结构。
构建环形链表很简单,我们先定义一个链表的基本结构
class Node {
int data;
Node next;
public Node() {
}
public Node(int data) {
this.data = data;
}
}
然后构造链表
Node head = new Node();
Node cur = head;
//构造链表
for (int i = 1; i <= n; i++) {
Node node = new Node(i);
cur.next = node;
cur = node;
}
cur.next = head.next; //首位连接形成环形链表
Node pre = head.next;
现在就完成了一个循环链表了
然后我们就要遍历链表删除节点例如我们数到k就删除节点就会有如下代码
while (pre.next != pre) {
for (int i = 1; i < k - 1; i++) {
pre = pre.next;
}
System.out.print(pre.next.data + "->");
pre.next = pre.next.next;
pre = pre.next;
}
我们假设k是3这也是约瑟夫的问题中的例子,那么for循环中我们循环了1次。此时pre指向要被删除的节点的前一个节点。然后执行我们的删除逻辑就可以了。
当满足while 的终止条件时,整个循环链表也只剩下一个节点。这就是我们最后剩下的节点。
整体代码如下:
public class yuesefuhuan {
public static void main(String[] args) {
count(41, 3);
}
public static void count(int n, int k) {
Node head = new Node();
Node cur = head;
//构造链表
for (int i = 1; i <= n; i++) {
Node node = new Node(i);
cur.next = node;
cur = node;
}
cur.next = head.next; //首位连接形成环形链表
Node pre = head.next;
//开始遍历节点
while (pre.next != pre) {
for (int i = 1; i < k - 1; i++) {
pre = pre.next;
}
System.out.print(pre.next.data + "->");
pre.next = pre.next.next;
pre = pre.next;
}
System.out.println("zuihou:" + pre.data);
}
}
class Node {
int data;
Node next;
public Node() {
}
public Node(int data) {
this.data = data;
}
}
执行以下结果为: 3->6->9->12->15->18->21->24->27->30->33->36->39->1->5->10->14->19->23->28->32->37->41->7->13->20->26->34->40->8->17->29->38->11->25->2->22->4->35->16->zuihou:31
符合约瑟夫问题的例子。