可以仿照利用數組實現棧的過程,使用數組實現隊列。以front指向隊首元素,值始終為數組首元素a[0]。出隊時,front保持不變,刪除隊首元素,其余元素依次向前移動,時間復雜度是O(n)。入隊時,根據隊列大小將元素存儲到相應位置。上述實現因為不斷移動元素,效率太低。因此以下使用環形數組的形式來構造隊列。定義兩個變量:
front:指向隊首元素。
rear:指向隊尾元素的下一個位置。
另外設環形數組大小為len。初始狀態下,front=rear=0。入隊時,在rear指向的位置存儲元素,然后令rear=(rear+1)%len。出隊時,刪除front指向的元素,然后令front=(front+1)%len。最后,front=rear既是隊滿的判斷條件又是隊空的判斷條件,不過可以完美解決。在入隊方法enqueue中,size==CAPACITY,那么就是隊滿了。在出隊方法中,如果size==0,那么即使隊空了。不過這種方法會導致原有隊首元素被覆蓋(覆蓋原隊首元素不符合隊列的設計初衷),可以通過禁止隊列規模超過CAPACITY-1的方法來解決此問題。這樣,只有隊空的時候才有front=rear。使用這種方法利用環形隊列實現了”燙手山芋“游戲。燙手山芋游戲規則:一群小孩圍成一圈,在他們之間傳遞山芋。其中,一個小孩負責數數,每數一次,就把山芋轉交給左邊的鄰居,從1開始數起,數到k時拿着山芋的孩子出列,然后重新從1開始說,從”淘汰“孩子的鄰居開始重新傳遞山芋。實現代碼如下:
首先給出Queue接口的代碼:

1 /** 2 * Created by hfz on 2016/8/2. 3 */ 4 public interface Queue { 5 void enqueue(Object obj);//入隊 6 Object dequeue();//出隊並返回對首元素 7 int getSize();//隊列元素個數 8 boolean isEmpty();//判斷隊列是否為空 9 Object front();//返回對首元素 10 }
然后是實現代碼:

1 import java.util.Objects; 2 import java.util.Random; 3 4 /** 5 * Created by hfz on 2016/8/2. 6 */ 7 /* 8 可以仿照利用數組實現棧的過程,使用數組實現隊列。以front指向隊首元素,值始終為數組首元素a[0]。 9 出隊時,front保持不變,刪除隊首元素,其余元素依次向前移動,時間復雜度是O(n)。 10 入隊時,根據隊列大小將元素存儲到相應位置。 11 12 上述實現因為不斷移動元素,效率太低。因此以下使用環形數組的形式來構造隊列。 13 定義兩個變量: 14 front:指向隊首元素。 15 rear:指向隊尾元素的下一個位置。 16 另外設環形數組大小為len 17 初始狀態下,front=rear=0。入隊時,在rear指向的位置存儲元素,然后令rear=(rear+1)%len。 18 出隊時,刪除front指向的元素,然后令front=(front+1)%len。 19 最后,front=rear既是隊滿的判斷條件又是隊空的判斷條件,不過可以完美解決。在入隊方法enqueue中, 20 size==CAPACITY,那么就是隊滿了。在出隊方法中,如果size==0,那么即使隊空了。不過這種方法會導致原有隊首元素被覆蓋(覆蓋原隊首元素 21 不符合隊列的設計初衷),可以通過禁止隊列規模超過CAPACITY-1的方法來解決此問題。這樣,只有隊空的時候才有front=rear。 22 各種方法時間復雜度均是O(1) 23 */ 24 25 public class Queue_Array implements Queue { 26 private static int CAPACITY=40; 27 private int capacity=0; 28 private Object[] S; 29 private int front=0; 30 private int rear=0; 31 32 public Queue_Array(int capacity){ 33 this.capacity=capacity; 34 S=new Object[capacity]; 35 } 36 public Queue_Array(){ 37 this(CAPACITY); 38 } 39 public void enqueue(Object obj){ 40 if(getSize()==CAPACITY-1){//隊滿 41 throw new ExceptionQueueFull("隊滿,不能入隊"); 42 } 43 else{//隊未滿,入隊 44 try { 45 46 S[rear] = obj; 47 //front=(front+1)%CAPACITY;//隊首指針加1,再對數組長度取模。 48 rear = (rear + 1) % CAPACITY;//隊尾指針加1,再對數組長度取模。 49 } 50 catch (ArrayIndexOutOfBoundsException ex){ 51 System.out.println(); 52 } 53 } 54 55 } 56 public Object dequeue(){ 57 if(rear==front){ 58 throw new ExceptionQueueEmpty("隊空,不能出隊"); 59 } 60 else{ 61 Object obj=S[front]; 62 S[front]=null; 63 front=(front+1)%CAPACITY; 64 return obj; 65 } 66 } 67 68 public Object front(){ 69 if(rear==front){ 70 throw new ExceptionQueueEmpty("隊空,沒有隊首元素"); 71 } 72 else{ 73 return S[front]; 74 } 75 } 76 public boolean isEmpty(){ 77 if(front==rear){ 78 return true; 79 } 80 else { 81 return false; 82 } 83 } 84 public int getSize(){ 85 return (CAPACITY+rear-front)%CAPACITY;//rear取模之后可能小於front,不能直接用(rear-front) 86 } 87 88 89 public static void main(String[] args){ 90 String[] children={"A","B","C","D","E","F","G","H","I","J","K"}; 91 Queue_Array queue=new Queue_Array(); 92 // int len=queue.capacity; 93 for(String s:children){ 94 queue.enqueue(s); 95 } 96 Random rand=new Random(); 97 Object dequeueObj; 98 int k=rand.nextInt(children.length-1)+1; 99 //k=4; 100 while(queue.getSize()!=1){ 101 for(int i=1;i<k;++i){ 102 dequeueObj=queue.dequeue(); 103 queue.enqueue(dequeueObj); 104 } 105 dequeueObj=queue.dequeue(); 106 System.out.println(String.format("%s 退出",(String)dequeueObj)); 107 } 108 System.out.println(String.format("when k is %s winner is %s ",k,queue.front())); 109 } 110 } 111 112 class ExceptionQueueEmpty extends RuntimeException { 113 public ExceptionQueueEmpty(String err){ 114 super(err); 115 } 116 } 117 class ExceptionQueueFull extends RuntimeException{ 118 public ExceptionQueueFull(String err){ 119 super(err); 120 } 121 }
其實,就燙手山芋游戲來說,使用如下的入隊和出隊方法更好:
在入隊方法enqueue中,size==CAPACITY,那么就是隊滿了。在出隊方法中,如果size==0,那么即是隊空了。這種方法會導致原有隊首元素被覆蓋,正好符合題意,可以將隊列大小設置為孩子個數。如果使用禁止隊列規模超過CAPACITY-1的方法,隊列大小的設置要大於孩子個數,否則入隊時會提示“隊列已滿”。