数据结构:栈

一、栈的介绍

        一种有次序的数据项的集合,在栈中,数据项的加入和移除都进发生在同一端。

        特点:后进先出:反转次序

        应用:① 浏览器后退按钮

                   ② Word的“撤销”按钮

  二、用Python实现Stack

        我们可以将 Python List 的任意一端(index=0或者index=-1)设置为栈顶。这里我们选用List的末端(index=-1)作为栈顶这样栈的操作就可以通过对 list 的 append 和 pop 来实现。

# 用list模拟栈的判空、添加、获取栈顶元素、删除、获取栈的长度操作
class Stack():
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self,item):
        self.items.append(item)

    def peek(self):
        return self.items[len(self.items)-1]

    def pop(self):
        return self.items.pop()

    def size(self):
        return len(self.items)


opt = Stack()
opt.push("hello")
print(opt.size()) # output:1
opt.push("cool")
print(opt.peek()) # output:cool
print(opt.isEmpty()) # output:False

三、栈的应用

        在前缀和后缀表达式中,操作符的次序完全决定了运算的次序,不再有混淆。所以在很多情况下,表达式的计算机表示都避免用复杂的中缀形式。

1、中缀表达式转后缀表达式 

# 记录操作符优先级
def infixToPostfix(infixexpr):
    prec = {}
    prec["*"] = 3
    prec["/"] = 3
    prec["+"] = 2
    prec["-"] = 2
    prec["("] = 1
    opStack = Stack()
    postfixList = [] # 后缀表达式列表
    tokenList = infixexpr.split() # 中缀表达式列表

    for token in tokenList:
        # 对操作数做处理
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfixList.append(token)
        # 对 "(" ")" 符号做处理
        elif token == "(":
            opStack.push(token)
        elif token == ")":
            topToken = opStack.pop()
            while topToken != '(':
                postfixList.append(topToken)
                topToken = opStack.pop()
        # 对操作符 "+-*/" 做处理
        else:
            while (not opStack.isEmpty()) and \
                (prec[opStack.peek()] >= prec[token]):
                    postfixList.append(opStack.pop())
            opStack.push(token)
   
    while not opStack.isEmpty():
        postfixList.append(opStack.pop())
    # 输出后缀表达式字符串
    return " ".join(postfixList)

print(infixToPostfix("( 1 + 2 ) * 3 + 8 / 2")) 
# 输出 "1 2 + 3 * 8 2 / +"

2、后缀表达式求值

步骤:①生成一个栈,把输出字符串转换为列表;

          ②循环列表元素:如果元素是操作数就压入栈顶;

          ③循环列表元素:如果是操作数则弹出距离栈顶最近的两个元素,先弹出的是右操作数,后弹出的是左操作数,将计算的结果压入栈顶;

          ④单词列表扫面结束后,栈顶的值就是表达式的值。弹出栈顶的值,返回。

'''后缀表达式求值'''
def postfixEval(postfixExpr):
    operandStack = Stack()
    tokenList = postfixExpr.split()
    for token in tokenList:
        if token in "0123456789":
            operandStack.push(int(token))
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            result = doMath(token,operand1,operand2)
            operandStack.push(result)
    
    return operandStack.pop()


def doMath(op, op1, op2):
    if op == "*":
        return op1 * op2
    if op == "/":
        return op1 / op2
    if op == "+":
        return op1 + op2
    if op == "-":
        return op1 - op2

print(postfixEval("1 2 + 3 * 8 2 / +"))

输出:13.0 

四、思考

题目:有一排商品,每一个商品都有自己的价值,现在需要花一定金额购买这些商品。规则是:如果一个商品的价值比它旁边的一个商品要高,那么这个商品就必须比它旁边的商品花费更多金额。所有的商品至少要进行一次金额购买。假设一次购买花费金额单位为1,最少需要多少金额可以购买所有商品?(题目来自牛客,思考是否能用栈实现)

输入案例:

1 4 2 1

输出:

7

参考资料
学习《数据结构与算法(Python版)》课程笔记。
课程链接:【北京大学】数据结构与算法Python版(完整版).

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值