隊列--數組實現


  可以仿照利用數組實現棧的過程,使用數組實現隊列。以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 }
View Code

  然后是實現代碼:

  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 }
View Code

  其實,就燙手山芋游戲來說,使用如下的入隊和出隊方法更好:

  在入隊方法enqueue中,size==CAPACITY,那么就是隊滿了。在出隊方法中,如果size==0,那么即是隊空了。這種方法會導致原有隊首元素被覆蓋,正好符合題意,可以將隊列大小設置為孩子個數。如果使用禁止隊列規模超過CAPACITY-1的方法,隊列大小的設置要大於孩子個數,否則入隊時會提示“隊列已滿”。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM