用棧實現基本計算器

2021-10-19 11:45:59 字數 3334 閱讀 5619

趣味**

**演示

1.3 **演示

實現乙個基本的計算器來計算乙個簡單的字串表示式 s 的值。

示例 1:

​ 輸入:s = 「1 + 1」

​ 輸出:2

示例 2:

​ 輸入:s = " 2-1 + 2 "

​ 輸出:3

因為睡眠不好的原因,總覺得頭脹脹的,精神狀態不好,但每日演算法的斷更又是我所不能接受的。所以這一篇我就用了力扣官方的題解,來為大家解析一下思路並做適當延伸。

題目要求滿足+/-兩種操作符的運算,且運算元都為非負整數,而且包含括號

首先明確的是,對於這種表示式求值的問題,編譯器對於表示式求值都是通過棧來實現的,我們這裡也不例外。

另外小學的知識告訴我們有括號的話,應該先算括號裡面的表示式,再將子表示式求解的結果作為表示式的一部分繼續運算。此外,還有乙個容易忽略的地方,那就是空格!!!很多人出於美觀的程式設計習慣,會在表示式中加入空格,這樣對表示式的求解並沒有影響,但我們在程式設計時需要刻意的忽略空格。最後,需要注意的還有對運算元的處理,在乙個字串中123被認定為三個字元!我們需要使用十進位制的運算知識將三個字元組合在一起處理。

到此,基本計算器的核心部分就完結了,具體的**看最後的**演示部分就ok了。

您可能會說,我點進來你就給我看這個,不是說好有乾貨嗎~

的確,在我看來呢,掌握上面的的確可以解決問題,但它不能作為一種解決問題的通用模式,依靠這種靈光一現的技巧是不長遠的,對於表示式求值的問題,更通用的解法是逆波蘭表示式——

剛好力扣上有這麼一道題,我們來一起小試牛刀吧~

根據逆波蘭表示法,求表示式的值。

有效的運算子包括+,-,*,/。每個運算物件可以是整數,也可以是另乙個逆波蘭表示式。

在分析之前,有必要先聊聊逆波蘭表示式是什麼,為什麼它對於表示式的求解有幫助?

逆波蘭表示式是一種利用棧來進行運算的數學表示式。我們通常使用的表示式是中綴表示式,比如:

( 1+

2)∗(

3−4)

(1+2)*(3-4)

(1+2)∗

(3−4

)計算機求解時會將這個中綴表示式先解析為符號樹,再求值。而解析符號樹需要遞迴遍歷這顆樹,假如表示式比較複雜,也就是樹的深度大時,會申請大量棧空間效能不高,而如果將中綴表示式變成字尾表示式時,情況就有所不同了,只需要很小的棧空間就可以完成操作。

說到這,你可能還是似懂非懂,同樣的表示式內容,為什麼逆波蘭表示式效率就高呢~

這是因為逆波蘭表示式可以簡化表示式的內容,它設計的初衷就是因為可以省略括號,從而減少cpu運算的次數。

既然逆波蘭表示式這麼好用,那怎麼將中綴表示式轉化為逆波蘭表示式呢?那就要看排程車演算法咯——

規則:從左到右遍歷中綴表示式的每個數字和符號,若是數字就輸出,即成為字尾表示式的一部分;若是符號,則判斷其與棧頂符號的優先順序,是右括號或優先順序低於找頂符號(乘除優先加減)則棧頂元素依次出找並輸出,並將當前符號進棧,一直到最終輸出字尾表示式為止。

對於其具體的案例,可以移步這篇博文:

看到這的小夥伴可以舒一口氣了,內功已成,剩下的招式就是信手拈來啦。但是追求更好的效能是乙個coder應該有的習慣,所以我們會從陣列模擬棧兩種思路來求解——

棧求解它的思路可謂非常樸素,我們先遍歷陣列,將所有的運算元入棧,當遇到運算子時,就取出棧頂的兩個元素,並將運算的結果壓棧,

將遍歷得到的字串轉化為整數時,有乙個小細節值得注意:是使用integer.parseint()還是integer.valueof(),它們都可以將字串轉化為整數,但前者比起後者少了裝箱的操作.

陣列模擬棧求解

雖然棧提供了對出棧入棧操作提供了方便的封裝,但也導致其操作不靈活,就拿這句**來看——

完全可以用更簡潔的陣列**實現:

此外,只需要申請乙個陣列用於儲存運算元即可,而假設乙個表示式長度為n,則最懷情況下,這個表示式中只包含運算元,並且運算元只有乙個,也就是

n /2

+1n/2+1

n/2+

1

來自力扣大佬的題解:

/** * 逆波蘭表示式

* */

public

class

solution2

}return res[0]

;}}class

solution

}return stack.

pop();

}}

class

solution

else

if(ch !=

' ')

//左括號

if(ch ==

'(')

else}}

if(n !=0)

stack.

push

(operand)

;return

calculateexp

(stack);}

private

static

intcalculateexp

(stack

stack)

else

}return res;

}}

日拱一卒,功不唐捐。

用棧實現計算器

我們平時用swith語句寫的計算器,只能處理簡單的兩個運算元和乙個運算子,這樣其實和日常應用方面差的有點遠,所以我們今天學習了一種用棧來實現一條複雜表示式的計算。這個需要用到棧的相關知識,除此之外我們還需要學會如何把中綴轉換成字尾表示式,比如 3 4 5 2 3這樣乙個表示式,從左至右遇到運算元壓入...

用棧實現的計算器

問題描述 描述 從鍵盤輸入乙個算術表示式 保證是整數 並輸出它的結果 保證資料中除法是整除 輸入 輸入一行字串表示算術表示式包括0.9,輸出 每行輸出計算結果 規則 1.自左至右掃瞄表示式,凡是遇到運算元一律進運算元棧。2.當遇到運算子時如果它的優先順序比運算子棧棧頂元素的優先順序高就進棧。反之,取...

C C 用棧實現計算器

使用棧實現計算器,最主要的就是進行運算子的優先順序判斷,然後進行對應的計算,然後將其壓入棧和從棧中取出來。其中要對輸入的表示式進行判斷,如果表示式不符合的話就直接不用計算。下面直接上 include include include using namespace std const int maxs...