第三章 基本结构(上)

第三章 基本结构(上)

301 什么是线性结构

  1. 线性结构:是指有序的数据项集合,每个数据项都有唯一的前驱和后继。
    (1)除了第一个没有前驱和最后一个没有后继。
    (2)数据插入数据集中都是在某一个数据之后或者某一个数据之前。
  2. 不同的线性结构关键在于数据项的增减方式,主要有四种:栈(stack)、队列(queue)、
    双端队列(Deque)、列表(list)

302 栈的python实现

  1. 栈的特性:
    (1)加入和移除只发生在栈顶,另外一端为栈底。
    (2)后进先出(LIFO):进入栈的时间越短离栈顶越近,进入栈的时间越久离栈底越近。
    (3)主要特性:实现了数据次序的反转
    (3)主要方法:
    在这里插入图片描述
  2. 栈的python实现
    采用list数据类型来实现栈。可以选择列表的末尾作为栈顶或者选择列表的开头作为栈顶,但是两种方案的时间复杂度不同,选择列表末尾作为栈顶的方案时间复杂度较优。
    选择末尾作为栈顶:
class Stack(object):
    def __init__(self):
        # 采用列表定义栈
        self.stack = list()

    def is_empty(self):
        # 判断栈是否为空
        return self.stack == []

    def push(self, value):
        # 压入栈顶
        return self.stack.append(value)

    def peek(self):
        # 返回栈顶数字
        return self.stack[-1]

    def size(self):
        # 返回栈的长度
        return self.stack.__len__()

    def pop(self):
        # 弹出栈顶数据
        return self.stack.pop()

选择开头作为栈顶

class Stack(object):
    def __init__(self):
        # 采用列表定义栈
        self.stack = list()

    def is_empty(self):
        # 判断栈是否为空
        return self.stack == []

    def push(self, value):
        # 压入栈顶
        return self.stack.insert(0, value)

    def peek(self):
        # 返回栈顶数字
        return self.stack[0]

    def size(self):
        # 返回栈的长度
        return self.stack.__len__()

    def pop(self):
        # 弹出栈顶数据
        return self.stack.pop(0)

栈顶为list首端的版本,其push/pop的复杂度为O(n),栈顶为list尾端的实现,其push/pop的复杂度为O(1)

303 简单的括号匹配

思路:最先遇到的左括号,一定是匹配最后的右括号。同样,最后遇到的左括号,一定是匹配最先的右括号。即左括号和右括号的次序是相反的。
在这里插入图片描述

from Stack.Stack import Stack

def parcheck(string):
    s = Stack()
    for str in string:
        if str is '(':
            s.push(str)
        else:
            if s.is_empty():
                return False
            else:
                s.pop()
    return True if s.is_empty() else False

通用匹配:

from Stack.Stack import Stack

def universal_parcheck(string):
    s = Stack()
    for str in string:
        if str in '([{':
            s.push(str)
        else:
            if s.is_empty():
                return False
            else:
                if not match(s.pop(), str):
                    return False
    return True if s.is_empty() else False


def match(open, close):
    opener = '([{'
    closer = ')]}'
    return opener.index(open) == closer.index(close)

304 十进制转二进制

除二余数法:将整数不断除以2,得到的余数就是从低到高的二进制数。得到的余数是从低到高的过程,但是输出确实从高到低的过程,这就是一种反序。
在这里插入图片描述

from Stack.Stack import Stack

def baseconvert(number):
    s = Stack()
    news_tring = ''
    while number:
        rem = number % 2
        number = number // 2
        s.push(rem)
    # return ''.join(str(i) for i in s.stack[::-1])
    while not s.is_empty():
        news_tring += str(s.pop())
    return news_tring

将除2改为除N就是将十进制转换为N进制的算法。

305 表达式转换

中缀表达式:操作符介于操作数中间的表达式。例:A+BC+D
前/后缀表达式:操作符位于操作数的前面或者后面的表达式,操作符决定次序。例:ABC*+D+
全括号表达式:在所有表达式的两边加上括号的表达式 例:(A+(B*C)+D)

在这里插入图片描述
将中缀表达式转化为前/后缀表达式:

  1. 将中缀表达式转换为全括号表达式
  2. 前缀表达式:遍历全括号表达式将操作符移到左括号,删除右括号。
    后缀表达式:遍历全括号表达式将操作符移到右括号,删除左括号。

306 中缀表达式转化为后缀表达式

1.遍历中缀表达式时,需要暂存操作符,并根据优先级倒序操作符,即可能需要反转操作符,就可以利用栈的反转特性,用栈来暂存操作符。
2. 栈顶的操作符就是最近暂存进去的,当遇到一个新的操作符,就需要跟栈顶的操作符比较下优先级,再行处理。
3. 流程:
(1)创建空栈、空列表用来暂存操作符、操作数。
(2)遍历全括号表达式,如果是操作数就存入列表,如果是操作符、左括号就存入栈(需要比较优先级),如果是右括号,就弹出栈顶到列表,直到遇到了左括号。
(3)全括号表达式遍历完时,将栈里剩余的所有操作符弹出到列表中。
(4)列表里面的各个元素连接就是所求的后缀表达式。

import string
from Stack.Stack import Stack

def infixtopostfix(infixexpr):
    prec = {'*': 3, '/': 3, '+': 2, '-': 2, '(': 1}
    s = Stack()
    l = list()
    for token in infixexpr:
        if token in string.ascii_uppercase or token in '0123456789':
            l.append(token)
        elif token is '(':
            s.push(token)
        elif token is ')':
            top_token = s.pop()
            while top_token != '(':
                l.append(top_token)
                top_token = s.pop()
        else:
            while (not s.is_empty()) and (prec[s.peek()] >= prec[token]):
                l.append(s.pop())
            s.push(token)
    while not s.is_empty():
        l.append(s.pop())
    return ''.join(l)

307 后缀表达式求值

遍历后缀表达式时,需要暂存操作数,再读取操作符,但是在遇到操作符为-或者/时,需要将操作数顺序对调。计算的结果也需要推入栈中用于后续的数据操作,最后栈中只剩了一个数字,就是最后的结果。
流程:从左到右扫描单词列表如果单词是一个操作数,将单词转换为整数int,压入栈顶。如果单词是一个操作符(*/±),就开始求值,从栈顶弹出2个操作数,先弹出的是右操作数,后弹出的是左操作数,计算后将值重新压入栈顶
在这里插入图片描述
代码:

from Stack.Stack import Stack

def do_math(token, o1, o2):
    if token is '/':
        return o2 / o1
    elif token is '-':
        return o2 - o1
    elif token is '+':
        return o2 + o1
    elif token is '*':
        return o2 * o1


def postfixEval(postfixexpr):
    s = Stack()
    for token in postfixexpr:
        if token in '0123456789':
            s.push(int(token))
        else:
            o1 = s.pop()
            o2 = s.pop()
            s.push(do_math(token, o1, o2))
    return s.pop()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值