栈_01_栈的应用:表达式求值

"""
注意,这里只考虑了输入表达式中,参与运算的书都是正数的情况
"""
class Linked_Stack:
    class Node:
        def __init__(self,value,next=None):
            self.value=value
            self.next=next

    """
    LIFO栈的实现(利用链表)
    """
    def __init__(self):
        """
        创建一个空栈
        """
        self._items=None
        self._size=0

    def push(self,value):
        """
        添加一个元素入栈
        :return:
        """
        self._items=self.Node(value,self._items)
        self._size+=1

    def pop(self):
        """
        一个元素出栈
        :return:
        """
        if self.isEmpty():
            raise KeyError("The stack is empty")
        item_value=self._items.value
        self._items=self._items.next
        self._size-=1
        return item_value

    def peek(self):
        if self.isEmpty():
            raise KeyError("The stack is empty")
        item_value=self._items.value
        return item_value

    def isEmpty(self):
        """
        判断栈是否为空
        :return:
        """
        return self._items==None

    def __extensionts(self):
        """
        扩展的功能函数
        :param item:
        :return:
        """
        tempList=[]

        def visitNode(node):
            if not node is None:
                visitNode(node.next)
                tempList.append(node.value)
            return tempList
        visitNode(self._items)
        return tempList

    def __getitem__(self, key):
        """
        支持对容器 self[key] 操作
        :param key:
        :return:
        """
        result_list=self.__extensionts()
        return result_list[key]

    def __iter__(self):
        """
        支持迭代操作
        :return:
        """
        result_list=self.__extensionts()
        return iter(result_list)

    def __str__(self):
        """
        利用list的str实现
        :return:
        """
        result_list=self.__extensionts()
        return str(result_list)

    def size(self):
        """
        返回
        :return:
        """
        return self._size

class Evaluate:
    """
    利用栈计算
    """
    def expression_splite(self,expression):
        """
        将传入表达式解析为 表达式解析单元列表
        :param expression:
        :return:
        """
        #去除字符串表达式首尾的特殊字符
        expression=expression.strip()
        #表达式解析结果列表
        result=[]

        number_item="" #用于存储拼接出来的数字单元

        #遍历表达式中每一个元素
        for cursor_index in range(0,len(expression)):
            #当前元素的值
            item=expression[cursor_index]

            #如果当前元素为操作符,就将操作符直加入操作符栈
            if item in ["(",")","+","-","*","/"]:
                #如果是开头出现的"(",就只将"("加入结果列表
                if item=="(" and cursor_index==0:
                    result.append(item)
                #如果遇到其他运算符,或者"(",就将他们前面的拼接的数字单元加入结果集合中
                else:
                    #如果当前拼接出来的运算数不为空
                    if number_item!="":
                        #将拼接出来的运算数加入栈
                        result.append(float(number_item))
                        number_item=""
                    #将运算符加入栈
                    result.append(item)
            #如果当前元素是数字,那就拼接数字,与符号
            elif item in ["0","1","2","3","4","5","6","7","8","9","."]:
                number_item+=item
                #如果当前元素是最后一个元素,就将最后一个元素加入结果集中
                if cursor_index==len(expression)-1:
                    result.append(float(number_item))

        #返回 表达式 字符串解析结果
        return result

    def generate_postfix_expression(self,expression):
        """
        将输入的中缀表达式转化为后缀表达式
        :param expression:
        :return:
        """
        #获取表达式列表
        linked_list=self.expression_splite(expression)

        #存储操作符的栈
        oper_stack=Linked_Stack()
        #存储后缀表达式处理结果的栈
        postfix_expression_stack=Linked_Stack()
        #操作符 优先级 列表
        oper_dict={'*':2,'/':2,'+':1,'-':1}

        for item in linked_list:
            #如果当前元素是操作符,处理操作符
            if item in ['(',')','+','-','*','/']:
                #如果当前操作符栈为空,就当前操作符加入操作符栈中
                if oper_stack.isEmpty():
                    oper_stack.push(item)
                #如果当前操作符栈不为空,进行相应处理
                else:
                    #如果当前元素为 '(‘,就将'('如栈
                    if item=='(':
                        oper_stack.push("(")
                    #如果当前元素是右括号,执行出栈操作,并将弹出栈的元素加入后缀表达式栈,知道弹出栈的是左括号,括号不加入后缀表达式栈
                    elif item==")":
                        oper=oper_stack.pop()
                        while oper!="(":
                            postfix_expression_stack.push(oper)
                            oper=oper_stack.pop()
                    #如果当前元素是运算符
                    else:
                        #弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
                        #弹出所有大于等于运算符栈的栈定元素(如果有右括号,则截止到右边括号)出现,并将他们加入
                        oper=oper_stack.peek()
                        while oper!="(" and oper_dict[oper]>=oper_dict[item]:
                            #栈顶元素出栈
                            oper=oper_stack.pop()
                            postfix_expression_stack.push(oper)
                            #获取新的栈顶元素的值
                            oper=oper_stack.peek()
                        #将当前元素item 加入操作符栈中
                        oper_stack.push(item)

            #如果当前元素是数字,就将数字入后缀表达式栈
            else:
                postfix_expression_stack.push(item)

        #处理完成表达式列表中每个元素后,将操作符栈的所有元素出栈并加入 后缀表达式栈
        while not oper_stack.isEmpty():
            oper=oper_stack.pop()
            postfix_expression_stack.push(oper)

        #返回后缀表达式栈
        return postfix_expression_stack


    def calculate_expression(self,expression):
        """
        计算表达式的值
        :param expression:
        :return:
        """

        #获取后缀表达式列表
        postfix_expression_stack=self.generate_postfix_expression(expression)
        #关于后缀表达式栈的缩影
        cursor_postfix_expression=0

        #操作数堆栈
        number_stack=Linked_Stack()

        #处理栈中的每个元素
        while cursor_postfix_expression<postfix_expression_stack.size():
            #获取当前栈索引所指向的栈中元素
            item=postfix_expression_stack[cursor_postfix_expression]
            #如果当前元素是运算符
            if item in ["+","-","*","/"]:
                #将参与运算的两个元素入栈,注意:这里一定要是 Arg_01_item 运算符 Arg_02_item,因为,Arg_02_item是栈顶元素也就是后如栈的(运算符右边的数),Arg_01_item是先入栈的(运算符左边的数)
                Arg_02_item=number_stack.pop()
                Arg_01_item=number_stack.pop()
                if item=="+":
                    val=Arg_01_item+Arg_02_item
                elif item=="-":
                    val=Arg_01_item-Arg_02_item
                elif item=="*":
                    val=Arg_01_item*Arg_02_item
                elif item=="/":
                    val=Arg_01_item/Arg_02_item
                else:
                    pass
                #将运算后的结果加入运算符栈中
                number_stack.push(val)
            #如果当前元素是数字
            else:
                #就将数字加入运算数栈
                number_stack.push(item)
            #索引自加1
            cursor_postfix_expression+=1

        #返回最终运算结果,也就是运算数栈中的最后一个元素
        return number_stack.pop()

