Python重现数据结构--栈类的实现,以及计算器的应用

简介

近期看了学长的字节跳动面试,收益匪浅,特别是在其中对算法题的考查。因此,打算重新用Python实现几种数据结构,并且进行相关的应用。

栈的定义,就不重复了。直接上代码

class Stack(object):
    def __init__(self,limit=10):
        self.stack = [] #存放元素
        self.limit = limit #栈容量极限

    def push(self,data): #进栈,将元素放在栈顶
        #判断元素是否溢出
        if len(self.stack) >= self.limit:
            raise IndexError('超出栈容量极限!')
        self.stack.append(data)

    def pop(self):
        #判断栈是否为空
        if self.stack:
            return self.stack.pop()
        else:
            raise IndexError('pop from an empty stack!')

    def peek(self):#查看栈顶元素
        if self.stack:
            return self.stack[-1]#返回队列最后一个元素

    def is_empty(self): #判断栈是否为空
        return not bool(self.stack)

    def size(self): #返回栈的大小
        return len(self.stack)

计算器的实现

实现了栈类之后,将其应用在计算器上:

主要难点:

  1. 输入字符串,如何转换成数字(多位数,而非常规的个位数字)以及符号‘
  2. 中缀表达式转化成后缀
  3. 利用后缀进行计算
1.运算式分割

核心思想:通过判断是否为数字为标准,利用符号位的序号来进行判断数字位的长度。

    # 运算式分割
    sym_list = []  # 符号序列列表
    n = 0   #数字位的长度
    fist_n = 0  #首个数字的位置
    for i in range(0, len(mul)):
        if mul[i].isnumeric():  #如果是数字,则开始计算长度
            n += 1
        else:   #非数字,则将本符号前的数字整个切分append入列表中
            if fist_n != fist_n + n:    #长度为0的情况
                sym_list.append(mul[fist_n:fist_n + n])     #先添加指定长度的数字位
            sym_list.append(mul[i])     #添加符号位
            fist_n = i + 1      #重新开始标记数字的首位置
            n = 0   #重新计算
        if i == len(mul) - 1:   #末尾,直接添加最后的数字
            sym_list.append(mul[fist_n:fist_n + n])
2.逆波兰操作

规则

  1. 如果读入操作数,直接放入输出字符串
  2. 读入“+,-,*,/”等一般运算符,则放入辅助栈中,注意,放入的字符的优先级必须高于栈顶符号优先级。如:如待放入“-”,栈顶为“*”,则需要先将“*”pop,并且放入输出字符转,之后再push“-”入栈。反之,则直接push入栈。
  3. 如果字符串为“(”,则直接入栈,并且之后,无需考虑其优先级。
  4. 如果为“)",则直接pop出所有在”(“之后的字符串,并且依次放入输出字符串。“(”,")"不需要放入输出字符串
  5. 如果最后辅助栈中还有字符,则直接依次pop进输出字符串
    # 逆波兰操作,中缀改后缀
    after_list = []  # 后缀列表
    for i, x in enumerate(sym_list):
        if x.isnumeric():
            after_list.append(x)
        else:
            if stack_sign.is_empty():
                stack_sign.push(x)
            else:
                if x == '(':
                    stack_sign.push(x)
                if x == ')':
                    while stack_sign.peek() != '(':
                        after_list.append(stack_sign.pop())
                    stack_sign.pop()
                if x == '+' or x == '-':
                    while stack_sign.peek() == '*' or stack_sign.peek() == '/':
                        after_list.append(stack_sign.pop())
                    stack_sign.push(x)
                if x == '*' or x == '/':
                    stack_sign.push(x)
    while not stack_sign.is_empty():
        after_list.append(stack_sign.pop())
3.后缀计算

