本章要求有以下預備知識:線性表的順序存儲結構之順序表類的實現_Java
今天我們來使用順序表類求解約瑟夫(Josephus)環問題。
首先我閒來描述下約瑟夫環問題:古代某法官要裁決n個犯人的死刑,他有一條荒唐的法律,將犯人站成一個圓圈,從第s個人開始數起,每數到第d個犯人,就拉出來處決,然後再從下一個開始數d個,數到的人再處決,……,知道剩下最後一個犯人予以赦免。
使用順序表類SeqList求解約瑟夫環問題,算法描述如下:
創建一個具有n個元素的順序表對象list。
從第s個元素開始,依次計數,每數到d,就將對應元素刪除。
重複計數並刪除元素,直到剩下一個元素。
設index表示順序表元素序號,計數時,使index按照以下規律變化,則數序表可以看成是環型結構:
index = (index + d-1) % list.length();
在聲明和創建SeqList對象時,指定泛型E爲一個類。程序如下:
import dataStructure.linearList.LList;
import dataStructure.linearList.SeqList;;
public class Josephus //求解約瑟夫環問題
{
private LList<String> list; //存儲約瑟夫環中的多個對象
public Josephus(int number,int start,int distance) //創建約瑟夫環並求解,參數指定環長度、起始位置、計數
{
this.list = new SeqList<String>(number); //順序表元素類型是字符串,指定容量
for(int i = 0;i < number;i ++)
this.list.add(new String((char)('A' + i) + "")); //添加字符串對象
System.out.print("約瑟夫環(" + number + "," + start + "," + distance + "),");
System.out.println(this.list.toString()); //顯示順序表所有對象的字符串表示
int index = start - 1; //計數起始位置
while (this.list.length() > 1) //多於一個對象時循環
{
index = (index + distance - 1) % this.list.length();
System.out.print("刪除" + this.list.remove(index).toString() + ","); //刪除指定位置對象
System.out.println(this.list.toString());
}
System.out.println("被赦免者是" + list.get(0).toString());
}
public static void main(String[] args)
{
new Josephus(10, 1, 3);
}
}
程序運行結果如下:
約瑟夫環(10,1,3),(A,B,C,D,E,F,G,H,I,J)
刪除C,(A,B,D,E,F,G,H,I,J)
刪除F,(A,B,D,E,G,H,I,J)
刪除I,(A,B,D,E,G,H,J)
刪除B,(A,D,E,G,H,J)
刪除G,(A,D,E,H,J)
刪除A,(D,E,H,J)
刪除H,(D,E,J)
刪除E,(D,J)
刪除J,(D)
被赦免者是D