数据结构-学习之路(二)-计算机计算与栈

**本博客内容根据 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-数据结构

相关文章
相关标签/搜索