雙端隊列就是隊列的頭尾兩端都能進行插入和刪除的隊列,而普通的隊列只能在頭部刪除,尾部插入。雙端隊列的英文名是deque, double-end queue.
實現雙端隊列最好使用雙向鏈表,因為在雙向鏈表中,鏈表中每一個節點,都能指向它的前一個節點和后一個節點,只操作一個節點,就能進行插入和刪除操作,
因此使用雙向鏈表實現隊列時,只要隊列中知道頭尾兩個節點,就可以在隊列的兩端進行插入和刪除操作。
雙端隊列中,使用雙向鏈表,所以可以聲明一個內部類DLNode表示鏈表中的每一個節點,因為節點中有數據,前一個節點的引用和后一個節點的引用,所以它有三個屬性data, next 和previous, 又因為雙端隊列中要知道鏈表中頭尾兩個節點的引用,所以還要聲明兩個屬性firstNode, lastNode.
public class DEuqeu<T> { private class DLNode { T data; DLNode next; DLNode previous; DLNode(T data) { this.data = data; } } private DLNode firstNode; // 指向雙向鏈表的頭節點 private DLNode lastNode; // 指向雙向 }
向隊列(鏈表)尾部添加元素,就是創建一個新節點,如果鏈表為空,直接讓firstNode和lastNode指向這個新節點,如果鏈表不為空,lastNode.next指向新節點,新節點的previous 指向lastNode,最后,lastNode指向新節點
public boolean isEmpty() { return firstNode == null; } public void addToBack(T newEntry) { DLNode newNode = new DLNode(newEntry); newNode.previous = lastNode; if (isEmpty()) firstNode = lastNode = newNode ; else { lastNode.next = newNode; lastNode = newNode; } }
向隊列(鏈表)頭部插入一個元素,就是創建一個新元素,它的lnext要指向firstNode, firstNode的previous指向新節點,然后firstNode 指向新節點
public void addToFront(T newEntry) { DLNode newNode = new DLNode(newEntry); newNode.next = firstNode; if (isEmpty()) firstNode =lastNode = newNode; else { firstNode.previous =newNode; firstNode = newNode; } }
從隊列(鏈表)頭部,刪除一個元素,如果鏈表為空,拋出異常,如果鏈表不為空,firstNode = firstNode.next; 同時iirstNode 的 previous只為null。如要只有一個元素,刪除之后,firstNode 為null,那lastNode也為null。
public T removeFront() { if(isEmpty()) { throw new RuntimeException("隊列為空"); } DLNode front = firstNode; firstNode = firstNode.next; if (firstNode == null) lastNode = null; else firstNode.previous = null; return front.data; }
從隊列(鏈表)尾部刪除一個元素,就是通過lastNode, 找到它的前一個節點,前一個節點的next 為null,就可以。
public T removeBack() { if(isEmpty()) { throw new RuntimeException("隊列為空"); } DLNode last = lastNode; lastNode = lastNode.previous; if (lastNode == null) firstNode = null; else lastNode.next = null; return last.data; }