1.基本结构
线性数据结构
1.1 栈
“后进先出 LIFO” 进栈和出栈的顺序正好相反
e.g. 浏览器的后退,word的undo
抽象数据类型“栈”是一个有次序的数据集,每个数据项仅从“栈顶”一端加入到数据集中、从数据集中移除,栈具有后进先出LIFO的特性。
1.1.1 栈的操作
基本操作:
操作例子:
Stack测试代码:
from pythonds.basic.stack import Stack
s = Stack()
print(s.isEmpty())
s.push(4)
s.push('dog')
print(s.peek())
s.push(True)
print(s.size())
print(s.isEmpty())
s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())
result:
True
dog
3
False
8.4
True
2
1.1.2 栈的应用——简单括号匹配
from pythonds.basic.stack import Stack
def perChecker(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 += 1
if balanced and s.isEmpty():
return True
else:
return False
实际应用中,会碰到更多种括号
python中的list [],dict {},tuple和表达式 ()。
def perChecker(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:
# 括号匹配
top = s.pop()
if not matches(top, symbol):
balanced = False
index += 1
if balanced and s.isEmpty():
return True
else:
return False
def matches(open, close): #匹配
opens = '([{'
closers = ')]}'
return opens.index(open) == closers.index(close) #通过索引进行匹配
1.1.3 栈的应用——十进制转换成二进制
from pythonds.basic.stack import Stack
def divideBy2(decNumber):
remstack = Stack()
while decNumber > 0:
rem = decNumber % 2
remstack.push(rem)
decNumber = decNumber // 2 # // 整数除
binString = ""
while not remstack.isEmpty():
binString = binString + str(remstack.pop())
return binString
print(divideBy2(42))
扩展:十六进制
from pythonds.basic.stack import Stack
def baseConverter(decNumber, base):
digits = "0123456789ABCDEF" #十六进制
remstack = Stack()
while decNumber > 0:
rem = decNumber % base #base为进制
remstack.push(rem)
decNumber = decNumber // base
newString = ""
while not remstack.isEmpty():
newString = newString + digits[remstack.pop()] # 如:pop()出14,则查表得到E
return newString
print(baseConverter(25,16))
print(baseConverter(25,2))
1.1.4 栈的应用——表达式转换
中缀表达式
前缀表达式
后缀表达式
算法:
from pythonds.basic.stack import Stack
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 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
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) #合成后缀表达式字符串
后缀表达式求值
from pythonds.basic.stack import Stack
def postfixEval(postfixExper):
operandStack = Stack()
tokenList = postfixExper.split()
for token in tokenList:
if token in "0123456789":
operandStack.push(int(token))
else:
operand2 = operandStack.pop() #从栈顶弹出2个操作数,先弹出的是右操作数,后弹出的是左操作数。
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
1.2 队列
“先进先出 FIFO”
e.g. 进程调度(进程数远多于CPU核心数,有些进程还要等待不同类型I/O事件),打印机,键盘缓存
1.2.1 队列的操作
1.2.2 队列的应用——热土豆问题
from pythonds.basic.queue import Queue
def hotPotato(namelist, num):
simqueue = Queue()
for name in namelist:
simqueue.enqueue(name)
while simqueue.size() > 1: #循环到队列只剩一个
for i in range(num): #队首出队,再入队,共循环num次
simqueue.enqueue(simqueue.dequeue())
simqueue.dequeue() #队首出队
return simqueue.dequeue() #最后唯一一个出队输出
# 传递固定人数,7
print(hotPotato(['Bill','David','Susan','Jane','Kent','Brad'],7))
1.2.3 队列的应用——打印任务
from pythonds.basic.queue import Queue
import random
class Printer:
def __init__(self, ppm):
self.pagerate = ppm #打印速度
self.currentTask = None #打印任务
self.timeRemaining = 0 #任务倒计时
def tick(self): #打印1秒
if self.currentTask != None:
self.timeRemaining = self.timeRemaining - 1
if self.timeRemaining <= 0:
self.currentTask = None
def busy(self): #打印忙?
if self.currentTask != None:
return True
else:
return False
def startNext(self,newtask): #打印新任务
self.currentTask = newtask
self.timeRemaining = newtask.getPages() * 60/self.pagerate
class Task:
def __init__(self,time):
self.timestamp = time #生成时间戳
self.pages =random.randrange(1,21) #打印页数
def getStamp(self):
return self.timestamp
def getPages(self):
return self.pages
def waitTime(self,currenttime):
return currenttime -self.timestamp #等待时间
def newPrintTask():
num =random.randrange(1,181) #1/180概率生成作业
if num == 180:
return True
else:
return False
def simulation(numSeconds, pagesPerMinute): #模拟
labprinter =Printer(pagesPerMinute)
printQueue = Queue()
waitingtimes = []
for currentSecond in range(numSeconds):
if newPrintTask():
task =Task(currentSecond)
printQueue.enqueue(task)
if (not labprinter.busy()) and (not printQueue.isEmpty()):
nexttask =printQueue.dequeue()
waitingtimes.append(nexttask.waitTime(currentSecond))
labprinter.startNext(nexttask)
labprinter.tick()
averageWait=sum(waitingtimes)/len(waitingtimes)
print("Average Wait %6.2f secs %3d tasks remaining."%(averageWait,printQueue.size()))
#模拟10次,每次3600s,打印机每分钟5页
for i in range(10):
simulation(3600,5)
Average Wait 120.17 secs 0 tasks remaining.
Average Wait 256.60 secs 2 tasks remaining.
Average Wait 48.81 secs 0 tasks remaining.
Average Wait 142.91 secs 2 tasks remaining.
Average Wait 113.92 secs 1 tasks remaining.
Average Wait 22.40 secs 2 tasks remaining.
Average Wait 119.29 secs 0 tasks remaining.
Average Wait 163.48 secs 1 tasks remaining.
Average Wait 133.04 secs 0 tasks remaining.
Average Wait 68.75 secs 0 tasks remaining.
1.3 双端队列抽象数据类型及Python实现+回文词判定
应用:“回文词”判定
from pythonds.basic.deque import Deque
# 判断是否是回文词
def back_to_word_check(s1):
deque = Deque() #实例化双端队列
[deque.addRear(i) for i in s1] #将字符串从队尾入队
while deque.size() > 1: #队列长度>1,则循环,否则为0或1个,则说明是回文词
first = deque.removeFront() #从队首出队一个
last = deque.removeRear() #从队尾出队一个
if first != last: #若不相同,则
return False #非回文词
return True #回文词
s1 = '枯眼望遥山隔水往来曾见几心知壶空怕酌一杯酒笔下难成和韵诗途路阻人离别久讯音无雁寄回迟孤灯夜守长寥寂夫忆妻兮父忆儿儿忆父兮妻忆夫寂寥长守夜灯孤迟回寄雁无音讯久别离人阻路途诗韵和成难下笔酒杯一酌怕空壶知心几见曾来往水隔山遥望眼枯'
print(back_to_word_check(s1))
1.4 无序表抽象数据类型及Python实现
实现
1.5 有序表抽象数据类型及Python实现
2 递归
2.1 递归与实现
将问题分解为规模更小的相同问题
递归实现:
递归深度限制,防止无限递归。
import sys
sys.getrecursionlimit() #默认限制递归1000
sys.getrecursionlimit(3000) #限制递归3000次
2.2 递归的应用——任意进制转换
def toStr(n,base):
convertString = "0123456789ABCDEF"
if n < base:
return convertString[n] #最小规模
else:
return toStr(n//base,base) + convertString[n%base] #减小规模,调用自身
print(toStr(1453,16)) #将1453转换成16进制
2.3 递归可视化
2.3.1 分形树
e.g.
2.3.2 谢尔宾斯基三角形
2.4 递归的应用——汉诺塔
def moveTower(height, fromPole, withPole, toPole):
if height >= 1:
moveTower(height - 1, fromPole, toPole, withPole)
moveDisk(height, fromPole, toPole)
moveTower(height - 1, withPole, fromPole, toPole)
def moveDisk(disk, fromPole, toPole):
print(f"Moving disk[{disk}] from {fromPole} to {toPole}")
moveTower(3, "#1", "#2", "#3")
Moving disk[1] from #1 to #3
Moving disk[2] from #1 to #2
Moving disk[1] from #3 to #2
Moving disk[3] from #1 to #3
Moving disk[1] from #2 to #1
Moving disk[2] from #2 to #3
Moving disk[1] from #1 to #3
几个小算法
读取以空格分隔的一行整数
input 3个数:
# input 3个数
a,b,c = map(int, input().split())
input 未知个数:
# input未知个数
op = map(int, input().split())
l = []
l=[i for i in op]
print(min(l))
将list中的string转换为int
假设有这样一个
results = [‘1’, ‘2’, ‘3’]
转化为下面这个样子
results = [1, 2, 3]
results = list(map(int, results))
洗盘子
from pythonds.basic.stack import Stack
def washdishes(nums):
s = Stack()
index = 0
l = []
for num in nums:
if s.isEmpty() or s.peek() < num:
s.push(num)
l.append(num)
elif s.peek() > num and num+1 in l:
s.push(num)
l.append(num)
else:
return 'No'
break
return 'Yes'
int()进制转换
num = int(str(num), base=m) #将m进制的num转换成十进制
进制转换表:
2进制 | 8进制 | 10 进制 | 16进制 | |
---|---|---|---|---|
2进制 | - | bin(int(x,8)) | bin(int(x,10)) | bin(int(x,16)) |
8进制 | oct(int(x,2)) | - | oct(int(x,10)) | oct(int(x,16)) |
10进制 | str(int(x,2)) | str(int(x,8)) | - | str(int(x,16)) |
16进制 | hex(int(x,2)) | hex(int(x,8) | hex(int(x,10)) | - |