看到网上很多示例编写的代码都不够精练简洁,现对“约瑟夫问题”用JAVA实现如下:
/**
* 使用环形链表实现约瑟夫问题
*/
class RoundLinked{
//头节点
private Node<Integer> head=new Node<>();
//尾节点
private Node<Integer> tail=head;
private int size=0;
public RoundLinked(int nums){
make(nums);
this.size=nums;
}
public boolean empty(){
return head==tail;
}
/**
*
* @param k 从第几个开始计数
* @param count 到第几个的时候重新开始数
*/
public void Josephus(int k,int count){
if(empty()){
return;
}
if(k>=size){
System.out.println("k的值不合法");
return;
}
//1.旋转到第k个节点
int tmpIndex=1;
do {
if(k==tmpIndex){
break;
}
head=head.next;
tail=tail.next;
tmpIndex++;
}while (true);
for (;;){
if(empty()){
break;
}
//2.开始丢手帕
for (int i = 0; i < count; i++) {
head=head.next;
tail=tail.next;
}
System.out.println("死掉:"+head);
//跳过当前节点
head= head.next;
//重连
tail.next=head;
}
//3.留在队列当中的
System.out.println("幸存:"+head);
}
private void make(int nums){
if(nums<1){
System.out.println("创建的节点不能为空!");
return;
}
for (int i = 0; i < nums; i++) {
Node<Integer> node=new Node<Integer>(i+1);
tail.next=node;
tail=tail.next;
}
//将空节点去掉
head=head.next;
//首尾相连
tail.next=head;
}
public void ls(){
if(empty()) return;
Node<Integer> cur=head;
do {
System.out.println(cur);
cur=cur.next;
}while (cur!=head);
}
static class Node<T>{
public T data;
public Node<T> next;
public Node(){
this(null);
}
public Node(T data,Node<T> next){
this.data=data;
this.next=next;
}
public Node(T data){
this(data,null);
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
'}';
}
}
}
测试:
public class RoundLinkedDemo {
public static void main(String[] args) {
RoundLinked linked=new RoundLinked(10);
linked.Josephus(1,1);
}
}
结果:
死掉:Node{data=2}
死掉:Node{data=4}
死掉:Node{data=6}
死掉:Node{data=8}
死掉:Node{data=10}
死掉:Node{data=3}
死掉:Node{data=7}
死掉:Node{data=1}
死掉:Node{data=9}
幸存:Node{data=5}
发博客真好玩儿._.