程式設計師,你應該知道的數據結構之棧
- 2019 年 10 月 3 日
- 筆記
數據結構中的棧不要與 Java 中的棧混淆,他們倆不是一回事,數據結構中的棧是一種受限制的線性表,棧具有先進後出、後進先出的特點,因為棧只允許訪問最後一個數據項,即最後插入的數據項。也許你會有疑問,棧既然有這麼多限制,為什麼不用數組或者鏈表而使用棧?在開發中,我們有特定的場景,根據特定的場景去選用數據結構,棧的適用場景非常多,比如瀏覽器的前進與後退、字元串括弧的合法性等,我們使用棧來實現就比較好,因為棧相對數組、鏈表來說對外提供的介面要少很多,介面少了,出錯的概率就減少了,對風險的可控性就提高了。
實現一個棧
從棧的定義中可以看出,棧主要有兩個操作,一個是新增一條數據,我們叫做入棧,另一個是獲取一條數據,稱為出棧,下面兩張圖是入棧出棧示意圖。


棧的實現有兩種方式,一種是基於數組實現的,我們叫作順序棧,另一種是基於鏈表實現的,我們叫作鏈式棧。下面是兩種棧的實現程式碼
基於數組的順序棧
/** * 基於數組的順序棧 */ public class ArrayStack { // 棧最大容量 private int maxSzie; // 存放內容 private String[] array; // 棧頂元素 private int top; public ArrayStack(int size){ this.maxSzie = size; this.array = new String[this.maxSzie]; this.top = 0; } /** * 入棧操作 * * @param data 數據 * @return 0:入棧失敗 1:入棧成功 */ public int push(String data) { if (top == maxSzie) return 0; array[top] = data; top++; return 1; } /** * 出棧操作 * * @return */ public String pop() { if (top == 0) return null; return array[--top]; } /** * 獲取棧頂元素 * * @return */ public String peek() { return array[top - 1]; } /** * 判斷棧是否為空 * @return */ public boolean isEmpty() { return top == 0; } } 基於鏈表的鏈式棧
/** * 基於鏈表的鏈式棧 */ public class LinkStack { // 始終指向棧的第一個元素 private Node top = null; /** * 壓棧 * * @param data * @return */ public int push(String data) { Node node = new Node(data); if (top == null) { top = node; } else { node.next = top; top = node; } return 1; } /** * 出棧 * * @return */ public String pop() { if (top == null) return null; String data = top.getData(); top = top.next; return data; } /** * 節點資訊 */ private static class Node { private String data; private Node next; public Node(String data) { this.data = data; this.next = null; } public String getData() { return this.data; } } } 棧的實現比較簡單,因為棧涉及的操作不多,主要就入棧和出棧兩個操作。
棧的應用
檢測字元串括弧的合法性
我們有時候需要檢測字元串括弧的合法性,即一個左括弧需要匹配一個右括弧,這個我們可以使用棧來實現。我們可以從一個合法的括弧來理解為什麼使用棧?如果括弧使用合法,最後一個左括弧跟第一個右括弧是匹配的,倒數第二個左括弧和第二個右括弧匹配的,以此類推,這符合我們棧的特性先進後出。
假設我們有三種括弧:圓括弧 ()、方括弧 [] 和花括弧{},我們使用棧來檢測括弧的合法性。我們將左括弧全部壓棧,當出現右括弧時,我們就進行匹配,這時候有如下三種情況:
- 棧為空,說明沒有左括弧,括弧使用不合法
- 棧中取出來的左括弧跟右括弧不匹配,括弧使用不合法
- 棧中取出的左括弧跟右括弧匹配,括弧使用暫時合法
當整個字元串都掃描完成後,檢測棧中是否還有值,如果棧為空,則說明括弧使用合法,反正,則括弧使用不合法。
實現程式碼
public static boolean BracketChecker(String data) { char[] chars = data.toCharArray(); ArrayStack stack = new ArrayStack(chars.length); for (char ch : chars) { switch (ch){ case '{': case '[': case '(': stack.push(ch); break; case '}': case ']': case ')': if (!stack.isEmpty()){ char ch1 = stack.pop(); if ((ch=='}' && ch1 !='{') ||(ch==']' && ch1 !='[') ||(ch==')' && ch1 !='(') ){ return false; } }else { return false; } break; default: break; } } return stack.isEmpty(); } 瀏覽器前進、後退功能
我們使用瀏覽器都知道,瀏覽器可以前進、後退功能,瀏覽器的前進後退也符合棧的特點,我們最先訪問的網頁肯定要最後才能倒回去。我們一起來看看棧怎麼實現這個功能?
我們需要定義兩個棧,我們將首次訪問的頁面壓棧到第一個棧中,當點擊後退時,從第一個棧中取出數據放入到第二個棧,當點擊前進按鈕時,從第二個棧取出數據放入第一個棧。當第一個棧沒有數據時,說明沒有頁面可以點擊後退了,當第二個棧沒有數據時,說明沒有頁面可以點擊前進了。這樣我們就通過棧實現了瀏覽器前進、後退功能。
最後
打個小廣告,金九銀十跳槽季,平頭哥給大家整理了一份較全面的 Java 學習資料,歡迎掃碼關注微信公眾號:「平頭哥的技術博文」領取,祝各位升職加薪。
