我自己学习数据结构的时候,总希望能找到很简单的入门代码,可总是很难找到,于是就想到能写一些简单的java代码。 在百度百科上面搜索到约瑟夫环的问题时,并没有发现java的简单实现,自己在下面弄也是弄了很久,慢慢整理了自己的思路写出了下面的代码。
import java.util.ArrayList;
/*约瑟夫环是一个数学的应用问题:
* 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。
* 从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,
* 数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
例子
n = 9, k = 1, m = 5
【解答】 出局人的顺序为5, 1, 7, 4, 3, 6, 9, 2, 8。
*/
public class JOSEPHUS {
public static void main(String[] args) {
int n = 9, k = 1, m = 5 ;
ArrayList<Integer> list=new ArrayList<Integer>(n);
//初始化一些数据
for(int i=1;i<=n;i++){
list.add(i);
}
int i=k-1,t=1; //初始化下标和计数器
while(!list.isEmpty()){
if(t==m){
System.out.print(list.remove(i)+" ");
i--;//删除过后,i的下标已经变化了,所以需要减少
t=0;//记数器重新归零
}
t++;i++;//往下加
if(i>=list.size()){//如果到末尾了,就直接跳到开始位置
i=0;
}
}
}
}
用ArrayList实现过后,我又思考,能不能直接用数组来写呢?答案是肯定的!呵呵……而且用数组的话,系统的开销一定会比上面用arraylist小得多。下面就是用数组实现的代码了:
public class JOSEPHUS_WITH_ARRAY {
public static void main(String[] args) {
int n = 9, k = 1, m = 5;
int[] list = new int[n];
// 初始化一些数据
for (int i = 0; i < n; i++) {
list[i] = i + 1;
}
int i = k - 1, t = 1; // 初始化下标和计数器
int count = 0;
boolean isdel = false;
while (true) {
if (t == m) {
System.out.print(list[i % n] + " ");
list[i % n] = -1;
count++;
isdel = true;/*引入isdel是为了使当list[i]变成-1后不会对后面
* 判断执行i++还是i++;t++;产生错误的影响*/
t = 0;// 记数器重新归零
}
if (count >= n)//如果都杀完了,就跳循环了,结束程序的执行
break;
if (list[i % n] == -1 && !isdel) {
i++;// 往下加
isdel = false;
} else {
if (list[(i + 1) % n] != -1) {/*这里的判断很关键,这里面其它也包含了一种思想,只考虑两步。如果出现了list[i]=-1同时list[i+1]=-1,那么只是下标移动,而计数器是不能加1的*/
i++;
t++;
} else {
i++;
}
}
}
}
}
关于用i%n,即用数组的下标去对数组的长度求余,也是后来才想到的,这样能保证数组永远不会出现越界的情况,而且可以实现类似于循环队列的效果。