資料結構 棧與棧的應用

2021-09-11 09:24:00 字數 2915 閱讀 8121

棧是非常重要的線性資料結構之一,其中一端為棧頂,加入元素和取出元素全部在棧頂端進行,滿足lifo(last in first out,後進先出)的性質。

考慮這樣乙個問題:

您需要寫一種資料結構,維護一系列數,初始為空。定義其中一端為頂,另一端為底,要求提供三種操作:

(1)格式:111x

xx,表示在最頂端處加入乙個數x

xx;(o(1

)o(1)

o(1)

)(2)格式:2

22,表示輸出最頂端的數,並將其刪除;(o(1

)o(1)

o(1)

)(3)格式:3

33,表示判斷資料結構是否為空。(o(1

)o(1)

o(1)

括號中的數字表示這種操作的期望複雜度。

你可以將這道題想成是乙個瓶子,每次可以向瓶口扔下乙個物品或取出瓶口的物品。

其實這裡要求的資料結構就是棧,滿足在同一端進與出的特性。下面我們來看看具體如何來實現。

可以發現乙個棧中最重要的其實是棧頂的位置,棧中的元素可以儲存在乙個陣列中。有了這樣的概念,我們就可以用乙個帶有棧頂元素位置指標的陣列來完成棧的模擬了(以下陣列名為a)。

我們將陣列的左側定義成棧底(頂的反面),右側為棧頂,那麼我們每次的新增操作其實就是在陣列右側新增乙個元素,如果原來的棧頂元素在陣列中的下標為cur

curcu

r,那麼我們只需將cur

curcu

r向右移動一格(增加1),再將需要加入的元素加入a[c

ur]a[cur]

a[cur]

中即可。

如果要取出棧頂元素,那麼其實直接輸出a[c

ur]a[cur]

a[cur]

即可。如果要達到刪除的目的,我們只需要將cur

curcu

r左移一格(減少1),這樣在新加元素時會自動覆蓋原有的a[c

ur+1

]a[cur+1]

a[cur+

1],所以其實並不必清零。

以下為棧的模擬的模板。上文的a陣列即為**中的val陣列,init可以實現對棧的初始化(其實就是將初始指標清零,相當於刪除所有元素),push能夠加入乙個元素,top返回棧頂元素,pop返回棧頂元素並刪除,empty檢測棧是否為空。

#include

using

namespace std;

const

int maxn=

100010

;struct stack_

;void init_ (stack_ &x)

int push_ (stack_ &x,

int y)

int top_ (stack_ x)

int pop_ (stack_ &x)

bool empty_ (stack_ x)

int main (

)

當然,這只是棧最基礎的形態,下面以兩道題目為例來講一講棧的一些應用。

1. 維護乙個棧,實現三種功能:

(1)向棧頂加入乙個數;(o(1

)o(1)

o(1)

)(2)刪除棧頂的數; (o(1

)o(1)

o(1)

)(3)詢問棧內的最小值。(o(1

)o(1)

o(1)

這是資料結構題的乙個簡單擴充套件,除去最基本的加入、刪除操作外,還有乙個查詢最小值的操作,有一種簡單的思路是在維護棧的同時還維護乙個堆,刪除時同時刪除,但是這樣的話三種操作的複雜度都是o

(log⁡n

)o(\log n)

o(logn

),不能滿足題目要求。

考慮到每次都只會刪除棧頂的元素。如果最小值會發生改變那麼只有可能是棧頂元素為原來的最小值。所以我們可以在維護原有的棧的同時再維護乙個額外的棧,儲存每個時刻的棧內最小值,即若原棧為a

aa,「最小值棧」為b

bb,那麼b[i

]=max⁡1≤

j≤ia

[j]b[i]=\max \limits_a[j]

b[i]=1

≤j≤i

max​a[

j],即i之前元素的最小值,例如:

a:5 1 6 7 0

b:5 1 1 1 0

那麼當我們加入元素的時候,先在a中直接加入,再在b中加入「原有棧頂元素和新元素的最小值」,例如上面粒子中,加入1時,將1與原有棧頂5比較,發現1比5小,因此在b中加入的是1。至於刪除,容易發現只要在兩個棧中都刪除棧頂就可以了,如果要詢問最小值,直接返回b的棧頂即可。

字尾表示式是典型的棧的實際應用。對於讀入進來的數字,我們可以將它加入到乙個棧中,如果遇到了乙個運算子,則取出棧頂的兩個數字,按照相應運算子運算後將結果加回棧中即可,最後輸出棧中剩餘的唯一元素。這是因為運算子的兩個運算元總是最近的兩個數字,而且優先順序是自然從左至右的。計算機計算字尾表示式要比中綴表示式(即我們平時所寫的表示式)更方便快捷一些。

還有一道類似的題目,可以作為習題,基本思路差不多,用棧維護括號序列:

luogu 1739 表示式括號匹配

在c++ stl中,可以直接使用棧,在標頭檔案中,包含pushpop等基本功能。

如果對棧有一定了解,那麼就可以去看一看單調棧的特性和原理了。

資料結構 棧應用

一 算術表示式的中綴表示 把運算子放在參與運算的兩個運算元中間的算術表示式稱為中綴表示式。例如 2 3 4 6 9 算術表示式中包含了算術運算子和算術量 常量 變數 函式 而運算子之間又存在著優先順序,不能簡單地進行從左到右運算,編譯程式在求值時,不能簡單從左到右運算,必須先算運算級別高的,再算運算...

資料結構 棧的應用

要求 首先將運算元棧opnd設為空棧,而將 作為運算子棧opter的棧底元素,這樣的目的是判斷表示式是否求值完畢 2 依次讀入表示式的每個字元,表示式須以 結尾,若是運算元則入棧opnd,若是運算子,則將此運算子c與opter的棧頂元素top比較優先順序後執行相應的操作,具體操作如下 i 若top的...

資料結構 棧的應用

棧是限制插入和刪除只能在乙個位置上進行的表,該位置是表的末端,也叫做棧頂。對棧的操作有進棧和出棧,進棧也叫做插入,出棧也就是刪除最後插入的元素。因此棧也被稱作lifo 後進先出 表。棧通常有兩種實現方式,陣列實現和鍊錶實現。下面是棧的兩個小應用demo 字串逆序 由於棧後進先出的特性,所以棧可以用於...