规则

  1. 从输出字符串依次进行,如果为数字,则放入新的辅助栈
  2. 如果为运算符(不需要放入栈),则取出后两位数字(a,b),进行相关计算。得到新的数字c,并且放入栈中。依次进行
  3. 如果最后只剩下一个数字,则为答案。
    #通过后缀表达式计算结果
    for i, x in enumerate(after_list):
        if x.isnumeric():
            stack_acc.push(x)
        else:
            b = float(stack_acc.pop())
            a = float(stack_acc.pop())
            if x == "+":
                c = a + b
            if x == "-":
                c = a - b
            if x == "*":
                c = a * b
            if x == "/":
                c = a / b
            stack_acc.push(c)
    print("ans = ",stack_acc.pop())

完整代码

#File name:栈类的实现,以及计算器的应用
#Author: Long  Version: 1.0  Date:2020.9.29
#Description: 实现计算器的基本操作
import re

class Stack(object):
    def __init__(self,limit=10):
        self.stack = [] #存放元素
        self.limit = limit #栈容量极限

    def push(self,data): #进栈,将元素放在栈顶
        #判断元素是否溢出
        if len(self.stack) >= self.limit:
            raise IndexError('超出栈容量极限!')
        self.stack.append(data)

    def pop(self):
        #判断栈是否为空
        if self.stack:
            return self.stack.pop()
        else:
            raise IndexError('pop from an empty stack!')

    def peek(self):#查看栈顶元素
        if self.stack:
            return self.stack[-1]#返回队列最后一个元素

    def is_empty(self): #判断栈是否为空
        return not bool(self.stack)

    def size(self): #返回栈的大小
        return len(self.stack)

def Mul_det():
    # 运算符ascii码
    # 使用栈实现运算符匹配
    mul = input("请输入运算式").strip()
    stack_sign = Stack(len(mul))  # 操作符栈
    stack_num = Stack(len(mul))  # 操作栈
    stack_acc = Stack(len(mul))  # 辅助栈

    # 运算式分割
    sym_list = []  # 符号序列列表
    n = 0   #数字位的长度
    fist_n = 0  #首个数字的位置
    for i in range(0, len(mul)):
        if mul[i].isnumeric():  #如果是数字,则开始计算长度
            n += 1
        else:   #非数字,则将本符号前的数字整个切分append入列表中
            if fist_n != fist_n + n:    #长度为0的情况
                sym_list.append(mul[fist_n:fist_n + n])     #先添加指定长度的数字位
            sym_list.append(mul[i])     #添加符号位
            fist_n = i + 1      #重新开始标记数字的首位置
            n = 0   #重新计算
        if i == len(mul) - 1:   #末尾,直接添加最后的数字
            sym_list.append(mul[fist_n:fist_n + n])

    # 逆波兰操作,中缀改后缀
    after_list = []  # 后缀列表
    for i, x in enumerate(sym_list):
        if x.isnumeric():
            after_list.append(x)
        else:
            if stack_sign.is_empty():
                stack_sign.push(x)
            else:
                if x == '(':
                    stack_sign.push(x)
                if x == ')':
                    while stack_sign.peek() != '(':
                        after_list.append(stack_sign.pop())
                    stack_sign.pop()
                if x == '+' or x == '-':
                    while stack_sign.peek() == '*' or stack_sign.peek() == '/':
                        after_list.append(stack_sign.pop())
                    stack_sign.push(x)
                if x == '*' or x == '/':
                    stack_sign.push(x)
    while not stack_sign.is_empty():
        after_list.append(stack_sign.pop())

    #通过后缀表达式计算结果
    for i, x in enumerate(after_list):
        if x.isnumeric():
            stack_acc.push(x)
        else:
            b = float(stack_acc.pop())
            a = float(stack_acc.pop())
            if x == "+":
                c = a + b
            if x == "-":
                c = a - b
            if x == "*":
                c = a * b
            if x == "/":
                c = a / b
            stack_acc.push(c)
    print("ans = ",stack_acc.pop())


if __name__ == '__main__':
    Mul_det()
    # sig = ['', '-', '*', '/', '(', ')']
    # mul = re.split("\+|\-|\*|\/|\(|\)",mul)#需要转义字符

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hanzoe_lwh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值