约瑟夫环是一个数学的应用问题:已知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();
}
}
}