棧,在這里說的是一種數據結構。
你還可能知道的棧
提到“棧”,做Java的同學還會想起Java內存模型中的“棧”,與之緊密關聯的還有一個名詞——堆,但是這里,此棧非彼棧。
引用《深入理解Java虛擬機》中有關棧的介紹
經常有人把Java內存區分為堆內存(Heap)和棧內存(Stack),這種分法比較粗糙,Java內存區域的划分實際上遠比這復雜。這種划分方式的流行只能說明大多數程序員最關注的、與對象內存分配關系最密切的內存區域是這兩塊。其中所指的“堆”筆者在后面專門講述,而所指的“棧”就是現在講的虛擬機棧,或者說是虛擬機棧中局部變量部分。
局部變量表存放了編譯可知的各種基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,它不等同於對象本身,可能是一個只想對象起始地址的引用指針,也可能是指向一個對象的句柄或其他與此對象相關的位置)和returnAddress類型(指向了一條字節碼指令的地址)
說人話就是,Java內存結構中的一部分,線程私有,用來存儲指定的數據類型數據。
棧是什么
棧是一種數據結構,它有自己的特點
-
它是一種線性表,同為線性表的還有之前說到的數組和鏈表
-
它操作受限,具體表現在先進后出,后進先出,只能在一端進行數據的插入和刪除
基於以上兩點,大概就能勾勒出棧的模樣。
棧的應用
經常聽到有很多人抱怨說(也包括我~~~),如果知道這門課這么重要,我當時拼死老命也要把它學好。
還記得當時看吳恩達的《machine learning》,在前幾節課里展示了如何使用聚類算法進行圖像處理,如果使用增強學習算法讓一個模型飛機飛起來
那么,我們來看下棧有什么應用
棧在表達式求值中的應用
給出一個表達式“3+5*8-6”,如果讓你算,想必難不倒你。
交給機器做,肯定也難不倒它,機器甚至可以做更加復雜的你做不到的運算。
但是機器底層是怎么做的,如果不給定規則,它並不知道加減乘除是什么,也不知道他們的優先級順序。所以,這時候棧就排上了用場。
具體做法:
准備兩個棧,一個用來存儲需要運算的數字,一個用來存儲運算符號。
數字棧按照從左到右的順序入棧,符號棧也是如此,只是除此之外還多了一個規則限定。
當新入棧的符號優先級比當前棧頂符號的優先級高的時候,繼續入棧;當比棧頂符號優先級低或者相同時,則取出當前棧頂符號,同時取出數字棧的操作數字進行運算,將運算后的結果壓棧,直至兩個棧元素全部彈出。
具體看專題中給出的過程圖
棧在括號匹配中的應用
給出一串“{(({[{{}}]}))}”,需要校驗這串表達式中是否能前后一一匹配。
沒錯,這個也可以利用棧的特性解決。
具體做法:
從左到右掃描表達式,對於左括號入棧,遇到右括號則取出當前棧頂元素,如果發現匹配,則取出棧頂元素繼續匹配。
當所有字符串匹配完成,並且棧最后是空棧,說明字符串可以正確匹配。
棧在瀏覽器前進后退中的應用
在瀏覽器中,我們可以通過前進后退回到自己想要的網頁。
這個功能也是可以通過棧來實現的,具體做法:
准備兩個棧,一個用於存放前進棧的網頁ID,一個用於存放后退棧的網頁ID。當需要前進的時候,從前進棧取出棧頂元素,並將該元素放入后退棧中;
當需要后退的時候,從后退棧取出棧頂元素,並將該元素放入前進棧中。
具體實現參見項目rome中的BackAndForwardUtil和BackAndForwardUtilDemo類
如何實現一個棧
采用鏈表接口實現一個棧結構
package com.jackie.algo.geek.time.chapter8_stack;
/**
* @Author: Jackie
*/
public class Stack {
private Node top = null;
/**
* 壓棧
* @see com.jackie.algo.geek.time.chapter6_linkedlist.LinkedList 中的insertToHead方法和這里的push思想類似
*
* |------|
* | node | 上移后的top在這個位置
* |------|
* | p | 一開始top在這里,經過node.next = top綁定了node和p關系后,又通過top = node,則將top上移
* |------|
* | ... |
* |------|
*
*/
public void push(int value) {
Node node = new Node(value, null);
if (top == null) {
top = node;
} else {
node.next = top;
top = node;
}
}
/**
* 出棧
*/
public int pop() {
if (top == null) {
return -1;
}
int value = top.value;
top = top.next;
return value;
}
public void printAll() {
Node p = top;
while (p != null) {
System.out.print(p.value + " ");
p = p.next;
}
System.out.println();
}
public static class Node {
private int value;
private Node next;
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
}
}
具體參見項目rome
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。