堆栈计算/二叉树表达简单数学表达式

本文介绍了如何使用堆栈计算方法处理数学表达式,遵循运算符优先级,递归计算并压栈。同时,通过构建二叉树来表示加减乘除、括号和乘方,利用前序遍历来分离运算符和数字,实现数学表达式的固化和embedding表示。二叉树结构揭示了运算优先级,便于按优先级分块处理。

 利用堆栈方式,入栈出栈&运算符运算等级,进行计算; 同一级的运算符,递归计算完,作为一个整体,压入栈;如此反复;按照运算优先级递增的顺序压栈,如果出现非此顺序计算符,则将原来的运算符&数字出栈计算,结果再压栈;



# ELEMENT=['+','-','*','/']
import re

LEVEL_1=['+','-']
LEVEL_2=['*','/']
LEVEL_3=['(']
LEVEL_4=[')']

def is_symbol(element):
    if element in LEVEL_1+LEVEL_2+LEVEL_3:
        return True
    return False

def priority(top_sym,wait_sym):
    if top_sym in LEVEL_1:
        if wait_sym in LEVEL_1:
            return '>'
        else:
            return  '<'
    elif top_sym in LEVEL_2:
        if wait_sym in LEVEL_2:
            return '>'
        elif wait_sym in LEVEL_3:
            return '<'
        elif wait_sym in LEVEL_1:
            return '>'
        else:
            raise ValueError('impossible')
    elif top_sym in LEVEL_3:
        if wait_sym in LEVEL_4:
            return '='
        else:
            return '<'



def calculate(num1,sym1,num2):
    if sym1=='+':
        return num1+num2
    elif sym1=='-':
        return num1-num2
    elif sym1=='*':
        return num1*num2
    elif sym1=='/':
        return num1/num2

def init_action(expression):
    expression_l=[]
    neg_pattern=re.compile('(\-\d+\.*\d*)')
    # init_l=[i for i in re.split('(\-\d+\.*\d*)',expression) if i]  ##?? 为何要根据 -\d 进行切分
    expressions=neg_pattern.split(expression)
    expressions=[elem for elem in expressions if elem]
    for expression_iter in expressions:
        if len(expression_l)==0 and neg_pattern.search(expression_iter):
            expression_l.append(expression_iter)
            continue

        cur_elems=[]
        expression_iter=list(expression_iter)
        tmp_nums=[]
        while len(expression_iter)>0:
            iter_elem=expression_iter.pop(0)
            if iter_elem in LEVEL_1+LEVEL_2+LEVEL_3+LEVEL_4:
                if tmp_nums:
                    cur_elems.append(float(''.join(tmp_nums)))
                    tmp_nums=[]
                cur_elems.append(iter_elem)
            else:
                tmp_nums.append(iter_elem)
        if tmp_nums:
            cur_elems.append(float(''.join(tmp_nums)))
        expression_l.extend(cur_elems)
        for char_iter in expression_iter:
            expression_l.append(char_iter)
    return expression_l

def main(expression):
    expression_l=init_action(expression=expression)
    symbol_stack=[]
    number_stack=[]

    for index,elem_iter in  enumerate(expression_l):
        # elem_iter=expression_l.pop(0)
        if not is_symbol(elem_iter) and index!=(len(expression_l)-1):
            number_stack.append(float(elem_iter))
            continue
        if not is_symbol(elem_iter) and index == (len(expression_l) - 1):
            number_stack.append(float(elem_iter))

        if len(symbol_stack)==0:
            symbol_stack.append(elem_iter)
            continue
        while True:
            if len(symbol_stack)==0:
                break
            # top_sym=symbol_stack.pop()
            if index==(len(expression_l)-1) and len(symbol_stack)>0:
                priority_symbol='>'
            elif len(symbol_stack)==0:
                break
            else:
                priority_symbol=priority(top_sym=symbol_stack[-1],wait_sym=elem_iter)
            if priority_symbol=='<':
                # symbol_stack.append(elem_iter)
                break
            elif priority_symbol=='>':
                right_number=number_stack.pop()
                left_number=number_stack.pop()

                # right_number=expression_l.pop())
                calc_symbol=symbol_stack.pop()
                new_num=calculate(num1=left_number,sym1=calc_symbol,num2=right_number)
                number_stack.append(new_num)
                # symbol_stack.pop()
                # symbol_stack.append(top_sym)
            elif priority_symbol=='=':
                raise ValueError('还没有处理')
            else:
                raise ValueError('**********ERROR**********')
        symbol_stack.append(elem_iter)
    if len(number_stack)==1:
        print(number_stack)
    elif len(number_stack)==2 and len(symbol_stack)==1:
        final_number=calculate(number_stack[0],symbol_stack.pop(),number_stack[1])
        print(final_number)
    else:
        print(number_stack)
        raise ValueError('what??')

if __name__=='__main__':
    a='5+6*4*3-10'
    main(expression=a)
    # print(r)











将加减乘除括号乘方表达式,建立二叉树, 数字作为叶子节点,终止计算,运算符号作为中间节点;优先级低的在最上层一层,其次是优先级高的在下面一层,进行结合;括号在最上面一层进行结合;因为是pre-order遍历&运算符在上&数字在下,所以 运算符&数字可以分开存储,然后进行concat;

from typing import List

priority={
    '+':0,
    '-':0,
    '*':1,
    '/':1
}



def from_infix_to_prefix(expression:List):
    res=[]
    st=[]
    expression.reverse()
    for elem in expression:
        if elem in [')']:
            st.append(elem)
        elif elem in ['(']:
            last_sym=st.pop()
            while last_sym!=')':
                res.append(last_sym)
                last_sym=st.pop()
        elif elem in priority:
            # if len(st)>0 and priority[elem]<priority[st[-1]]:
            while len(st)>0 and st[-1] not in [")", "]"] and   priority[elem]<priority[st[-1]]:
                res.append(st.pop())
            st.append(elem)
        else:
            res.append(elem)
    while st:
        res.append(st.pop())
    res.reverse()
    print(res)
    return res
if __name__=='__main__':
    expression = '4+5*6*2-8*7-10'
    expression = ['4', '+', '5', '*', '6', '*', '2', '-', '8', '*', '7', '-', '10']

    expression='4+5*6*(2-8)*7-10'
    expression=['4','+','5','*','6','*','(','2','-','8',')','*','7','-','10']

    from_infix_to_prefix(expression=expression)

应用:对数学表达式进行固化表达,同一套表达逻辑;得到整体的embedding表达; 二叉树可以代表一种运算的优先级,底层优先级高,上层优先级低;  二叉树视为多个&多层二叉树的叠加累积,所以可以根据计算优先级,进行分块处理;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值