约瑟夫问题的一种解法

/*

* 问题原型

*/

41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。约瑟夫将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

/*

* 问题分析

*/

这个问题还有一种描述为丢手绢问题,因此代码命名以shoujuan

由于最近在学习java,因此决定用java链表来完成这个问题。设计一个循环链表,将41个人链接起来,选定一个人作为起始,逢3进行remove动作。

需要设计类:

  shoujuan,用以表示每个人。包含成员:number用以计数,nextJuan用以表示下一个人。

  ShouJuanList,用以表示链表。包含成员:shouJuanFirst用以表示第一个人,shouJuanNbr用以表示总人数。包含方法:makeCircle()制造环形链表,addShouJuan()新增一个节点,removeShouJuan()删除一个节点。

/*

* 难点分析

*/

在完成这个代码的过程中,主要考虑到循环链表的特性,即最后一个又指向头结点。完成这个代码需要对传值和传址有十分清晰的认识,传入的地址是会影响这个地址上是值的。

需要对头结点、第二个结点做特殊的考虑,防止有遗漏情况。

方法不是最简的,作为学习途中的一个标记,mark一下。

/*

* 代码

*/

ShouJuan.java

 1 package com.diushoujuan;
 2 
 3 public class ShouJuan {
 4     private int number;
 5     private ShouJuan nextJuan = null;
 6     
 7     public ShouJuan(int n){
 8         this.number = n;
 9     }
10 
11     public int getNumber() {
12         return number;
13     }
14 
15     public void setNumber(int number) {
16         this.number = number;
17     }
18 
19     public ShouJuan getNextJuan() {
20         return nextJuan;
21     }
22 
23     public void setNextJuan(ShouJuan nextJuan) {
24         this.nextJuan = nextJuan;
25     }
26     
27     public void showNbr(){
28         System.out.println("nub is: "+ this.number);
29     }
30 }

ShouJuanList.java

 1 package com.diushoujuan;
 2 
 3 /*
 4  * 创建循环链表
 5  */
 6 public class ShouJuanList {
 7     private ShouJuan shouJuanFirst = null;
 8     
 9     private int shouJuanNbr = 0;
10     
11     public int getShouJuanNbr() {
12         return shouJuanNbr;
13     }
14 
15     public void setShouJuanNbr(int shouJuanNbr) {
16         this.shouJuanNbr = shouJuanNbr;
17     }
18 
19     public ShouJuan getShouJuanFirst() {
20         return shouJuanFirst;
21     }
22 
23     public void setShouJuanFirst(ShouJuan shouJuanFirst) {
24         this.shouJuanFirst = shouJuanFirst;
25     }
26 
27     //制造环形链表
28     public void makeCircle(){
29         if(shouJuanFirst != null){
30             ShouJuan shouJuanTemp = shouJuanFirst;
31             while(null != shouJuanTemp.getNextJuan()){
32                 shouJuanTemp = shouJuanTemp.getNextJuan();
33             }
34             shouJuanTemp.setNextJuan(shouJuanFirst);
35         }
36     }
37     
38     //新增一个节点
39     public void addShouJuan(ShouJuan shouJuan){
40         ShouJuan shouJuanTemp = null;
41         if(shouJuanFirst == null){
42             shouJuanFirst = shouJuan;                
43         }else{
44             shouJuanTemp = shouJuanFirst;
45             while(null != shouJuanTemp.getNextJuan()){
46                 shouJuanTemp = shouJuanTemp.getNextJuan();
47             }
48             shouJuanTemp.setNextJuan(shouJuan);
49         }
50         shouJuanNbr++;        
51     }
52     
53     //删除一个节点
54     public void removeShouJuan(ShouJuan shouJuan){
55         ShouJuan shouJuanTemp = shouJuanFirst;
56         if (shouJuanTemp == shouJuanFirst && shouJuanTemp.getNumber() == shouJuan.getNumber() && shouJuanNbr == 1) {
57             shouJuanFirst = null;
58             shouJuanNbr--;
59         }else if(shouJuanTemp == shouJuanFirst && shouJuanTemp.getNumber() == shouJuan.getNumber() && shouJuanNbr == 2){
60             shouJuanFirst = shouJuanFirst.getNextJuan();
61             shouJuanNbr--;
62         }else if(shouJuanTemp == shouJuanFirst && shouJuanTemp.getNumber() == shouJuan.getNumber() && shouJuanNbr>2){
63             while(shouJuanTemp.getNextJuan() != shouJuanFirst){
64                 shouJuanTemp = shouJuanTemp.getNextJuan();
65             }
66             shouJuanTemp.setNextJuan(shouJuanFirst.getNextJuan());
67             shouJuanFirst = shouJuanFirst.getNextJuan();
68             shouJuanNbr--;
69         }else{
70             if(shouJuanTemp == shouJuanFirst && shouJuanTemp.getNumber() != shouJuan.getNumber()){
71                 shouJuanTemp = shouJuanTemp.getNextJuan();
72             }
73             while(true){
74                 if(shouJuanTemp.getNextJuan().getNumber() == shouJuan.getNumber()){
75                     shouJuanTemp.setNextJuan(shouJuanTemp.getNextJuan().getNextJuan());
76                     shouJuanNbr--;
77                     break;
78                 }
79                 shouJuanTemp = shouJuanTemp.getNextJuan();
80             }            
81         }
82     }
83 }

PlayGame.java

package com.diushoujuan;

public class PlayGame {

    public final static int shouJuanNbr = 2;
    public final static int shouJuanRemoveNbr = 2;
    
    public static void main(String[] args) {
        ShouJuanList shouJuanList = new ShouJuanList();
        
        for(int i = 1; i<=shouJuanNbr; i++){
            ShouJuan shouJuan = new ShouJuan(i);
            shouJuanList.addShouJuan(shouJuan);
        }
        shouJuanList.makeCircle();
        
        ShouJuan shouJuanRemove = shouJuanList.getShouJuanFirst();
        while(shouJuanList.getShouJuanNbr() >= shouJuanRemoveNbr){
            if (shouJuanRemove != shouJuanList.getShouJuanFirst()) {
                shouJuanRemove= shouJuanRemove.getNextJuan();
            }
            for(int i = 1;i< shouJuanRemoveNbr;i++){
                shouJuanRemove = shouJuanRemove.getNextJuan();
            }
            shouJuanList.removeShouJuan(shouJuanRemove);
        }
        
        ShouJuan shouJuanShow = shouJuanList.getShouJuanFirst();
        for(int i = 1;i< shouJuanRemoveNbr;i++){            
            shouJuanShow.showNbr();
            shouJuanShow = shouJuanShow.getNextJuan();
        }
    }

}
原文地址:https://www.cnblogs.com/wee616/p/4777027.html