python 表达式求值数据结构_python 数据结构与算法
python 数据结构与算法
1 python常见数据结构性能
1.1 List
1.1.1 安索引取值和赋值
1.1.2 列表append和__add__()
1.1.3 使用timeit模块测试执行时间
1.1.4 List基本操作的大O数量级
1.2 Dict
1.2.1 dict数据类型
2 线性结构 Linear Structure
2.1 栈Stack
2.1.1 抽象数据类型Stack
2.1.2 Stack的操作如下
2.1.3 栈的应用1:简单括号匹配
2.1.3.1 圆括号匹配
2.1.3.2 通用括号匹配
2.1.4 栈的应用2:进制转换
2.1.4.1 十进制转换二进制
2.1.4.2 十进制转换任意进制
2.1.5 栈的应用3:表达式转换
2.1.5.1 中缀表达式
2.1.5.2 全括号中缀表达式
2.1.5.3 前缀和后缀表达式
2.1.5.4 中缀表达式转换为前缀和后缀形式
2.1.5.5 通用的中缀转后缀算法
2.1.5.6 后缀表达式求值
2.2 队列Queue
1 python常见数据结构性能
1.1 List
1.1.1 安索引取值和赋值
list最常用的操作是:按索引取值和赋值(v=a[i],a[i]=v),这两个操作执行时间与列表大小无关,均为O(1)。
1.1.2 列表append和__add__()
list.addend(v),执行时间是O(1)。
list0 = list1 + [v],执行时间是O(n+k),其中k是被加的列表长度。
1.1.3 使用timeit模块测试执行时间
使用timeit模块对函数计时:
1.1.4 List基本操作的大O数量级
1.2 Dict
1.2.1 dict数据类型
字典是根据key找到对应的value,最常用的取值get和赋值set,其性能都是O(1)。另外一个常用的操作判断字典中是否存在某个key (in),这个性能也是O(1)。
2 线性结构 Linear Structure
线性结构是一种有序数据项的集合,其中每个数据项都有唯一的前驱和后继(除了第一个和最后一个)。
2.1 栈Stack
栈是一种有次序的数据项集合,在栈中,数据项的加入和移除都仅发生在同一端,这一端叫做“栈顶top”,另一端叫做“栈底base”。
栈是一种后进先出LIFO:Last in First out,这是一种基于数据项保存时间的次序,时间越短的离栈顶越近,而时间越长的离栈底越近。
2.1.1 抽象数据类型Stack
抽象数据类型“栈”是一个有次序的数据集,每个数据项仅从“栈顶”一端加入到数据集中、从数据集中移除,栈具有后进先出LIFO的特性。
2.1.2 Stack的操作如下
stack():创建一个空栈,不包含任何数据项。
push(item):将item加入栈顶,无返回值。
pop():将栈顶的数据项移除,并返回,栈被修改。
peek():“窥视”栈顶数据项,返回栈顶的数据。
isEmpty():返回是否是空栈。
size():返回栈中有多少个数据项。
class Stack(object):
def __init__(self):
self.stack = []
def push(self, item):
self.stack.append(item)
def pop(self):
if not self.is_empty():
return self.stack.pop()
def peek(self):
if not self.is_empty():
return self.stack[self.size()-1]
def is_empty(self):
return len(self.stack) == 0
def size(self):
return len(self.stack)
2.1.3 栈的应用1:简单括号匹配
2.1.3.1 圆括号匹配
括号必须遵循“平衡”原则,即每个开括号必须有一个比括号对应。
从左到右扫描括号,最新打开的左括号,应该匹配最先遇到的右括号。这样,第一个左括号就应该匹配最后一个右括号,这种次序反转的识别,正好符合栈的特性。
流程图如下:
from data_structure.Stack.stack import Stack
def brackets_valid(expression):
stack = Stack()
for item in expression:
if item == "(":
stack.push(item)
elif item == ")":
if stack.is_empty():
return False
else:
stack.pop()
return stack.is_empty()
if __name__ == '__main__':
print(brackets_valid("()()()"))
print(brackets_valid("(()())(()"))
print(brackets_valid("((5+6)*(4+3))+((10-9)"))
2.1.3.2 通用括号匹配
实际应用中,会遇到更多种括号,比如:[], {},()。
from data_structure.Stack.stack import Stack
def brackets_valid(expression):
stack = Stack()
mapping = {
")": "(",
"]": "[",
"}": "{"
}
for item in expression:
if item in "([{":
stack.push(item)
elif item in ")]}":
if stack.is_empty():
return False
else:
if stack.peek() != mapping[item]:
return False
else:
stack.pop()
return stack.is_empty()
if __name__ == '__main__':
print(brackets_valid("()()()"))
print(brackets_valid("(()())(()"))
print(brackets_valid("((5+6)*(4+3))+((10-9)"))
print(brackets_valid("{{([][])}()}"))
print(brackets_valid("[[{{(())}}]]"))
print(brackets_valid("[][][](){}"))
print(brackets_valid("([)}"))
print(brackets_valid("((()]))"))
print(brackets_valid("[{()]"))
2.1.4 栈的应用2:进制转换
进制:指用多少字符来表示整数。十进制是0-9十个数字字符,二进制是0、1两个字符。
例如:十进制233对应的二进制是11101001,具体算法如下:
233 = 2102 + 3101 + 3100
11101001 = 127 + 126 + 125 + 024 + 123 + 022 +021 + 1*20
2.1.4.1 十进制转换二进制
常见的十进制转换二进制采用的是**“除2求余数”的算法。如下:35的二进制是100011。在除2求余的过程中,得到的余数是从低到高的次序,而输出则是从高到低,所以需要一个栈来反转次序**。
from data_structure.Stack.stack import Stack
def convert(num):
if not isinstance(num, int):
return False
stack = Stack()
while num:
num, remainder = divmod(num, 2)
stack.push(remainder)
result = ""
while not stack.is_empty():
result += str(stack.pop())
return result
if __name__ == '__main__':
print(f"35的二进制数是{convert(35)}")
2.1.4.2 十进制转换任意进制
将“除2求余”改为“除N求余”就可以将上面的算法扩展为任意进制转换。
十进制233对应八进制351,十六进制是E9。
主要区别是:
二进制:0-1
十进制:0-9
八进制:0-7
十六进制:0-9,A-F
from data_structure.Stack.stack import Stack
def convert(num, unit):
if not isinstance(num, int):
return False
dights = "0123456789ABCDEF"
stack = Stack()
while num:
num, remainder = divmod(num, unit)
stack.push(remainder)
result = ""
while not stack.is_empty():
result += str(dights[stack.pop()])
return result
if __name__ == '__main__':
print(f"35的二进制数是{convert(35, 2)}")
print(f"233的八进制数是{convert(233, 8)}")
print(f"233的十六进制数是{convert(233, 16)}")
2.1.5 栈的应用3:表达式转换
2.1.5.1 中缀表达式
操作符位于两个操作数之间的表示法,称为“中缀”表达式。例如:A+B。
2.1.5.2 全括号中缀表达式
计算机处理时最好避免复杂的优先级(乘除优先于加减、括号优先级)规则,能明确规定所有的计算顺序是最好的。因此,引入全括号表达式: ((A+B*C)+D)
2.1.5.3 前缀和后缀表达式
前缀表达式:将操作符移到操作数前面,即:+AB。
后缀表达式:将操作符移到操作数后面,即:AB+。
在前缀和后缀表达式中,操作符次序完全决定了运算的次序,不再混淆。
2.1.5.4 中缀表达式转换为前缀和后缀形式
2.1.5.5 通用的中缀转后缀算法
中缀表达式A+BC,对应的后缀表达式是 ABC+。其中,操作数ABC的顺序没有改变,操作符的出现顺序在后缀表达式中反转了。由于*的优先级比+高,所以后缀表达式中操作符的出现顺序与运算次序一致。
算法流程:
import string
from data_structure.Stack.stack import Stack
def convert_postfix(expression):
result = ""
oper_stack = Stack()
priority = {
"(": 0,
"+": 1,
"-": 1,
"*": 2,
"/": 2
}
for item in expression:
if item in string.ascii_letters or item in string.digits:
result += item
elif item == "(":
oper_stack.push(item)
elif item == ")":
while oper_stack.peek() != "(":
result += oper_stack.pop()
else:
oper_stack.pop()
elif item in "+-*/":
while oper_stack.peek() and \
priority[oper_stack.peek()] >= priority[item]:
result += oper_stack.pop()
else:
oper_stack.push(item)
while not oper_stack.is_empty():
result += oper_stack.pop()
return result
if __name__ == '__main__':
print(convert_postfix("A+B*C"))
print(convert_postfix("(A+B)*C"))
2.1.5.6 后缀表达式求值
对于后缀表达式从左到右扫描,由于操作符在操作数后面,所以要暂存操作数,在遇到操作符的时候再将暂存的两个操作数进行实际的计算。
例如: ABC*+,先扫描到了ABC暂存到栈中,扫描到*的时候,从栈中弹出2个操作数做乘法,做完之后再存入栈中;继续扫描到+,从栈中弹出2个操作数做加法。
注意:对于-/操作符,弹出的两个操作数顺序很重要,先弹出的是右操作数,后弹出的是左操作数。
算法流程:
import string
from data_structure.Stack.stack import Stack
from data_structure.Stack.infix_to_postfix import convert_postfix
def calculate(expression):
stack = Stack()
for item in expression:
if item in string.digits:
stack.push(item)
elif item in "+-*/":
first = stack.pop()
second = stack.pop()
stack.push(str(eval(second + item + first)))
return stack.pop()
if __name__ == '__main__':
print(calculate(convert_postfix("1+2*3")))
print(calculate(convert_postfix("(1+2)*3")))
2.2 队列Queue
python 表达式求值数据结构_python 数据结构与算法相关推荐
- python 表达式求值_简单算术表达式求值
本文主要探讨简单的数学算术表达式求值算法的原理和实现. 1. 约束 本文只是探讨简单的算术表达式的求值算法,为了将主要精力放在算法思想的探讨和实现上,避免陷入对其他不是直接相关的细节的过多思考,所以提 ...
- 【数据结构与算法】之深入解析“逆波兰表达式求值”的求解思路与算法示例
一.题目要求 根据逆波兰表示法,求表达式的值.有效的算符包括 +.-.*./,每个运算对象可以是整数,也可以是另一个逆波兰表达式. 两个整数之间的除法只保留整数部分. 可以保证给定的逆波兰表达式总是有 ...
- Suzy找到实习了吗Day 11 |栈与队列中途 20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值
Day 11 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值 20. 有效的括号 注意栈不是一个数据结构,需要自己用list实现栈的逻辑 class Solu ...
- python前缀表达式求值_python数据结构与算法 11 后缀表达式求值
从本节开始,删除原版的英文,直接发译后的文稿. 后缀表达式求值 栈的最一个应用例子,计算一个后缀表达式的值.这个例子中仍然用栈的数据结构.不过,当扫描表达式的时候,这次是操作数压栈等待,不是转换算法中 ...
- python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图
python数据结构和算法 参考 本文github 计算机科学是解决问题的研究.计算机科学使用抽象作为表示过程和数据的工具.抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性.Pytho ...
- python输入数学表达式并求值_Python 条件表达式求值
Python 条件表达式求值,Python对表达式执行严格排序,其中值得注意的例外情况是短路运算符and和or.对语句的求值也有严格的顺序要求,这使得难以对其进行优化,因为可能会破坏严格的求值顺序. ...
- [数据结构]表达式求值
一.问题描述 表达式求值是数学中的一个基本问题,也是程序设计中的一个简单问题.我们所涉及的表达式中包含数字和符号,本实验中处理的符号包括'+'.'-'.'*'.'/'.'('和')',要求按照我们所习 ...
- c语言中缀表达式求值_数据结构考研笔记之栈与队列(四)栈与队列应用括号匹配、中缀表达式转前缀后缀问题...
文字:独木 排版:独木 图片:独木 栈与队列 1.括号匹配问题 栈 例题1 例题2-----不匹配例题1 例题3-----不匹配例题2 2. 表达式求值问题 例题 1.中缀表达式转前缀表达式 2.中缀 ...
- linux算术表达式求值数据结构,数据结构:算数表达式求值演示
题目:设计一个程序,演示用算符优先法对算数表达式求值的过程. 一.需求分析 以字符序列的形式从终端读入输入语法正确.不含变量的整数表达式.利用教科书表3.1给出的算符优先关系,实现对算数四则混合运算表 ...
最新文章
- Skpi List跳表
- Xtrabackup的“流”及“备份压缩”功能
- 纹理和基元_通过粘性仙人掌基元进行延迟加载和缓存
- @Select注解的使用
- html表格添加选项代码,使用实例演示 表单 中的选项卡功能 在里面添加table id=bootstrap-table/table后不显示表格...
- html导入夸克,index.html
- CentOS防止黑客攻击Linux服务器实战演练
- 机器人参数校准的原理
- 海洋工作室成立啦!!
- HTML和XHTML解析(HTMLParser、BeautifulSoup)
- 修改注册表,改回主页---内容来自百度
- 【十次方】Springboot中使用Redis做缓存
- 视频压缩工具及使用方法
- 分数换算小数补0法_小学数学概念+知识点顺口溜汇总+常用单位换算汇总
- 服务器返回的14种常见HTTP状态码
- CISSP第5/8知识点错题集
- django+haystack+ElasticsearchSearch
- 编译原理实验四:验证Yacc的使用
- 谷粒学院项目对应知识点
- skysat重访周期_重访CSS背景属性
热门文章
- 博弈问题及SG函数(真的很经典)
- php 合并两个数组并去重,合并两个数组 以KEY 作为键
- vue 父链和子组件索引_vue子组件和父组件双向绑定的几种方案
- JAVA错误:无法从静态上下文中引用非静态变量 this
- 打游戏提示计算机丢失,Windows7电脑运行某游戏提示“计算机丢失mxvcp120.dll”怎么办...
- 双显示器设置:如何设置一台电脑两个显示器
- TorchMetrics:PyTorch的指标度量库
- java mvc中重复提交表单,spring mvc 防止重复提交表单的两种方法,推荐第二种
- 前端常见浏览器兼容性问题及解决办法
- 使用微信开发者工具添加小程序底部导航栏报错