• 前缀(波兰式)、中缀、后缀(逆波兰)表达式;中缀转后缀


    前缀表达式的计算机求值

    注意:在前缀表达式中,遇到运算符时,如“-”,是栈顶元素 - 次顶元素

    中缀表达式

    后缀表达式

     注意:在后缀表达式中,遇到运算符时,如“-”,是次顶元素 - 栈顶元素

    逆波兰计算器

    思路如后缀表达式中的第二张图所示

    代码实现如下:

    1. # 用数组模拟栈
    2. class ArrayStack:
    3. def __init__(self, size):
    4. self.max_size = size # 栈的最大容量
    5. self.top = -1 # top 表示栈顶
    6. self.stack = [] # 用列表表示数组
    7. # 判断栈满
    8. def is_full(self):
    9. return self.top == self.max_size - 1
    10. # 判断栈空
    11. def is_empty(self):
    12. return self.top == -1
    13. # 入栈
    14. def push(self, ele):
    15. if self.is_full():
    16. print("栈已满")
    17. else:
    18. self.top += 1
    19. self.stack.insert(self.top, ele)
    20. # 出栈
    21. def pop(self):
    22. if self.is_empty():
    23. print("栈空")
    24. else:
    25. val = self.stack.pop(self.top)
    26. self.top -= 1
    27. return val
    28. # 实现逆波兰表达式
    29. def poland(expression: str):
    30. # 以空格分割输入的逆波兰表达式
    31. str_list = expression.split(" ")
    32. # 创建操作数栈
    33. num_stack = ArrayStack(len(str_list))
    34. operator = {
    35. "+": lambda x, y: x + y,
    36. "-": lambda x, y: x - y,
    37. "*": lambda x, y: x * y,
    38. "/": lambda x, y: x / y
    39. }
    40. # 从左往右遍历逆波兰式列表
    41. for i in str_list:
    42. try:
    43. i = float(i)
    44. # 遇到数字将其压入操作数栈
    45. num_stack.push(float(i))
    46. except Exception: # 遇到运算符弹出两个操作数进行运算,并将结果压入数栈
    47. # 弹出两个操作数,注意是 次顶元素 运算符(如 -) 栈顶元素
    48. num2 = num_stack.pop()
    49. num1 = num_stack.pop()
    50. res = operator[i](num1, num2)
    51. if res:
    52. # 将运算结果压入栈
    53. num_stack.push(res)
    54. else:
    55. raise ValueError("不支持运算符{}".format(i))
    56. print("运算结果为:", num_stack.pop())
    57. poland("3 4 + 5 * 6 -")
    58. poland("4 5 * 8 - 60 + 8 2 / +")

    中缀表达式转后缀表达式

    思路分析

    示意图

    例子:将中缀表达式:1+((2+3)* 4)-5  转为后缀表达式: 1 2 3 + 4 * + 5 - 

    代码实现 

    1. # 用数组模拟栈
    2. class ArrayStack:
    3. def __init__(self, size):
    4. self.max_size = size # 栈的最大容量
    5. self.top = -1 # top 表示栈顶
    6. self.stack = [] # 用列表表示数组
    7. # 判断栈满
    8. def is_full(self):
    9. return self.top == self.max_size - 1
    10. # 判断栈空
    11. def is_empty(self):
    12. return self.top == -1
    13. # 入栈
    14. def push(self, ele):
    15. if self.is_full():
    16. print("栈已满")
    17. else:
    18. self.top += 1
    19. self.stack.insert(self.top, ele)
    20. # 出栈
    21. def pop(self):
    22. if self.is_empty():
    23. print("栈空")
    24. else:
    25. val = self.stack.pop(self.top)
    26. self.top -= 1
    27. return val
    28. # 查看栈顶元素
    29. def get_top(self):
    30. if self.is_empty():
    31. print("栈空")
    32. else:
    33. return self.stack[self.top]
    34. # 中缀表达式转后缀表达式
    35. class InfixToPostfix:
    36. def __init__(self, size):
    37. # 1、初始化两个栈 s1, s2
    38. self.s1 = ArrayStack(size)
    39. self.s2 = ArrayStack(size)
    40. def is_high_priority(self, oper1, oper2):
    41. """判断 oper1 的优先级是否大于 oper2,是返回 True"""
    42. priority_dict = {
    43. '+': 0,
    44. '-': 0,
    45. '*': 1,
    46. '/': 1
    47. }
    48. prio1 = priority_dict.get(oper1)
    49. prio2 = priority_dict.get(oper2)
    50. if prio1 is None:
    51. raise ValueError('不支持运算符' + oper1)
    52. if prio2 is None:
    53. raise ValueError('不支持运算符' + oper2)
    54. return prio1 > prio2
    55. def infix2postfix(self, infix_exp: str) -> list:
    56. """将中缀表达式转为后缀表达式返回"""
    57. # 将中缀表达式字符串转换为列表
    58. infix_list = self.str_to_list(infix_exp)
    59. # 2、从左往右遍历中缀表达式,即遍历列表的每一个元素 ele
    60. for ele in infix_list:
    61. # 3、遇到的元素 ele 是数字,直接压入栈 s2
    62. if '0' <= ele <= '9':
    63. self.s2.push(ele)
    64. # 4、遇到的元素 ele 是运算符,按以下三种情况处理:
    65. elif ele != '(' and ele != ')':
    66. while True:
    67. # 4.1、如果栈 s1 为空,或者 s1 栈顶为左括号 ( ,则直接将元素 ele 压入栈 s1
    68. if self.s1.is_empty() or self.s1.get_top() == '(':
    69. self.s1.push(ele)
    70. break
    71. # 4.2、如果不满足4.1,则比较元素 ele 和 s1 栈顶元素的优先级,
    72. # 如果 ele 优先级大于 s1 栈顶元素,则直接将元素 ele 压入栈 s1
    73. elif self.is_high_priority(ele, self.s1.get_top()):
    74. self.s1.push(ele)
    75. break
    76. # 4.3、如果不满足4.1、4.2,则弹出 s1 栈顶元素压入 s2,
    77. # 然后回到 4.1 步重新判断元素 ele 和 s1 栈顶元素的关系
    78. else:
    79. self.s2.push(self.s1.pop())
    80. # 5、遇到的元素 ele 是左括号 ( ,直接压入栈 s1
    81. elif ele == '(':
    82. self.s1.push(ele)
    83. # 6、遇到的元素 ele 是右括号 ) ,依次弹出 s1 元素,并将弹出的元素压入 s2,
    84. # 直到弹出的元素是 左括号 ( ,则停止弹出 s1 元素,并且将弹出的左括号丢弃,不压入栈 s2
    85. else:
    86. val = self.s1.pop()
    87. while val != '(':
    88. self.s2.push(val)
    89. val = self.s1.pop()
    90. # 7、重复步骤2-6,直到列表遍历完毕,将栈 s1 剩余的元素依次弹出压入栈 s2 ,
    91. # 此时栈 s2 中的元素,从栈底到栈顶的顺序就是得到的后缀表达式
    92. while not self.s1.is_empty():
    93. self.s2.push(self.s1.pop())
    94. result = []
    95. # 依次弹出 s2 栈顶元素,并添加到列表 result 中
    96. while not self.s2.is_empty():
    97. result.append(self.s2.pop())
    98. # 将列表 result 反转,得到的才是后缀表达式
    99. result.reverse()
    100. return result
    101. def str_to_list(self, infix_expression: str) -> list:
    102. """将中缀表达式字符串转换为列表"""
    103. # 将字符串转换为列表,并去除字符串中的空格
    104. infix_list = [i for i in infix_expression if i != ' ']
    105. # 遍历列表,将多位数合并成一个字符串
    106. i = 0
    107. while i < len(infix_list):
    108. val = infix_list[i]
    109. # 如果该元素是数字
    110. if '0' <= val <= '9':
    111. next = infix_list[i + 1] if i + 1 < len(infix_list) else None
    112. # 判断列表的下一个元素是不是数字,是的话说明是多位数,需要进行拼接
    113. while next and '0' <= next <= '9':
    114. val += next # 拼接数字
    115. infix_list.pop(i + 1) # 并从列表中移除下一位数字
    116. # 继续判断下一个元素是不是数字,如果是还需要继续拼接
    117. next = infix_list[i + 1] if i + 1 < len(infix_list) else None
    118. # 将拼接好的多位数赋值给i,即列表中遇到的多位数的第一个数字的位置
    119. infix_list[i] = val
    120. i += 1
    121. return infix_list # 返回转换后的中缀表达式列表
    122. # 1+((2+3)* 4)-5 转为后缀表达式: 1 2 3 + 4 * + 5 -
    123. s = '1+((2+3)* 4)-5'
    124. infix_to_postfix = InfixToPostfix(len(s))
    125. print(infix_to_postfix.infix2postfix(s)) # 1 2 3 + 4 * + 5 -

  • 相关阅读:
    sklearn快速入门教程:归一化
    SpringMVC完整版详解
    [论文][表情识别]Towards Semi-Supervised Deep Facial Expression Recognition with An Adaptive Confidence Margin
    Elasticvue - 用于浏览器的免费开源 Elasticsearch GUI
    OpenCV-Python小应用(一):人脸识别
    Python实战:读取MATLAB文件数据(.mat文件)
    吴恩达机器学习-1
    【架构整洁之道系列】(四)软件架构师与软件架构
    Kafka磁盘写满日志清理操作
    tkinter制做一个音乐下载小软件,多种音乐免费听
  • 原文地址:https://blog.csdn.net/2301_77659011/article/details/132590346