Java栈 Stack
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/120830358
本文出自【趙彥軍的博客】
Java隊列 Queue
Java隊列 Deque
Java隊列 PriorityQueue
Java棧 Stack
Java阻塞隊列 LinkedBlockingDeque
文章目錄
- Stack
- Stack的作用
- 計算中綴表達式
- 小結
Stack
棧(Stack)是一種后進先出(LIFO:Last In First Out)的數據結構。
什么是LIFO呢?我們先回顧一下Queue的特點FIFO:
所謂FIFO,是最先進隊列的元素一定最早出隊列,而LIFO是最后進Stack的元素一定最早出Stack。如何做到這一點呢?只需要把隊列的一端封死:
因此,Stack是這樣一種數據結構:只能不斷地往Stack中壓入(push)元素,最后進去的必須最早彈出(pop)來:
Stack只有入棧和出棧的操作:
- 把元素壓棧:push(E);
- 把棧頂的元素“彈出”:pop();
- 取棧頂元素但不彈出:peek()。
在Java中,我們用Deque可以實現Stack的功能:
- 把元素壓棧:push(E)/addFirst(E);
- 把棧頂的元素“彈出”:pop()/removeFirst();
- 取棧頂元素但不彈出:peek()/peekFirst()。
為什么Java的集合類沒有單獨的Stack接口呢?因為有個遺留類名字就叫Stack,出于兼容性考慮,所以沒辦法創建Stack接口,只能用Deque接口來“模擬”一個Stack了。
當我們把Deque作為Stack使用時,注意只調用push()/pop()/peek()方法,不要調用addFirst()/removeFirst()/peekFirst()方法,這樣代碼更加清晰。
//不推薦 Stack<String> stack = new Stack<>();//推薦 Deque<String> stack = new LinkedList<>(); Deque<String> stack = new ArrayDeque<>();Stack的作用
Stack在計算機中使用非常廣泛,JVM在處理Java方法調用的時候就會通過棧這種數據結構維護方法調用的層次。例如:
static void main(String[] args) {foo(123); }static String foo(x) {return "F-" + bar(x + 1); }static int bar(int x) {return x << 2; }JVM會創建方法調用棧,每調用一個方法時,先將參數壓棧,然后執行對應的方法;當方法返回時,返回值壓棧,調用方法通過出棧操作獲得方法返回值。
因為方法調用棧有容量限制,嵌套調用過多會造成棧溢出,即引發StackOverflowError , 例如:
// 測試無限遞歸調用 public class Main {public static void main(String[] args) {increase(1);}static int increase(int x) {return increase(x) + 1;} }我們再來看一個Stack的用途:對整數進行進制的轉換就可以利用棧。
例如,我們要把一個int整數12500轉換為十六進制表示的字符串,如何實現這個功能?
首先我們準備一個空棧:
然后計算12500÷16=781…4,余數是4,把余數4壓棧:
然后計算781÷16=48…13,余數是13,13的十六進制用字母D表示,把余數D壓棧:
然后計算48÷16=3…0,余數是0,把余數0壓棧:
最后計算3÷16=0…3,余數是3,把余數3壓棧:
當商是0的時候,計算結束,我們把棧的所有元素依次彈出,組成字符串30D4,這就是十進制整數12500的十六進制表示的字符串。
計算中綴表達式
在編寫程序的時候,我們使用的帶括號的數學表達式實際上是中綴表達式,即運算符在中間,例如:1 + 2 * (9 - 5)。
但是計算機執行表達式的時候,它并不能直接計算中綴表達式,而是通過編譯器把中綴表達式轉換為后綴表達式,例如:1 2 9 5 - * +。
這個編譯過程就會用到棧。我們先跳過編譯這一步(涉及運算優先級,代碼比較復雜),看看如何通過棧計算后綴表達式。
計算后綴表達式不考慮優先級,直接從左到右依次計算,因此計算起來簡單。首先準備一個空的棧:
然后我們依次掃描后綴表達式1 2 9 5 - * +,遇到數字1,就直接扔到棧里:
緊接著,遇到數字2,9,5,也扔到棧里:
接下來遇到減號時,彈出棧頂的兩個元素,并計算9-5=4,把結果4壓棧:
接下來遇到*號時,彈出棧頂的兩個元素,并計算2*4=8,把結果8壓棧:
接下來遇到+號時,彈出棧頂的兩個元素,并計算1+8=9,把結果9壓棧:
掃描結束后,沒有更多的計算了,彈出棧的唯一一個元素,得到計算結果9。
小結
棧(Stack)是一種后進先出(LIFO)的數據結構,操作棧的元素的方法有:
- 把元素壓棧:push(E);
- 把棧頂的元素“彈出”:pop(E);
- 取棧頂元素但不彈出:peek(E)。
在Java中,我們用Deque可以實現Stack的功能,注意只調用push()/pop()/peek()方法,避免調用Deque的其他方法。
最后,不要使用遺留類Stack。
總結
以上是生活随笔為你收集整理的Java栈 Stack的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java队列 PriorityQueue
- 下一篇: Java阻塞队列 LinkedBlock