java實現隊列

隊列的定義

  隊列的特色是節點的排隊次序和出隊次序按入隊時間前後肯定,即先入隊者先出隊,後入隊者後出隊。即咱們常說的FIFO(first in first out)先進先出。    java

順序隊列定義及相關操做

  順序存儲結構存儲的隊列稱爲順序隊列,內部使用一個一維數組存儲,用一個隊頭指針front指向隊列頭部節點(即便用int類型front來表示隊頭元素的下標),用一個隊尾指針rear,指向隊列尾部元素(int類型rear來表示隊尾節點的下標)。數組

  初始化隊列時: front = rear = -1 (非必須,也可設置初始值爲0,在實現方法時具體修改)this

  隊列滿時:     rear = maxSize-1 (其中maxSize爲初始化隊列時,設置的隊列最大元素個數)spa

  隊列爲空時:  front = rear指針

  下面使用java實現一個基於一維數組的順序隊列,代碼以下:code

 1 /**
 2  * 定義一個queue
 3  */
 4 class ArrayQueue{
 5     private int[] data ; //隊列中存放的數據
 6     private int maxSize ; //隊列的大小
 7     private int front ;//指向隊列頭部的指針
 8     private int rear ; //指向隊列尾部的指針
 9 
10     public ArrayQueue(int maxSize){
11         this.maxSize = maxSize;
12         data = new int[maxSize];
13         front = -1;
14         rear = -1;
15     }
16 
17     /**
18      * 判斷隊列是否已滿
19      * @return
20      */
21     public boolean isFull(){
22         return rear == maxSize -1 ;
23     }
24 
25     /**
26      * 判斷隊列是否爲空
27      * @return
28      */
29     public boolean isEmpty(){
30         return rear == front;
31     }
32 
33     /**
34      * 添加數據到隊列
35      * @param n
36      */
37     public void add(int n){
38         if(isFull()){
39             System.out.println("隊列已滿,不能添加");
40             return;
41         }
42         data[++rear] = n;
43     }
44 
45     /**
46      * 顯示頭部數據
47      * @return
48      */
49     public void head(){
50         if(isEmpty()){          
      throw new RuntimeException("隊列爲空"); 53 } 54 System.out.println(data[front+1]); 55 } 56 57 /** 58 * 取出頭部數據 59 * @return 60 */ 61 public int pop(){ 62 if(isEmpty()){
64 throw new RuntimeException("隊列爲空"); 65 } 66 int a = data[++front]; 67 data[front] = 0; 68 return a; 69 } 70 71 /** 72 * 打印所有數據 73 */ 74 public void print(){ 75 if(isEmpty()){ 76 System.out.println("隊列爲空"); 77 return; 78 } 79 for(int i=0;i<data.length;i++){ 80 System.out.printf("array["+i+"]=%d\n",data[i]); 81 } 82 } 83 }

  簡單描述順序隊列的入隊(add方法):blog

  

 1 public static void main(String []args) {
 2         //1.聲明一個能夠存儲6個元素的順序隊列,默認值爲0,front 和rear指針爲-1
 3         ArrayQueue queue = new ArrayQueue(6);
 4         //2.向順序隊列中添加元素
 5         queue.add(1);
 6         queue.add(2);
 7         queue.add(3);
 8         queue.add(4);
 9         queue.add(5);
10         queue.add(6);
11         //2.1打印當前隊列元素
12         queue.print();
13         //3.將順序隊列中元素取出
14         queue.pop();
15         queue.pop();
16         queue.pop();
17         queue.pop();
18         queue.pop();
19         queue.pop();
20         //4.隊列中元素所有取出
21 }

  在代碼中初始化了一個大小爲6的順序隊列,下圖展現了第一步(即代碼ArrayQueue queue = new ArrayQueue(6))中隊列元素及指針狀況隊列

 

  其中front和rear指向的虛線框實際並不存在,僅用來表示初始化時的默認狀態,因咱們實現的隊列元素使用int[]存儲元素,因此初始值均爲0(如用Object[]或範型則初始值爲null)io

      執行queue.add(1)方法後隊列的狀態以下圖:class

 

  能夠看到向隊列中添加元素後,rear指針向後移動一個位置指向第一個元素位置,後面繼續添加後面5個元素後隊列以下圖所示

  接下來看下隊列的出隊狀況 

  當第一次執行queue.pop()方法後,隊列元素如上圖所示,此時隊列剩下5個元素

  當第六次執行queue.pop()方法後,隊列元素以下圖所示

  此時隊列中元素已所有出隊,按正常邏輯應該能夠添加元素到隊列中,但此時添加元素卻會報隊列已滿錯誤(rear=maxSize-1),固然即便前面元素未出隊也會報相同錯誤。這就是咱們常說的「假溢出」問題。爲解決這個問題,就引出了咱們的環形隊列。

