深度剖析Java數據結構之隊列(一)——雙端隊列(ArrayDeque)

1、隊列前端

隊列是一種特殊的線性表,它只容許在表的前端(front)進行刪除操做,而在表的後端(rear)進行插入操做。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。隊列中沒有元素時,稱爲空隊列。java

2、雙端隊列後端

雙端隊列是隻既能夠在表的前端進行插入和刪除操做,又能夠在表的後端進行插入和刪除操做。數組

3、ArrayDeque的實現ide

Java中的雙端隊列是用數組實現的,類的全限名稱是java.util.ArrayDeque,該類的聲明以下:函數

<span style="font-size:18px;">public class ArrayDeque<E> extends AbstractCollection<E>implements Deque<E>, Cloneable, Serializable{}</span>

該類繼承了AbstractCollection類,實現了Deque、Cloneable和Serializable接口。實現Cloneable和Serializable接口的主要目的是爲了實現克隆和序列化。spa

該類中定義了四個個成員變量操作系統

<span style="font-size:18px;">public class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>, Cloneable, Serializable { private transient E[] elements; private transient int head; private transient int tail; private static final int MIN_INITIAL_CAPACITY = 8; }</span>

其中elements是數組的首地址,head是指向隊首的下標,tail是指向隊尾的下一個位置的下標。MIN_INITIAL_CAPACITY 定義了在建立隊列是,若是有指定長度,並且指定長度小於MIN_INITIAL_CAPACITY,則使用MIN_INITIAL_CAPACITY 做爲數組的最小長度。htm

其構造函數有一下幾種:對象

<span style="font-size:18px;">public ArrayDeque() { elements = (E[]) new Object[16]; }</span>

第一種構造函數,默認狀況下,數組的長度爲16。

<span style="font-size:18px;">public ArrayDeque(int numElements) { allocateElements(numElements); }</span>

第二種構造函數,給定數組長度,則調用allocateElements()函數,分配數組空間。allocateElements()函數的實現以下:

<span style="font-size:18px;">private void allocateElements(int numElements) { int initialCapacity = MIN_INITIAL_CAPACITY; if (numElements >= initialCapacity) { initialCapacity = numElements; initialCapacity |= (initialCapacity >>> 1); initialCapacity |= (initialCapacity >>> 2); initialCapacity |= (initialCapacity >>> 4); initialCapacity |= (initialCapacity >>> 8); initialCapacity |= (initialCapacity >>> 16); initialCapacity++; if (initialCapacity < 0) // Too many elements, must back off initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements } elements = (E[]) new Object[initialCapacity]; }</span>

對於一個給定長度,先判斷是否小於定義的最小長度,若是小於,則使用定義的最小長度做爲數組的長度。不然,找到比給定長度大的最小的2的冪數(在if裏面的覺得語句實現這一功能)。

<span style="font-size:18px;">public ArrayDeque(Collection<? extends E> c) { allocateElements(c.size()); addAll(c); }</span>

第三種構造函數,給定一個集合,先分配空間,而後添加到集合中。

從上面的三種構造函數中,能夠判斷出來,數組的長度是2的冪數,定義爲2的冪數我的認爲有兩個緣由:

1.夥伴系統

操做系統分配內存的方法使用夥伴系統的話,每一塊的大小都是2的冪數,若是分配的內存大小爲2的冪數,能夠減小內存分配的時間。

夥伴系統在百度百科中的解釋:http://baike.baidu.com/view/4935190.htm

2.插入和刪除的速度

對於數組,若是head的值爲0,時,在隊首插入元素,有一種方法是將所有元素都向後移動一位,而後將新的元素插入。這樣子的話,插入和刪除的速度會很是慢,特別是在元素不少的狀況下。另外一種方法就是在head的值爲0時,在隊首插入元素,能夠將head的值置爲(數組的長度-1)。也就是將新插入的元素放到數組的最後,以此類推。在計算插入元素位置下標的時候,數組長度是2的冪數就用處了。下面是插入元素時,計算插入位置的值的語句

<span style="font-size:18px;">head = (head - 1) & (elements.length - 1)</span>

length-1的值爲高位全爲0,低位全爲1,經過按位相與,能夠得出應該插入元素的位置。而後就是該類的一些方法了,有點面向對象的思想的都應該會想到,應該有頭插,頭刪,尾插,尾刪等等一些操做,在此就不一一列出了,實現起來也比較簡單。關鍵仍是要了解ArrayDeque的實現機制。

相關文章
相關標籤/搜索