Python数据结构与算法学习(一)

视频教程:本视频介绍_哔哩哔哩_bilibili

一、栈

栈是一种线性结构,其基本特性就是先进后出(FILO)。

在python中通过列表list能实现栈:

###################################################################
# 栈:先进后出
# 有反转操作的流程,用栈比较合适
###################################################################
# 创建栈类,栈有push、pop、peek、size、isEmpty五种属性
class Stack:
    def __init__(self):
        self.items = []  # 初始化空栈

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

    def push(self, item):  # 入栈
        self.items.append(item)

    def pop(self):  # 出栈
        return self.items.pop()

    def peek(self):  # 找最后一个
        return self.items[-1]
        # return self.items[len(self.items)-1]

    def size(self):  # 栈长度
        return len(self.items)

    def __repr__(self):  # 打印输出
        return self.items

最简单实现栈的代码:

# 极简栈
class simple_Stack(list):
    def push(self, item):
        self.append(item)
    def peek(self):
        return self[-1]
    def isEmpty(self):
        return self == []
    def size(self):
        return len(self)

栈的应用实例:

1、进行括号匹配:

# 进行括号匹配,这部分代码只涉及小括号的匹配
def parChecker(symbolString):  # 仅匹配圆括号
    s = Stack()
    balanced = True  # 是否匹配标志
    index = 0
    while index < len(symbolString) and balanced:  # 没有检索完且匹配
        symbol = symbolString[index]  # 获得字符
        if symbol == '(':  # 左括号入栈
            s.push(symbol)
        else:  # 有括号,进行匹配
            if s.isEmpty():  # 栈已经空了,说明右括号是多的,不匹配
                balanced = False
            else:  # 栈不空,最后一个左括号出栈
                s.pop()
        index = index + 1  # 搜索下一个字符

    if balanced and s.isEmpty():  # 完全匹配
        return True
    else:  # 不完全匹配,左括号是多的
        return False


print(parChecker('((()()))'))
print(parChecker('(()'))

支持小括号、中括号、大括号的匹配:

def match(chr1, chr2):
    opens = ["{", "[", "("]
    closers = ['}', ']', ")"]
    return opens.index(chr1) == closers.index(chr2)

def allparChecker(symbolString):  # 匹配多重括号
    s = Stack()
    balanced = True  # 是否匹配标志
    index = 0
    while index < len(symbolString) and balanced:  # 没有检索完且匹配
        symbol = symbolString[index]  # 获得字符
        if symbol in '{[(':  # 左括号入栈
            s.push(symbol)
        else:  # 有括号,进行匹配
            if s.isEmpty():  # 栈已经空了,说明右括号是多的,不匹配
                balanced = False
            else:  # 栈不空,最后一个左括号出栈
                if match(s.peek(), symbol):
                    s.pop()
                else:
                    balanced = False
        index = index + 1  # 搜索下一个字符

    if balanced and s.isEmpty():  # 完全匹配
        return True
    else:  # 不完全匹配,左括号是多的
        return False


print(allparChecker('({})'))
print(allparChecker('({}])'))
print(allparChecker('([{}])'))

2、十进制转换成n进制,采用取余数的方法,python实现代码如下:

# 十进制转为n进制
def divideBynum(decNumber, base=2):
    digits = '0123456789ABCDEF'  # 设置进制的表示符表
    remstack = Stack()
    while decNumber > 0:  # 除数仍然大于0,继续转化为二进制
        rem = decNumber % base  # 取余数
        remstack.push(rem)  # 余数进栈
        decNumber = decNumber // base  # 除二取整

    binString = ''
    while not remstack.isEmpty():  # 余数栈不为空
        binString = binString + digits[remstack.pop()]  # 取出最后一个余数

    return binString


print(divideBynum(42, 16))

3、中缀表达式转后缀表达式。

中缀表达式指操作符在两个操作数之间,如:A+B;后缀表达式指操作数在两个操作符之后,如:AB+。它们表达同样的意思,即A和B相加。前缀表达式同理。

对于计算机而言,要处理中缀表达式会比较麻烦,而处理后缀表达式则比较简单,所以在处理表达式之前,需要先把输入的中缀表达式转换成后缀表达式,下面为python实现的代码:

# 中缀表达式转后缀表达式
def infixToPostfix(infixespr):
    prec = {}  # 操作符优先级字典
    prec['*'] = 3
    prec['/'] = 3
    prec['+'] = 2
    prec['-'] = 2
    prec['('] = 1
    opStack = Stack()  # 操作符栈
    postfixList = []  # 操作数list
    tokenList = infixespr.split()

    for token in tokenList:  # 取出字符
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token not in prec.keys():  # 对操作数进行
            postfixList.append(token)  # 把操作数记录于操作数list中,因为后缀表达式中操作数在操作符前面,且顺序不会发生改变
        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('A + B / C * D / E'))

4、后缀表达式的计算问题。

从中缀表达式转换成后缀表达式后,再对表达式进行计算:

# 后缀表达式的计算
def doMath(token, operand1, operand2):
    if token == '*':
        result = operand1 * operand2
    elif token == "/":
        result = operand1 / operand2
    elif token == "+":
        result = operand1 + operand2
    else:
        result = operand1 - operand2
    return result

def postfixEval(postfixExpr):
    operandStack = Stack()  # 记录操作数的栈
    tokenList = postfixExpr.split()  # 记录原始表达式
    for token in tokenList:  # 遍历表达式
        if token.isdigit():  # 判断字符串是否为数字
            operandStack.push(float(token))  # 若是数字,进操作数栈
        else:  # 若不为数字,进行数学运算
            operand2 = operandStack.pop()  # 先取出表达式后一个数
            operand1 = operandStack.pop()  # 再取出表达式前一个数
            result = doMath(token, operand1, operand2)  # 进行数学运算
            operandStack.push(result)  # 运算结果进栈

    return operandStack.pop()  # 遍历完表达式,也就计算完了所有的结果,最终栈里只剩下最后的计算结果,作为返回值


print(postfixEval(infixToPostfix('1 + 12 / 3 * 4 / 5')))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值