Python版数据结构与算法
Posted 大聪明Smart
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python版数据结构与算法相关的知识,希望对你有一定的参考价值。
数据结构
引子
未来简史: 数据主义 Dataism
问题的求解: What Why How 基于有穷观点的能行方法
图灵机计算模型
算法和计算复杂性
可计算问题:算法的难易程度
不可计算问题:边界或极限
突破极限:SETI@home、光子计算、智慧众包科研项目
算法分析:计算资源消耗,何为计算资源?存储空间或内存,执行时间。
算法时间度量指标
问题的规模影响算法执行时间
数量级函数 大O表示法 O(n)
例子:T(n) = 5n^2 + 27n +1005 O(n^2)
其他因素: 最好 最差 平均
常见的大O数量级函数 O(1) log(n) O(n) n*log(n) n^2 n^3 2^n
"变位词"问题
abcd dcba
- 逐个对比 O(n^2)
- 排序对比 O(nlogn)
- 暴力穷尽 。。。。
- 计数比较 对每个字母出现的次数进行计数 最后对比 O(n) 空间换时间
Python数据类型的性能
让最常用的操作性能最好
pop 最好不要pop(0) 他要把所有的数据都后移一位 时间复杂度很高
线性结构Liner Structure
线性结构是一种有序数据项的集合,其中每个数据项都要唯一的前驱和后继。
数据项的增减方式不同构成了不同的数据结构
栈Stack
一种有次序的数据项集合。在栈中,数据项的加入和移除只发生在同一端。这一端叫栈顶top,另一端叫栈底base。
栈的特性:反转次序
操作
# ADT.py
"""
要掌握思想
栈和队列
"""
# 栈:先进后出的数据结构,栈顶和栈尾。随便选取列表的一端设置位栈顶或栈底。这里把最后一个元素选为栈顶,这种性能会好一点。
# 用列表实现:我们定义列表开始的位置为栈底,末尾为栈顶。
# Stack() 创建一个空栈。它不需要参数,并返回一个空栈。
# push()
class Stack(object):
def __init__(self):
self.items = []
def push(self,item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
"""从栈返回顶部项,但不会删除它。不需要参数,不修改栈。"""
return len(self.items) - 1
def isEmpty(self):
return self.items == []
def size(self):
return len(self.items)
if __name__ == '__main__':
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print('栈顶元素下标',stack.peek())
print(stack.isEmpty())
print(f'元素个数{stack.size()}')
栈的应用:简单的括号匹配
括号必须正确匹配,
每个开括号“(” 必须对应一个闭括号 “)”;
要正确嵌套。
# 导入栈包
from ADT import Stack
def is_kuohao(s):
# 创建一个空栈
stack = Stack()
for i in s:
if i == '(':
# 如果是左括号,入栈
stack.push(i)
else:
# 如果是右括号,则出栈一个左括号,他们俩一对
if stack.isEmpty():
# 如果此时栈已空,则直接返回False,因为已经匹配不了了
return False
# 不为空才出栈
stack.pop()
return stack.isEmpty()
s = input()
print(is_kuohao(s))
栈的应用:混合括号匹配
"""
括号混合存在的情况
"""
# 导入栈包
from ADT import Stack
def match(a, b):
opens = '{[('
closes = '}])'
return opens.index(a)==closes.index(b)
def par_check(s):
# 创建一个空栈
stack = Stack()
for i in s:
if i in '({[':
# 如果是左括号,入栈
stack.push(i)
else:
# 如果是右括号,则出栈一个左括号,并检测他们俩是不是一对
if stack.isEmpty():
# 如果此时栈已空,则直接返回False,因为已经匹配不了了
return False
# 不为空才出栈
if not match(stack.pop(), i):
return False
return stack.isEmpty()
s = input()
print(par_check(s))
栈的应用:进制转换
"""
给定一个十进制数,把他转换成k进制
除k求余法
"""
from ADT import Stack
def digit(base, k):
arr = '0123456789ABCDEF'
res = ''
stack = Stack()
while base != 0:
stack.push(arr[base % k])
base = base // k
while not stack.isEmpty():
res += stack.pop()
return int(res)
print(digit(100, 16)) # 64
print(int('64', 16)) # 100
栈的应用:表达式
中缀表达式:运算符在中间,例如A+B。如果含有其他运算符再要考虑优先级,优先级是人为规定的。
例如A+B*C,为了让计算机具有更强的辨识度,给表达式全部加上括号,这样就无需考虑运算符的优先级而只需考虑括号即可。
例如(A+(B*C)),即全括号表达式。
前缀表达式:为了方便优先级的表示,把运算符放在操作数的前边。
后缀表达式:为了方便优先级的表示,把运算符放在操作数的后边。
中缀表达式 | 前缀表达式 | 后缀表达式 |
---|---|---|
A+B*C | +A*BC | ABC*+ |
前缀和后缀可以省去括号了。离运算符最近的先操作。计算机里通常勇后缀表达式。
中缀表达式转换位前缀表达式或后缀表达式
(A+(B*C))
看子表达式(B*C)的右括号,运算符一道右括号位置代替他,再删掉左括号得到后缀表达式。
通用转换
从左到右依次扫描,把操作符暂存到一个栈中
if 操作数 直接添加到后缀表达式的末尾
if 左括号 压入opstack栈顶
if 右括号 反复弹出opstack栈顶
操作符加入到输出列表末尾知道碰到左括号
if 操作符 压入opstack栈顶 要比较其与栈顶操作符的优先级 优先级高的在栈顶
"""后缀表达式"""
from ADT import Stack
def hou_ex(ex):
res = ''
prec = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
stack = Stack()
for s in ex:
if s not in '()+-*/':
res += s
res += ' '
elif s == '(':
stack.push(s)
elif s == ')':
opt = stack.pop()
while opt != '(':
res += opt
res += ' '
opt = stack.pop()
elif s in '+-*/':
while not stack.isEmpty() and prec[stack.peek()] > prec[s]:
if stack.peek() == '(':
break
res += stack.pop()
res += ' '
stack.push(s)
while not stack.isEmpty():
res += stack.pop()
res += ' '
return res
ex = list(input().strip().split())
print(hou_ex(ex))
# 11 + 2 * 3
后缀表达式求值
"""后缀表达式求值"""
from ADT import Stack
def compute(x, y, opt):
if opt == '+':
return x + y
elif opt == '-':
return x - y
elif opt == '*':
return x * y
else:
return x / y
def hou_value(ex):
stack = Stack()
for s in ex:
if s not in '+-*/':
stack.push(s)
else:
b = int(stack.pop())
a = int(stack.pop())
stack.push(compute(a, b, s))
return stack.pop()
ex = list(input().strip().split())
print(hou_value(ex))
# 11 2 3 * +
队列Queue
队列是一种有次序 的集合,其特征是:新数据项的添加总发生在一端,尾端rear;现存数据项的移除发生在另一端,首端front。
# ADT.py
# 队列:先进先出。队头和队尾。
# 我们定义列表开始位置为队头,末尾为队尾。
class Queue(object):
def __init__(self):
self.items = []
def enqueue(self,item):
self.items.insert(0, item)
def dequeue(self):
return self.items.pop()
def isEmpty(self):
return self.items == []
def size(self):
return len(self.items)
if __name__ == '__main__':
q = Queue()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
print(q.dequeue())
print(q.dequeue())
print(q.dequeue())
双端队列Deque
列表List
以上是关于Python版数据结构与算法的主要内容,如果未能解决你的问题,请参考以下文章