大概花了一个晚上搭一个中午的时间,完善了一个关于Josephus的程序,这个Josephus游戏可是非常经典的算法,作为一个想从事软件的人最好能够理解一下,毕竟这个计算机教材上也讲过类似题目,具体的关于问题的描述我就不多说了,这个Josephus一般都是用队列来实现,当然了对于一个具体的算法而言数据结构并不是第一重要的,最重要的还是算法本身。这个程序关键之处还是在于如何巧妙地实现对淘汰的人的处理,用队列比较好实现。
public class CountDown { public static Object josephus(Queue_List q,int k)throws QueueStackEmpty,QueueStackFull{ if(q.isEmpty()) return null; while(q.size()>1){ q.traversal();//遍历所有队列元素 for(int i=1;i<k;i++){ q.enqueue(q.dequeue()); } Object e=q.dequeue(); System.out.println("\n孩子"+e+"退出"); System.out.print("\n队头指针指向"+q.getItem(q.f)+"队尾指针指向"+q.getItem(q.r-1)+"\n"); } return q.dequeue(); } //将一组对象组织为一个队列 public static Queue_List buildQueue(Object[] a){ Queue_List ql = new Queue_List(); for(int i=0;i<a.length;i++){ ql.enqueue(a[i]); } return ql; } public static void main(String[] args) { try{ String[] kid ={ "Alice","Bob","Cindy","Oliver","July", "Rikc","Robin","Bill","Tom","Sam","Kim", "Lin","Linda","UU","Baidu","Web" }; System.out.println("最终的幸运者是:"+josephus(buildQueue(kid),1)); }catch(QueueStackEmpty e){ System.out.println("栈空了"); }catch(QueueStackFull e){ System.out.println("栈满了"); } } } //模仿队列数据结构的类 class Queue_List { //队列的元素仍不能超过SIZE个元素,超过部分就会回到下标为0处,是否覆盖原来的数据取决于队头指针的值 public final int SIZE = 17; public Object[] Q; int f,r; //分别指向队头元素和队尾元素 public Queue_List(){ Q = new Object[SIZE]; f = -1; //队头指针初始化为-1; } public Queue_List(int num){ Q= new Object[num]; f = -1; //队头指针初始化为-1; } //返回指定元素的下标值 public int getElement(Object obj){ for(int i=0;i<r;i++){ if(Q[i].equals(obj))return i; } return -2; } //返回指定下标处的值 public Object getItem(int index){ return Q[index]; } //替换或设置指定下标处的值 public void setItem(int index,Object obj){ Q[index]=obj; } //弹出队头元素 public Object dequeue(){ if(isEmpty()) throw new QueueStackEmpty("栈为空"); int i=f; f++; //队头指针往后移动一位 return Q[i]; } //添加元素到队列中,添加成功返回true public boolean enqueue(Object obj)throws QueueStackFull{ if(f == -1){ f=0;r=0; } if(r>=(SIZE)){ //如果队尾指针已经到达尾部 if(f==0){ throw new QueueStackFull("栈满了"); } int tempF=f,tempSize=size(); for(int i=0,j=tempF;i<tempSize;i++,j++){ Q[i]=Q[j]; } //重新定位队头指针和队尾指针 f=0;r=tempSize; } Q[r]=obj; r++; //队尾指针总是指向最后一个将要添加的元素 return true; } public int size() { return (r-f); } public boolean isEmpty() { if(size()==0 || f== -1) return true; return false; } public void traversal(){ int j=0; for(int i=f;i<r;i++){ j++; if(j%10==0) System.out.println(); System.out.print(" "+ Q[i]); } } }