基本结构
栈
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
单一括号匹配算法
from basic.Stack import Stack
# 1.初始化,建立栈
# 2.遍历字符串
# (1)如果是左括号就存入栈
# (2)如果是右括号:
# a.没有与之匹配的左括号(栈为空),返回False
# b.有可以匹配的左括号,二者抵消
# 3.如果栈内没有剩余左括号,返回True,否则返回False
def parChecker(symbolString):
# 初始化
s = Stack()
index = 0
while index < len(symbolString):
symbol = symbolString[index]
if symbol == "(":
s.push(symbol)
else:
if s.isEmpty():
return False
else:
s.pop()
index += 1
if s.isEmpty():
return True
else:
return False
通用括号匹配
from basic.Stack import Stack
# 1.初始化,建立栈
# 2.遍历字符串
# (1)如果是左括号就存入栈
# (2)如果是右括号:
# a.没有与之匹配的左括号(栈为空),返回False
# b.有可以匹配的左括号,二者抵消
# 3.如果栈内没有剩余左括号,返回True,否则返回False
def parChecker2(symbolString):
s=Stack()
index=0
while index<len(symbolString):
symbol=symbolString[index]
if symbol in "([{":
s.push(symbol)
else:
if s.isEmpty():
return False
else:
top=s.pop()
if not matches(top,symbol):
return False
index+=1
if s.isEmpty():
return True
else:
return False
def matches(open,close):
opens="([{"
closers=")]}"
return opens.index(open)==closers.index(close)
十进制转二进制
from basic.Stack import Stack
# 1.创建一个栈
# 2. rem存放ducNumber除2的余数,入栈。decNumber除2
# 3. 反向输出,出栈
def divideBy2(decNumber):
remstack=Stack()
while decNumber>0:
rem=decNumber%2
remstack.push(rem)
decNumber//=2
binString =""
while not remstack.isEmpty():
binString+=str(remstack.pop())
return binString
16进制以下通用进制转换
from basic.Stack import Stack
# 1.设置一个digits来存放表示字符
# 2.创建栈
# 3.进制转换,入栈
# 4.出栈对比digits,输出表示字符
def baseConverter(decNumber, base):
digits = "0123456789ABCDEF"
remstack = Stack()
while decNumber > 0:
rem = decNumber % base
remstack.push(rem)
decNumber //= base
newString = ""
while not remstack.isEmpty():
newString += digits[remstack.pop()]
return newString
表达式
中缀表达式
操作符介于操作数中间的表示法,称为中缀表达式。
优先级
- 引入了“优先级”的概念来消除混淆
- 规定高优先级的操作符先计算
- 相同优先级操作符从左到右依次计算
- 引入括号来表示强制优先级,括号的优先级最高;在嵌套的括号中,内层的优先级更高
**全括号中缀表达式:**在所有表达式两边都加上括号
前缀和后缀表达式
以操作符相对于操作数的位置来定义.
操作符的次序完全决定了运算的次序,不再有混淆,不需要括号。
中缀表达式 | 前缀表达式 | 后缀表达式 |
---|---|---|
A + B A+B A+B | + A B +AB +AB | A B + AB+ AB+ |
A + B ∗ C A+B*C A+B∗C | + A ∗ B C +A*BC +A∗BC | A B C ∗ + ABC*+ ABC∗+ |
( A + B ) ∗ C (A+B)*C (A+B)∗C | ∗ + A B C *+ABC ∗+ABC | A B + C ∗ AB+C* AB+C∗ |
A + B ∗ C + D A+B*C+D A+B∗C+D | + + A ∗ B C D ++A*BCD ++A∗BCD | A B C ∗ + D + ABC*+D+ ABC∗+D+ |
( A + B ) ∗ ( C + D ) (A+B)*(C+D) (A+B)∗(C+D) | ∗ + A B + C D *+AB+CD ∗+AB+CD | A B + C D + ∗ AB+CD+* AB+CD+∗ |
A ∗ B + C ∗ D A*B+C*D A∗B+C∗D | + ∗ A B ∗ C D +*AB*CD +∗AB∗CD | A B ∗ C D ∗ + AB*CD*+ AB∗CD∗+ |
A + B + C + D A+B+C+D A+B+C+D | + + + A B C D +++ABCD +++ABCD | A B + C + D + AB+C+D+ AB+C+D+ |
中缀表达式转换前缀或后缀
-
将中缀表达式转换为全括号表达式
-
遇到括号时,将操作符替代右括号的位置,删去左括号,得到后缀表达式
-
遇到括号时,将操作符替代左括号的位置,删去右括号,得到前缀表达式
中缀转后缀算法
from basic.Stack import Stack
# 1.创建字典,用于存放操作符优先级
# 2.创建栈,用于暂存操作符;
# 创建空列表,用于存放后缀表达式;
# 解析表达式为单词列表
# 3.遍历单词列表
# (1)如果为操作数,就添加到后缀表达式列表
# (2)如果为左括号,放入操作符栈
# (3)如果为右括号,反复弹出栈顶操作符存入表达式列表,直到弹出左括号
# (4)如果为操作符:
# a.如果栈顶操作符优先级更大,则先弹出栈顶操作符存入表达式列表,再将操作符入栈
# b.否则直接入栈
# 4.遍历结束后如果有操作符未弹出,则按出栈顺序存入表达式列表
# 5.用join合成后缀表达式字符串
def infixToPostfix(infixexpr):
prec = {}
prec["*"] = 3
prec["/"] = 3
prec["+"] = 2
prec["-"] = 2
prec["("] = 1
opStack = Stack()
postfixList = []
tokenList=list(infixexpr)
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 basic.Stack import Stack
# 1.将中缀转换为后缀表达式;
# 创建空栈,存放操作数
# tokenList获得单词列表
# 2.遍历tokenList:
# (1)如果为数字,存放到栈中
# (2)如果为操作符,取出两个操作数进行计算,结果重新入栈
# 3.计算完毕,返回结果
def postfixEval(postfixExpr):
postfixExpr = infixToPostfix(postfixExpr)
operandStack = Stack()
tokenList = list(postfixExpr)
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
# 1.创建字典,用于存放操作符优先级
# 2.创建栈,用于暂存操作符;
# 创建空列表,用于存放后缀表达式;
# 解析表达式为单词列表
# 3.遍历单词列表
# (1)如果为操作数,就添加到后缀表达式列表
# (2)如果为左括号,放入操作符栈
# (3)如果为右括号,反复弹出栈顶操作符存入表达式列表,直到弹出左括号
# (4)如果为操作符:
# a.如果栈顶操作符优先级更大,则先弹出栈顶操作符存入表达式列表,再将操作符入栈
# b.否则直接入栈
# 4.遍历结束后如果有操作符未弹出,则按出栈顺序存入表达式列表
# 5.用join合成后缀表达式字符串
def infixToPostfix(infixexpr):
prec = {}
prec["*"] = 3
prec["/"] = 3
prec["+"] = 2
prec["-"] = 2
prec["("] = 1
opStack = Stack()
postfixList = []
tokenList = list(infixexpr)
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)
队列
class Queue:
def __init__(self):
self.item = []
def isEmpty(self):
return self.item == []
def enqueue(self, item):
self.item.insert(0, item)
def dequeue(self):
return self.item.pop()
def size(self):
return len(self.item)
热土豆问题
from basic.Queue import Queue
# 1.创建一个空队列
# 2.将列表存放入队列
# 3.当队列中人数大于1的情况下:
# (1)每传递一次,队首入队,重新从队尾入队
# (2)每完成一轮,队首出队
# 4.最后队列中剩下一个元素
def hotPotato(namelist, num):
simqueque = Queue()
for name in namelist:
simqueque.enqueue(name)
while simqueque.size() > 1:
for i in range(num):
simqueque.enqueue(simqueque.dequeue())
simqueque.dequeue()
return simqueque.dequeue()
打印机问题
-
实例配置:
一个实验室中,在任意的一个小时内,有大约10名学生在场, 这一个小时内,每人会发起约2次左右的打印,每次1~20页 -
打印机性能:
草稿模式:每分钟10页
正常模式:每分钟5页,质量较高
Q:如何设置打印机模式,让大家都不会等太久的前提下提高打印质量?
-
对象:
- 打印任务:提交时间、打印页数
- 打印队列:具有FIFO性质的打印任务队列
- 打印机:打印速度、是否忙
-
过程:生成和提交任务
-
确定生成概率:每小时有10个学生提交20个作业。
概率为:每180秒会有1个作业生成—— 1 180 / s \frac{1}{180}/s 1801/s
-
确定打印页数:1~20页概率相同
-
-
过程:实施打印
- 当前打印作业:正在打印的作业
- 打印结束倒计时:开始时倒计时,为0时处理下一个任务
-
模拟时间:
- 统一的时间框架:以 秒 秒 秒为单位,设置结束时间
- 同步所有过程:在一个单位时间内,对生成任务和打印任务各处理一次
-
模拟流程
- 创建打印队列对象
- 时间按照
秒
秒
秒的单位流逝
- 按照概率生成打印作业,加入打印队列
- 如果打印机空闲,且队列不空,则取出队首作业打印,记录此作业等待时间
- 如果打印机忙,则按照打印速度进行1秒打印
- 如果当前作业打印完成,则打印机进入空闲
- 时间用尽,开始统计平均等待时间
- 作业的等待时间:
- 生成作业时,记录生成的时间戳
- 开始打印时,当前时间减去生成时间即可
- 作业的打印时间:
- 生成作业时,记录作业的页数
- 开始打印时,页数除以打印速度即可
# 实例配置:
# 一个实验室中,在任意的一个小时内,有大约10名学生在场,
# 这一个小时内,每人会发起约2次左右的打印,每次1~20页
#
# 打印机性能:
# 草稿模式:每分钟10页
# 正常模式:每分钟5页,质量较高
#
# 如何设置打印机模式,让大家都不会等太久的前提下提高打印质量
#
#
#
from basic.Queue import Queue
import random
class Printer:
def __init__(self, ppm):
self.pagerate = ppm # 打印速度
self.currentTask = None # 打印任务
self.timeRemaining = 0 # 任务倒计时
# 进行1秒打印
# 如果当前任务不为空,进行倒计时
# 如果倒计时结束,任务结束
def tick(self):
if self.currentTask != None:
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()))
for i in range(10):
simulation(3600,10)
双端队列
class Deque:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def addFront(self, item):
self.items.append(item)
def addRear(self, item):
self.items.insert(0, item)
def removeFront(self):
return self.items.pop()
def removeRear(self):
return self.items.pop(0)
def size(self):
return len(self.items)
回文词
from basic.Deque import Deque
# 1.将字符串存入双端队列
# 2.取出双端队列两端进行比较
def palchecker(aString):
chardeque = Deque()
for ch in aString:
chardeque.addRear(ch)
while chardeque.size() > 1:
first = chardeque.removeFront()
last = chardeque.removeRear()
if first != last:
return False
return True
列表
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self, newNext):
self.next = newNext
无序表
class UnorderedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def size(self):
current = self.head
count = 0
while current != None:
count += 1
current = current.getNext()
return count
def search(self, item):
current = self.head
while current != None:
if current.getData() == item:
return True
else:
current = current.getNext()
return False
def remove(self, item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
prevoius = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
有序表
class OrderedList:
def __init__(self):
self.head = None
def search(self, item):
current = self.head
found = False
stop = False
while current != None and not found and not stop:
if current.getData() == item:
found = True
else:
if current.getData() > item:
stop = True
else:
current = current.getNext()
return found
def add(self, item):
current = self.head
previous = None
stop = False
while current != None and not stop:
if current.getData() > item:
stop = True
else:
previous = current
current = current.getNext()
temp = Node(item)
if previous == None:
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current)
previous.setNext(temp)