數據結構-學習之路(二)-計算機計算與棧

**本博客內容根據 Mooc 浙江大學 數據結構 2.2課 堆棧一課總結獲得
若是對於博客中的算法有任何疑問請您斧正**python


問題:

​ 當計算機面對一個複雜的算術表達式要如何進行計算呢?git

思考歷程:

​ 首先若是是3 + 2這個簡單的算術表達式, 咱們能夠從左到右將表達式分解成, 運算數3,2運算符號"+", 而後就能夠輕鬆的獲得結果也就是5, 若是咱們利用機器來計算,那麼也會是一樣的道理。可是咱們知道運算符號是有優先級的,若是咱們如今要計算的表達式是2 + 3/2這樣的一個稍複雜的計算表達式的時候,若是咱們仍是簡單的從左到右進行分解運算數運算符號,那麼這其中就會多出不少複雜的計算斷定。所以, 咱們有了一個更利於計算的表達式後綴表達式面試


什麼是後綴表達:

後綴表達式就是運算符號是在要運算的兩個數以後。而上面兩個咱們在生活中常見的算數表達式也被稱爲中綴表達式。咱們將2 + 3/2 這個中綴表達式變成後綴表達式, 就會得232/+。第一次面對這個後綴表達式確定會感受很奇怪,但若是咱們知道這個表達式是如何運做後,咱們也將會知道爲何後綴表達式更適合計算機來計算。算法


如何經過後綴表達式進行計算:

​ 對於 232/+這個後綴表達式。咱們從左到右進行遍歷,若是獲得是運算數咱們就找"一個地方"進行存儲。express

若是是運算符, 就去存儲的地方找到後進入的兩個運算數,而後進行計算, 接着把結果繼續存儲。數據結構

不斷重複這個過程,直到循環結束,最終咱們就會獲得最後的結果。app

下圖1.1就代表了後綴表達式的運算過程
其中存儲結構最上方爲當前循環的運算數,存儲結構中顯示爲這次循環後存儲結構的結果:學習

image.png

圖1.1 後綴表達式的運算過程

咱們能夠看到咱們利用了一個特殊的存儲方式,先進入到存儲結構的元素反而是最後從存儲結構出來的,這種存儲數據的結構也就是。棧的特色就是先進後出, 每次從棧中推出的元素都是最後進入的元素。棧在計算機計算過程常常會變用到, 在個人理解當中當咱們在計算過程當中若是須要記錄以前的結果而且在後面利用到它,那麼這個時候咱們就均可以利用棧。例如咱們經常使用的遞歸其實也是利用了棧來存儲"上一個結果"的。spa


C1 python中棧的簡單實現:

"""
  要實現一個最簡單的棧,咱們基本只要實現兩個方法,

  一個是棧的push方法,把元素壓入棧裏面。

  另外一個就是pop方法,把棧的最後一個元素推出並返回該元素
"""
class Stack:

  # 不要讓類變量是可變對象
  # values = []

  def __init__(self):
      self.values = []

  def __getitem__(self, item):
      return self.values.__getitem__(item)

  def push(self, value):
      self.values.append(value)

  def pop(self):
      return self.values.pop()

  def __len__(self):
      return len(self.values)

如何把中綴表達式變成後綴表達式:

首先咱們仍是循環中綴表達式, 這個時候咱們不關心數字, 因此咱們當咱們遇到數字就直接輸出這個數字。code

而當咱們遇到的是運算符的時候,咱們就要先把這個運算符和棧裏面已有的運算符進行比較,由於咱們在計算的時候會先計算優先級高的運算符,因此咱們要把棧裏面比當前循環到的運算符優先級高的運算符輸出,而後把當前的這個運算符壓棧。

固然有一個特殊的運算符號也就是"()" 括號,這個時候咱們就要特殊處理了,若是是"(",咱們直接入棧,若是遇到了 ")"這個時候咱們就要把棧裏面"("後面的全部運算符都出棧。最後若是循環結束,這時候咱們就要把棧裏面剩下的全部運算符都出棧


C2 python中中綴表達式變後綴的簡單實現:

"""
只是簡單實現 不考慮中綴表達式中的浮點數, 
而且只簡單的處理 "*","/","+","-","(",")"等符號
"""
def convert_the_infix_expression_to_suffix_expression(infix_expression: str) -> list:
    """
    :param infix_expression:
    :return:

    Usage::
        >>> convert_the_infix_expression_to_suffix_expression("3 + 2 / 4")
        [3, 2, 4, "/", "+"]
    """
    res = []
    operator_stack = Stack()

    # 存儲符號的等級
    operator_ranks = {
        "*": 2,
        "/": 2,
        "+": 1,
        "-": 1,
        "(": 0,
        ")": 0
    }
    for operator in infix_expression:
        if operator.isdigit():
            # 數字直接存入
            res.append(int(operator))
        else:
            # 操做符要和stack裏面的進行比較
            if operator == "(":
                operator_stack.push(operator)
            elif operator == ")":
                # 遇到右括號把棧裏面(上的全部符號pop出來
                while operator_stack and operator_stack[-1] != "(":
                    res.append(operator_stack.pop())
                # 把 "("拋出
                operator_stack.pop()
            elif operator.isspace():
                continue
            else:
                # 把棧裏面全部優先級 >= 當前運算符的都拋出
                # 而後把當前運算符加入
                while operator_stack and operator_ranks[operator_stack[-1]] >= operator_ranks[operator]:
                    res.append(operator_stack.pop())
                operator_stack.push(operator)
    #  把符號棧裏面的全部符號拋出
    while operator_stack:
        res.append(operator_stack.pop())
    return res

總結:

​ 經過上述的學習,咱們也就能夠了解到了中綴表達式, 後綴表達式,以及在面試當中會問到的中綴到後綴的轉換。


參考

Mooc-數據結構

相關文章
相關標籤/搜索