数据结构与算法分析(三):基本数据结构(1)


线性数据结构:一旦某个元素被添加进来,它与前后元素的相对位置将保持不变。
真正区分线性数据结构的是元素的添加方式和移除方式,尤其是添加操作和移除操作发生的位置。

1、栈

栈有时也被称作“下推栈”。它是有序集合,添加操作和移除操作总发生在同一端。这种排序被称作LIFO,即后进先出。

用Python实现栈

class Stack:
    # 创建一个空栈。它不需要参数,且会返回一个空栈
    def __init__(self):
        self.items = []
        
    # 检查栈是否为空。它不需要参数,且会返回一个布尔值
    def isEmpty(self):
        return self.items == []

    # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值
    def push(self, item):
        self.items.append(item)

    # 将栈顶的元素移除,它不需要参数,会返回顶端元素,并修改栈的内容
    def pop(self):
        return self.items.pop()

    # 返回栈顶元素,但是并不移除该元素
    def peek(self):
        return self.items[-1]

    # 返回栈中元素的数目
    def size(self):
        return len(self.items)

用栈实现数制转换

在计算机科学中,经常涉及数制转换,比如将十进制转换为二进制,方法就是用该数除以2并记录余数,最后反转余数顺序即可得到对应的二进制数据。这里记录余数并反转输出非常适合栈的处理方式。

def divideBy2(decNumber):
    # 创建空栈用于存放余数
    remstack = Stack()

    # 用该数除以2,将余数存入栈,商降为0之前继续循环
    while decNumber > 0:
        rem = decNumber % 2
        remstack.push(rem)
        decNumber = decNumber // 2

    binString = ""
    # 将栈内的数值依次弹出并拼接在一起
    while not remstack.isEmpty():
        binString = binString + str(remstack.pop())

    return binString

将2换为参数,就能将十进制数转换为任意进制数

def baseConverter(decNumber, base):
    # 创建空栈
    remstack = Stack()
    digits = "0123456789ABCDEF"
    
    while decNumber > 0:
        rem = decNumber % base
        remstack.push(rem)
        decNumber = decNumber // base
    
    newString = ''
    while not remstack.isEmpty():
        newString = newString + digits[remstack.pop()]
    
    return newString

2、前序、中序、后序表达式

对于A * B这样的算式,运算符在数值中间,这种表达式被称作中序表达式,也是大家所熟悉的算式。与之对应的,运算符在数值前面的称之为前序表达式,在数值后面的是后序表达式。

中序表达式前序表达式后序表达式
A + B+ A BA B +
A + B * C+ A * B CA B C * +
(A + B) * C* + A B CA B + C *
A + B * C + D+ + A * B C DA B C * + D +
( A + B ) * (C + D)* + A B + C DA B + C D + *
A * B + C * D+ * A B * C DA B * C D * +
A + B + C + D+ + + A B C DA B + C + D +

将中序表达式转换为后续表达式的步骤:
(1)创建用于保存运算符的空栈opstack,以及一个用于保存结果的空列表。
(2)使用字符串方法split将输入的中序表达式转换为一个列表。
(3)从左到右扫描这个标记列表

  • 如果标记是操作数,将其添加到结果列表的末尾。
  • 如果标记是左括号,将其压入opstack。
  • 如果标记是右括号,反复从opstack栈中移除元素,直到移除对应的左括号。将从栈中取出的每一个运算符都添加到结果列表的末尾。
  • 如果标记是运算符,将其压入opstack栈中。但是,在这之前,需要先从栈中取出优先级更高或相同的运算符,并将它们添加到结果列表的末尾。
    (4)当处理完输入表达式以后,检查opstack。将其中所有剩下的运算符全部添加到结果列表的末尾。
    在这里插入图片描述
    代码实现:
from pythonds.basic import Stack
import string


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 string.ascii_uppercase:
            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)

3、计算后序表达式

假设后序表达式是一个以空格分隔的标记串,其中,运算符标记有*、/、+和-,操作数标记是一位的整数值,结果是一个整数。步骤如下:
(1)创建空栈operandStack
(2)使用字符串split将输入的后序表达式转换为一个列表
(3)从左往右扫描这个标记列表

  • 如果标记是操作数,将其转换成整数并且压入operandStack栈中。
  • 如果标记是运算符,从operandStack栈中取出两个操作数。第一次取出右操作数,第二次取出左操作数。进行相应的算数运算,然后将运算结果压入operandStack栈中。
    (4)当处理完输入表达式时,栈中的值就是结果,将其从栈中返回。
    代码如下:
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
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    else:
        return op1 - op2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值