環形隊列

  環形隊列,顧名思義即讓普通隊列首尾相連,造成一個環形。當rear指向尾元素後,當隊列有元素出隊時,能夠繼續向隊列中添加元素。

  這裏我使用的是rear指針指向最後一個節點的後一個元素,即會佔用一個位置用來表示隊列已滿。

  

  初始化隊列時: front = rear = 0

  隊列滿時:    ( rear +1 ) % maxSize == front (其中maxSize爲初始化隊列時,設置的隊列最大元素個數)

  這裏不能使用rear = maxSize-1做爲判斷隊滿的條件,因使用環形隊列方式實現,當第一次隊滿時,rear = maxSize -1,執行出隊操做後原隊頭位置空出,此時繼續執行入隊操做,則rear向後移動一個位置,則rear = 0,而此時隊列也是已滿狀態。因此只要rear 向前移動一個位置就等於front時,就是隊滿的狀況。

  隊列爲空時:  front == rear

  先看下具體代碼

  

 1 public class CycleQueue {
 2 
 3     /**
 4      *
 5      */
 6     private int maxSize ;
 7     private int data[] ;
 8     private int front ;
 9     /**
10      * 這裏rear指向最後一個數據的後面一個位置,即隊列中有一個爲空佔位
11      */
12     private int rear ;
13 
14     public CycleQueue(int maxSize){
15         this.maxSize = maxSize;
16         data = new int[maxSize];
17         front = 0;
18         rear = 0;
19     }
20 
21     /**
22      * 判斷隊列是否已滿
23      * 因是循環隊列,因此rear值可能小於front,因此不能使用rear == maxSize -1來判斷
24      * @return
25      */
26     public boolean isFull(){
27         return (rear + 1) % maxSize == front;
28     }
29 
30     public boolean isEmpty(){
31         return rear == front;
32     }
33 
34     public void add(int n){
35         if(isFull()){
36             System.out.println("隊列已滿,不能添加");
37             return;
38         }
39         data[rear] = n;
40         rear = (rear + 1) % maxSize;
41     }
42 
43     public void head(){
44         if(isEmpty()){
45             throw new RuntimeException("隊列爲空");
46         }
47         System.out.println("head="+data[front]);
48     }
49 
50     public int pop(){
51         if(isEmpty()){
52             throw new RuntimeException("隊列爲空");
53         }
54         int value = data[front];
55         front = (front + 1) % maxSize;
56         return value;
57     }
58 
59     public void print(){
60         if(isEmpty()){
61             System.out.println("隊列爲空");
62             return;
63         }
64         for(int i= front; i<front+size(); i++){
65             System.out.printf("array"+(i%maxSize)+"=%d",data[i%maxSize]);
66         }
67     }
68 
69     /**
70      * 因是循環隊列,因此會出現rear<front狀況,這裏須要+maxSize
71      * @return
72      */
73     public int size(){
74         return (rear - front + maxSize)%maxSize;
75     }
76 }

  下面再以圖解的方式講解一下環形隊列的入隊出隊以及隊滿狀況。當執行初始化代碼後

1 CycleQueue queue = new CycleQueue(6);   

  此時front = rear = 0,隊列爲空。當第一次執行queue.add(1)後,環形隊列元素以下圖所示

 

  當依次執行queue.add(2);queue.add(3);queue.add(4);queue.add(5);後,達到(rear+1)%maxSize=front (即rear=5)條件,隊列已滿不能添加新元素。此時環形隊列元素狀況以下圖

 

  因此這種狀況會浪費一個空間來做爲判滿的條件。

  下面執行出隊操做,當第一次執行出隊操做queue.pop()方法後,環形隊列元素狀況以下圖所示

   此時 (rear+1)%maxSize = 0  不等於 front=1 ,因此能夠繼續向隊列中添加元素,也就不會出現假溢出的狀況。當執行入隊(例queue.add(6))操做後,rear = (rear+1)%maxSize 即rear=0,以此來生成環形隊列。此時隊列元素狀況以下圖所示

  另外,再說明下環形隊列有效元素個數問題,若是不是環形隊列,則有效元素個數size = rear - front。而使用環形實現後,會出現rear<front的狀況,因此這裏使用(rear-front+maxSize)%maxSize的方式計算有效元素個數。(或者在內部定義一個size屬性,當元素入隊時size++,當出隊時size--)

  所以在打印隊列中元素時,從front位置開始至 front+size位置結束來循環打印有效元素。

總結

  若是不實用環形隊列方式實現隊列,則會出現「假溢出」狀況(即隊列滿後,將所有元素出隊卻不能繼續添加元素的狀況)。而環形隊列會在隊頭元素出隊後,將隊尾指針rear從新分配爲0,以達到循環使用隊列空間的目的。

相關文章
相關標籤/搜索