package DataStructures.Queues; /** * A [deque](https://en.wikipedia.org/wiki/Double-ended_queue) is short for a double ended queue * pronounced "deck" and sometimes referred to as a head-tail linked list. A deque is a data * structure based on a doubly linked list, but only supports adding and removal of nodes from the * beginning and the end of the list. * * @author [Ian Cowan](https://github.com/iccowan) */ public class Deques { /** Node for the deque */ class DequeNode { /** Value of the node */ S val; /** Next node in the deque from this node */ DequeNode next = null; /** Previous node in the deque from this node */ DequeNode prev = null; /** Constructor */ DequeNode(S val) { this.val = val; } } /** Head of the deque */ DequeNode head = null; /** Tail of the deque */ DequeNode tail = null; /** Size of the deque */ int size = 0; /** * Adds the specified value to the head of the deque * * @param val Value to add to the deque */ public void addFirst(T val) { // Create a new node with the given value DequeNode newNode = new DequeNode(val); // Add the node if (head == null) { // If the deque is empty, add the node as the head and tail head = newNode; tail = newNode; } else { // If the deque is not empty, insert the node as the new head newNode.next = head; head.prev = newNode; head = newNode; } size++; } /** * Adds the specified value to the tail of the deque * * @param val Value to add to the deque */ public void addLast(T val) { // Create a new node with the given value DequeNode newNode = new DequeNode(val); // Add the node if (tail == null) { // If the deque is empty, add the node as the head and tail head = newNode; tail = newNode; } else { // If the deque is not empty, insert the node as the new tail newNode.prev = tail; tail.next = newNode; tail = newNode; } size++; } /** * Removes and returns the first (head) value in the deque * * @return the value of the head of the deque */ public T pollFirst() { // If the head is null, return null if (head == null) return null; // First, let's get the value of the old head T oldHeadVal = head.val; // Now, let's remove the head if (head == tail) { // If there is only one node, remove it head = null; tail = null; } else { // If there is more than one node, fix the references head.next.prev = null; DequeNode oldHead = head; head = head.next; // Can be considered unnecessary... // Unlinking the old head to make sure there are no random // references possibly affecting garbage collection oldHead.next = null; } size--; return oldHeadVal; } /** * Removes and returns the last (tail) value in the deque * * @return the value of the tail of the deque */ public T pollLast() { // If the tail is null, return null if (tail == null) return null; // Let's get the value of the old tail T oldTailVal = tail.val; // Now, remove the tail if (head == tail) { // If there is only one node, remove it head = null; tail = null; } else { // If there is more than one node, fix the references tail.prev.next = null; DequeNode oldTail = tail; tail = tail.prev; // Similarly to above, can be considered unnecessary // See `pollFirst()` for explanation oldTail.prev = null; } size--; return oldTailVal; } /** * Returns the first (head) value of the deque WITHOUT removing * * @return the value of the head of the deque */ public T peekFirst() { return head.val; } /** * Returns the last (tail) value of the deque WITHOUT removing * * @return the value of the tail of the deque */ public T peekLast() { return tail.val; } /** * Returns the size of the deque * * @return the size of the deque */ public int size() { return size; } /** * Returns whether or not the deque is empty * * @return whether or not the deque is empty */ public boolean isEmpty() { return head == null; } /** * Returns a stringified deque in a pretty form: * *

Head -> 1 <-> 2 <-> 3 <- Tail * * @return the stringified deque */ @Override public String toString() { String dequeString = "Head -> "; DequeNode currNode = head; while (currNode != null) { dequeString += currNode.val; if (currNode.next != null) dequeString += " <-> "; currNode = currNode.next; } dequeString += " <- Tail"; return dequeString; } public static void main(String[] args) { Deques myDeque = new Deques(); for (int i = 0; i < 42; i++) { if (i / 42.0 < 0.5) { myDeque.addFirst(i); } else { myDeque.addLast(i); } } System.out.println(myDeque); System.out.println("Size: " + myDeque.size()); System.out.println(); myDeque.pollFirst(); myDeque.pollFirst(); myDeque.pollLast(); System.out.println(myDeque); System.out.println("Size: " + myDeque.size()); System.out.println(); int dequeSize = myDeque.size(); for (int i = 0; i < dequeSize; i++) { int removing = -1; if (i / 39.0 < 0.5) { removing = myDeque.pollFirst(); } else { removing = myDeque.pollLast(); } System.out.println("Removing: " + removing); } System.out.println(myDeque); System.out.println(myDeque.size()); } }