def check_expression_split():
    """
    测试 表达式 元素解析列表
    :return:
    """
    expression_01="((2+18)/12+144/6.89)/90.28"
    expression_list_01=Evaluate().expression_splite(expression_01)
    print(expression_01," >>>>>>>> ",expression_list_01)

    expression_02="89+(89/33.3-12*(3+23)*4)"
    expression_list_02=Evaluate().expression_splite(expression_02)
    print(expression_02," >>>>>>>> ",expression_list_02)

def check_stack():
    """
    测试 链表栈 的运行是否正常
    :return:
    """
    stack_linked=Linked_Stack()

    for _ in range(10,20):
        stack_linked.push(_)
    print("0>>>>>>>>>>:",stack_linked.size())

    print("-----"*10)

    for _ in stack_linked:
        print("1>>>>>>>>>>:",stack_linked.peek())

    print("-----"*10)

    for _ in range(0,10):
        print("1_1>>>>>>>>:",stack_linked[_])

    print("-----"*10)

    for _ in stack_linked:
        print("2>>>>>>>>>>:",_)

    print("-----"*10)

    print("3>>>>>>>>>>>>>:",stack_linked.isEmpty())

    print("-----"*10)

    for _ in range(0,10):
        pop_value=stack_linked.pop()
        print("4>>>>>>>>>>:",pop_value)

    print("-----"*10)

    print("5>>>>>>>>>>:",stack_linked.isEmpty())

def check_postfix_expression():
    """
    检查后缀表达式的输出结果
    :return:
    """
    expression_01="(2+18)/12"
    expression_list_01=Evaluate().generate_postfix_expression(expression_01)
    print(expression_01," >>>>>>>> ",expression_list_01)

    expression_02="((2+18)/12+144/6.89)/90.28"
    expression_list_02=Evaluate().generate_postfix_expression(expression_02)
    print(expression_02," >>>>>>>> ",expression_list_02)

    expression_03="89+(89/33.3-12*(3+23)*4)"
    expression_list_03=Evaluate().generate_postfix_expression(expression_03)
    print(expression_03," >>>>>>>> ",expression_list_03)

