约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。
1.用单链表实现
package com.cws.joseph; import java.util.Date; public class JosephCircle { /** * 作者: * 功能:约瑟夫环 * 用单链表实现 */ public static void main(String[] args){ NodeLink link = new NodeLink(); // link.setLen(5); System.out.println("开始创建"+new Date()); link.createLink(1000000); System.out.println("创建结束"+new Date()); // link.test(); link.setK(1000); link.setM(1000); System.out.println("开始游戏"+new Date()); link.play(); System.out.println("游戏结束"+new Date()); } } class Node{ private long no; private Node nextNode; public long getNo() { return no; } public void setNo(long no) { this.no = no; } public Node getNextNode() { return nextNode; } public void setNextNode(Node nextNode) { this.nextNode = nextNode; } public Node(long no){ this.no=no; } } class NodeLink{ private Node firstNode; private Node temp; private Node temp2; private long len; private long k;//第几个人开始报数 private long m;//每次报多少数 public Node getTemp2() { return temp2; } public void setTemp2(Node temp2) { this.temp2 = temp2; } public long getK() { return k; } public void setK(long k) { this.k = k; } public long getM() { return m; } public void setM(long m) { this.m = m; } public void createLink(long len){ this.len = len; for(long i = 1;i<=len;i++){ if(i==1){ Node node = new Node(i); firstNode = node; temp = node; }else if(i != 1 && i != len){ Node node = new Node(i); temp.setNextNode(node); temp = node; }else{ Node node = new Node(i); temp.setNextNode(node); temp = node; temp.setNextNode(firstNode); } } } public void test(){ for(long i =0;i<this.len;i++){ if(i==0){ temp=firstNode; } System.out.println(temp.getNo()); temp = temp.getNextNode(); } } public void play(){ temp = firstNode; //先找到第一个报数的人 for(long i = 1;i<k;i++){ temp = temp.getNextNode(); } while(this.len != 1){ //找到要出列的人 for(long i=1;i<m;i++){ if(i==(m-1)){ temp2 = temp; } temp = temp.getNextNode(); } //让要出列的人出列 temp2.setNextNode(temp.getNextNode()); temp = temp.getNextNode(); this.len--; } System.out.println("最后一个出列的是"+temp.getNo()); } public Node getFirstNode() { return firstNode; } public void setFirstNode(Node firstNode) { this.firstNode = firstNode; } public Node getTemp() { return temp; } public void setTemp(Node temp) { this.temp = temp; } public long getLen() { return len; } public void setLen(long len) { this.len = len; } }
2.用双链表解决
package com.cws.joseph; import java.util.Date; public class JosephCircle_2 { /** * 作者: * 功能:约瑟夫环 * 用双向链表实现 */ public static void main(String[] args) { // TODO Auto-generated method stub DoubleLink doubleLink = new DoubleLink(); System.out.println("开始创建"+new Date()); doubleLink.createDoubleLink(1000000); System.out.println("创建结束"+new Date()); // doubleLink.testlast(); doubleLink.setK(1000); doubleLink.setM(1000); System.out.println("开始游戏"+new Date()); doubleLink.play(); System.out.println("游戏结束"+new Date()); } } class DoubleNode{ private long no; private DoubleNode lastNode; private DoubleNode nextNode; public long getNo() { return no; } public void setNo(long no) { this.no = no; } public DoubleNode getLastNode() { return lastNode; } public void setLastNode(DoubleNode lastNode) { this.lastNode = lastNode; } public DoubleNode getNextNode() { return nextNode; } public void setNextNode(DoubleNode nextNode) { this.nextNode = nextNode; } public DoubleNode(long no){ this.no = no; } } class DoubleLink{ private long len; private DoubleNode firstNode; private DoubleNode lastNode; private DoubleNode temp; private DoubleNode temp2; private long k;//第几个人开始报数 public long getK() { return k; } public void setK(long k) { this.k = k; } public long getM() { return m; } public void setM(long m) { this.m = m; } private long m;//每次报多少数 public long getLen() { return len; } public void setLen(long len) { this.len = len; } public DoubleNode getFirstNode() { return firstNode; } public void setFirstNode(DoubleNode firstNode) { this.firstNode = firstNode; } public void createDoubleLink(long len){ this.len = len; for(long i=1;i<=len;i++){ if(i == 1){ DoubleNode doubleNode = new DoubleNode(i); firstNode = doubleNode; temp = doubleNode; temp2 = doubleNode; }else if(i !=1 && i !=len){ DoubleNode doubleNode = new DoubleNode(i); temp.setNextNode(doubleNode);//设置上个的下一个 temp = doubleNode;//移动到当前 temp.setLastNode(temp2);//设置当前个的上一个 temp2 = doubleNode; }else{ DoubleNode doubleNode = new DoubleNode(i); lastNode = doubleNode; temp.setNextNode(doubleNode);//设置上个的下一个 temp = doubleNode;//移动到当前 temp.setLastNode(temp2);//设置当前个的上一个 temp.setNextNode(firstNode);//设置最后一个的下一个为第一个 temp=firstNode;//移动到第一个 temp.setLastNode(doubleNode);//设置第一个的上一个为最后一个 } } } public void play(){ temp = firstNode; //先找到第一个报数的人 for(long i = 1;i<k;i++){ temp = temp.getNextNode(); } while(this.len != 1){ //找到要出列的人 for(long i=1;i<m;i++){ temp = temp.getNextNode(); } //让要出列的人出列 // temp2.setNextNode(temp.getNextNode()); if(len != 2){ temp2 = temp.getLastNode(); temp = temp.getNextNode(); temp2.setNextNode(temp); temp.setLastNode(temp2); }else{ temp = temp.getNextNode(); temp.setLastNode(null); temp.setNextNode(null); } this.len--; } System.out.println("最后一个出列的是"+temp.getNo()); } public void testnext(){ for(long i =0;i<this.len;i++){ if(i==0){ temp=firstNode; } System.out.println(temp.getNo()); temp = temp.getNextNode(); } } public void testlast(){ for(long i=this.len;i>=1;i--){ if(i == this.len){ temp = lastNode; } System.out.println(temp.getNo()); temp = temp.getLastNode(); } } }