Stack, Queue and Priority Queue
In comparison with Dynamic Sets such as BST and Hash Table, Stack, Queue and Priority Queue are relatively simple abstract data types. Albeit their easy implementation in coding, their importance can never be overlooked.
1. Stack
A Stack conforms to the principle of First-In, Last-Out (FILO). Here is a Stack based on Single-Linked List.
1 class Stack<T> { 2 private class Node<T> { 3 public Node<T> next; 4 public T data; 5 } 6 7 private Node<T> head; 8 9 public Stack() { 10 head = new Node<T>(); 11 } 12 public void push(T item) { 13 // Add an item to the top of the stack 14 Node<T> top = new Node<T>(); 15 top.data = item; 16 top.next = head.next; 17 head.next = top; 18 } 19 public boolean isEmpty() { 20 // Return whether the stack is empty 21 return head.next==null; 22 } 23 public T peek() { 24 // Return the top item of the stack 25 if (head.next==null) { 26 throw new RuntimeException("Stack Underflow"); 27 } else { 28 return head.next.data; 29 } 30 } 31 public T pop() { 32 // Extract the top item of the stack 33 if (head.next==null) { 34 throw new RuntimeException("Stack Underflow"); 35 } else { 36 T val = head.next.data; 37 head.next = head.next.next; 38 return val; 39 } 40 } 41 }
2. Queue
Instead of adopting FILO principle, a Queue adheres to the principle of First-In, First-Out (FIFO).
1 class Queue<T> { 2 private class Node<T> { 3 public Node<T> next; 4 public T data; 5 } 6 7 private Node<T> head, tail; 8 9 public Queue() { 10 head = new Node<T>(); 11 tail = head; 12 } 13 public void add(T item) { 14 // Enqueue a new item 15 tail.next = new Node<T>(); 16 tail = tail.next; 17 tail.data = item; 18 } 19 public boolean isEmpty() { 20 // Return whether the queue is empty 21 return head==tail; 22 } 23 public T peek() { 24 // Return the head of the queue 25 if (head==tail) { 26 throw new RuntimeException("Queue Underflow"); 27 } else { 28 return head.next.data; 29 } 30 } 31 public T poll() { 32 // Dequeue an item from the queue 33 if (head==tail) { 34 throw new RuntimeException("Queue Underflow"); 35 } else { 36 T val = head.next.data; 37 if (head.next==tail) { 38 tail = head; 39 } 40 head.next = head.next.next; 41 return val; 42 } 43 } 44 }
3. Priority Queue
Here I shall provide a Min-Priority Queue based on a Binary Heap.
1 class MinPriorityQueue<T extends Comparable> { 2 private T[] items; // data of heap items 3 private int len; // current length 4 private int size; // size of space 5 6 public MinPriorityQueue(int size) { 7 if (size<=0) { 8 throw new RuntimeException("Illegal Initial Size"); 9 } else { 10 this.size = size; 11 items = (T[]) new Comparable[size]; 12 } 13 } 14 public void add(T item) { 15 // Add a new item to the priority queue 16 if (len==size) { 17 doubleSize(); 18 } 19 items[len++] = item; 20 sift_up(len-1); 21 } 22 private void doubleSize() { 23 // Double the space size when it's filled up 24 if ((size<<1)<0) { 25 throw new RuntimeException("Size Expansion Failed"); 26 } else { 27 T[] tmp = items; 28 items = (T[]) new Comparable[size<<1]; 29 for (int i=0;i<len;i++) { 30 items[i] = tmp[i]; 31 } 32 size <<= 1; 33 } 34 } 35 public boolean isEmpty() { 36 // Return whether the priority queue is empty 37 return len==0; 38 } 39 public T poll() { 40 // Extract the head of the priority queue 41 if (len==0) { 42 return null; 43 } else { 44 T val = items[0]; 45 items[0] = items[--len]; 46 sift_down(0); 47 return val; 48 } 49 } 50 public T peek() { 51 // Return the head of the priority Queue 52 if (len==0) { 53 return null; 54 } else { 55 return items[0]; 56 } 57 } 58 private void sift_up(int i) { 59 // Adjustment made when items[i] is excessively small 60 // in terms of its current position 61 int j = ((i-1)>>1); 62 if (j<i && items[i].compareTo(items[j])<0) { 63 T tmp = items[i]; 64 items[i] = items[j]; 65 items[j] = tmp; 66 sift_up(j); 67 } 68 } 69 private void sift_down(int i) { 70 // Adjustment made when items[i] is excessively large 71 // in terms of its current position 72 int j = (i<<1)+1, k = (i<<1)+2, idx = i; 73 if (j<len) { 74 if (items[idx].compareTo(items[j])>0) { 75 idx = j; 76 } 77 if (k<len&&items[idx].compareTo(items[k])>0) { 78 idx = k; 79 } 80 if (idx>i) { 81 T tmp = items[i]; 82 items[i] = items[idx]; 83 items[idx] = tmp; 84 sift_down(idx); 85 } 86 } 87 } 88 }