def check_calculation():
    """
    检查计算的结果(运用后缀表达式)
    :return:
    """
    expression_01="(2+18)/12"
    expression_list_01=Evaluate().generate_postfix_expression(expression_01)
    val=Evaluate().calculate_expression(expression_01)
    print(expression_01,"=",eval(expression_01)," >>>>>>>> ",expression_list_01,"=",val)

    expression_02="((2+18)/12+144/6.89)/90.28"
    expression_list_02=Evaluate().generate_postfix_expression(expression_02)
    val=Evaluate().calculate_expression(expression_02)
    print(expression_02,"=",eval(expression_02)," >>>>>>>> ",expression_list_02,"=",val)

    expression_03="89+(89/33.3-12*(3+23)*4)"
    expression_list_03=Evaluate().generate_postfix_expression(expression_03)
    val=Evaluate().calculate_expression(expression_03)
    print(expression_03,"=",eval(expression_03)," >>>>>>>> ",expression_list_03,"=",val)


if __name__=="__main__":
    check_expression_split()
    print("-"*1000)
    check_stack()
    print("-"*1000)
    check_postfix_expression()
    print("-"*1000)
    check_calculation()
“”“
输出结果
((2+18)/12+144/6.89)/90.28  >>>>>>>>  ['(', '(', 2.0, '+', 18.0, ')', '/', 12.0, '+', 144.0, '/', 6.89, ')', '/', 90.28]
89+(89/33.3-12*(3+23)*4)  >>>>>>>>  [89.0, '+', '(', 89.0, '/', 33.3, '-', 12.0, '*', '(', 3.0, '+', 23.0, ')', '*', 4.0, ')']
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0>>>>>>>>>>: 10
--------------------------------------------------
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
1>>>>>>>>>>: 19
--------------------------------------------------
1_1>>>>>>>>: 10
1_1>>>>>>>>: 11
1_1>>>>>>>>: 12
1_1>>>>>>>>: 13
1_1>>>>>>>>: 14
1_1>>>>>>>>: 15
1_1>>>>>>>>: 16
1_1>>>>>>>>: 17
1_1>>>>>>>>: 18
1_1>>>>>>>>: 19
--------------------------------------------------
2>>>>>>>>>>: 10
2>>>>>>>>>>: 11
2>>>>>>>>>>: 12
2>>>>>>>>>>: 13
2>>>>>>>>>>: 14
2>>>>>>>>>>: 15
2>>>>>>>>>>: 16
2>>>>>>>>>>: 17
2>>>>>>>>>>: 18
2>>>>>>>>>>: 19
--------------------------------------------------
3>>>>>>>>>>>>>: False
--------------------------------------------------
4>>>>>>>>>>: 19
4>>>>>>>>>>: 18
4>>>>>>>>>>: 17
4>>>>>>>>>>: 16
4>>>>>>>>>>: 15
4>>>>>>>>>>: 14
4>>>>>>>>>>: 13
4>>>>>>>>>>: 12
4>>>>>>>>>>: 11
4>>>>>>>>>>: 10
--------------------------------------------------
5>>>>>>>>>>: True
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(2+18)/12  >>>>>>>>  [2.0, 18.0, '+', 12.0, '/']
((2+18)/12+144/6.89)/90.28  >>>>>>>>  [2.0, 18.0, '+', 12.0, '/', 144.0, 6.89, '/', '+', 90.28, '/']
89+(89/33.3-12*(3+23)*4)  >>>>>>>>  [89.0, 89.0, 33.3, '/', 12.0, 3.0, 23.0, '+', '*', 4.0, '*', '-', '+']
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(2+18)/12 = 1.6666666666666667  >>>>>>>>  [2.0, 18.0, '+', 12.0, '/'] = 1.6666666666666667
((2+18)/12+144/6.89)/90.28 = 0.24996147019035977  >>>>>>>>  [2.0, 18.0, '+', 12.0, '/', 144.0, 6.89, '/', '+', 90.28, '/'] = 0.24996147019035977
89+(89/33.3-12*(3+23)*4) = -1156.3273273273273  >>>>>>>>  [89.0, 89.0, 33.3, '/', 12.0, 3.0, 23.0, '+', '*', 4.0, '*', '-', '+'] = -1156.3273273273273
”“”

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354