棧——一種操作受限的線性表

  • 不是在說內存中的堆棧,這裏的棧是指一種數據結構,可以基於數組或者鏈表實現;
  • 基於數組:順序棧
  • 基於鏈表:鏈式棧
  • 單從功能上來說,數組和鏈表都可以替代棧這種數據結構,但是數組和鏈表是最基礎的數據結構,操作上自由靈活,使用不可控易出錯,而在操作上做了限制,使得棧只能在特定的場景下使用;
  • 當某個數據集合只涉及在一端插入刪除數據,並且滿足 先進後出,後進先出 的特性,首選 “”這種數據結構。

特點

  • 先進後出,後進先出

順序棧

  • 基於數組構造,通過限制操作,只開放特定的操作接口,來實現,因爲操作受限,有固定的操作特定,所以才叫做棧。
  • 如下基於數組實現了一個順序棧,開放的操作有:push入棧(將元素壓入棧頂),pop出棧(彈出棧頂元素),peek查看棧頂;
public class ArrayStack {
    private String[] items;
    private int size;
    private int capacity;

    /**
     * 構建一個數組棧
     * @param capacity 指定棧容量
     */

    public ArrayStack(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.items = new String[capacity];
    }

    /**
     * 壓入棧
     * @param item
     * @return
     */
    public boolean push(String item){
        if(size==capacity){
            return false;
        }
        items[size++] = item;
        return true;
    }

    /**
     * 彈出棧頂元素
     * @return
     */
    public String pop(){
        if(size==0){
            return null;
        }
        return items[--size];
    }

    /**
     * 查看棧頂元素
     * @return
     */
    public String peek(){
        if(size==0){
            return null;
        }
        return items[size-1];
    }
}
  • 基於數組實現的棧在容量上是由限制的,不過可以實現支持動態擴容,但每次擴容需要搬移數據;
  • 插入複雜度最好O(1),最壞O(n),均攤O(1),刪除(pop出棧)O(1);
  • 基於鏈表實現的棧不存在擴容的問題;
	/**
     *  成長因子,數組容量不夠時,擴容(java數組容器默認應該是1.5倍)
     */
    private static final int GROW_FACTOR = 2;

    /**
     * 內部使用 ,擴充容量
     */
    private void addCapacity(){
        //容量翻倍
        //搬移數據到新數組
        //...
    }

應用場景

函數調用棧

  • 用來存儲函數調用時需要的臨時變量
  • 每進入一個函數,就會將一個臨時變量作爲一個棧壓入棧
  • 當函數調用執行完成,將這個函數的對應棧幀全部出棧
  • 至於爲什麼使用棧,那也是因爲函數調用符合後進先出的特性

利用棧實現表達式求值

  1. 需要用到兩個棧,一個存數值,一個存運算符
  2. 列出運算符優先級,例如( ) * / + - =,從高到低
  3. 從左到右遍歷表達式,遇到數字壓入數值棧,遇到運算符,與運算符棧頂比較優先級
  4. 棧頂運算符相較優先級高:則彈出棧頂運算符和先後連續彈出數值棧頂兩個數值a,b,用彈出的運算符對這兩個進行運算【後彈出b 運算符 先彈出a】,運算結果入數值棧,剛纔遍歷到的運算符繼續和運算符棧頂比較優先級
  5. 棧頂運算符相較優先級低:運算符入棧
  6. 直至棧空

括號匹配檢查

  1. (),{},[]假設兩兩嵌套 ({})、{()}、([])、[()]、{[()]}…都合法
  2. 遍歷表達式,屬於左括號入棧,屬於右括號則與棧頂元素匹配
  3. 如果左右括號不匹配(不是左右匹配或者類型不匹配)則表達式格式非法
  4. 如果括號匹配,則彈出棧頂元素,繼續遍歷下一個。

兩個棧,模擬瀏覽器前進後退功能;

兩個棧X,Y
1、首次瀏覽的頁面 ,壓入X
2、前進-無效,後退,彈出X棧頂,壓入Y
3、前進-彈出Y棧頂,壓入X, 後退 -彈出X棧頂,壓入Y

X棧空 不能後退
Y棧空 不能前進

熄燈

  • 數組和鏈表是最基礎的數據結構,從功能上來說,數組或鏈表確實可以替代棧,
  • 但特定的數據結構是對特定場景的抽象,而且數組或鏈表暴露了太多的操作接口,操作上的確靈活自由,但使用時就比較不可控,自然也就更容易出錯。
  • 棧、隊列、堆以及樹都是在數組或者鏈表的基礎上加入了特定的屬性和操作限制的,適應不同場景的 應用型的數據結構。
  • 操作受限制,但在特定的場景使用方便 ,可以實現一個棧類,特有屬性,和特有的操作。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章