堆棧(Stack)是一種常見的數據結構,符合后進先出(First In Last Out)原則,通常用於實現對象存放順序的逆序。棧的基本操作有push(添加到堆棧),pop(從堆棧刪除),peek(檢測棧頂元素且不刪除)。
第一種實現方式:普通數組實現
/** * Created by Frank */ public class ToyStack { /** * 棧的最大深度 **/ protected int MAX_DEPTH = 10; /** * 棧的當前深度 */ protected int depth = 0; /** * 實際的棧 */ protected int[] stack = new int[MAX_DEPTH]; /** * push,向棧中添加一個元素 * * @param n 待添加的整數 */ protected void push(int n) { if (depth == MAX_DEPTH - 1) { throw new RuntimeException("棧已滿,無法再添加元素。"); } stack[depth++] = n; } /** * pop,返回棧頂元素並從棧中刪除 * * @return 棧頂元素 */ protected int pop() { if (depth == 0) { throw new RuntimeException("棧中元素已經被取完,無法再取。"); } // --depth,dept先減去1再賦值給變量dept,這樣整個棧的深度就減1了(相當於從棧中刪除)。 return stack[--depth]; } /** * peek,返回棧頂元素但不從棧中刪除 * * @return */ protected int peek() { if (depth == 0) { throw new RuntimeException("棧中元素已經被取完,無法再取。"); } return stack[depth - 1]; } }
第二種實現方式:deque雙向隊列
import java.util.ArrayDeque; import java.util.Deque; public class IntegerStack { private Deque<Integer> data = new ArrayDeque<Integer>(); public void push(Integer element) { data.addFirst(element); } public Integer pop() { return data.removeFirst(); } public Integer peek() { return data.peekFirst(); } public String toString() { return data.toString(); } public static void main(String[] args) { IntegerStack stack = new IntegerStack(); for (int i = 0; i < 5; i++) { stack.push(i); } System.out.println("After pushing 5 elements: " + stack); int m = stack.pop(); System.out.println("Popped element = " + m); System.out.println("After popping 1 element : " + stack); int n = stack.peek(); System.out.println("Peeked element = " + n); System.out.println("After peeking 1 element : " + stack); } } /* 輸出 After pushing 5 elements: [4, 3, 2, 1, 0] Popped element = 4 After popping 1 element : [3, 2, 1, 0] Peeked element = 3 After peeking 1 element : [3, 2, 1, 0] */
ArrayDeque源碼
//java.util.ArrayDeque的源碼: private transient E[] elements; private transient int head; private transient int tail; /*此處存放e的位置是從elements數組最后的位置開始存儲的*/ public void addFirst(E e) { if (e == null) throw new NullPointerException(); elements[head = (head - 1) & (elements.length - 1)] = e;//首次數組容量默認為16,head=(0-1)&(16-1)=15 if (head == tail) doubleCapacity(); } /*每次擴容都按插入的先后順序重新放入一個新的數組中,最新插入的放在數組的第一個位置。*/ private void doubleCapacity() { assert head == tail; int p = head; int n = elements.length; int r = n - p; // number of elements to the right of p int newCapacity = n << 1; if (newCapacity < 0) throw new IllegalStateException("Sorry, deque too big"); Object[] a = new Object[newCapacity]; System.arraycopy(elements, p, a, 0, r); System.arraycopy(elements, 0, a, r, p); elements = (E[])a; head = 0; tail = n; } public E removeFirst() { E x = pollFirst(); if (x == null) throw new NoSuchElementException(); return x; } public E pollFirst() { int h = head; E result = elements[h]; // Element is null if deque empty if (result == null) return null; elements[h] = null; // 重新設置數組中的這個位置為null,方便垃圾回收。 head = (h + 1) & (elements.length - 1);//將head的值回退,相當於將棧的指針又向下移動一格。例如,12--〉13 return result; } public E peekFirst() { return elements[head]; // elements[head] is null if deque empty }