Python数据结构与算法分析(第2版) —— 第1章 导论 and 第2章 算法分析 and 第3章 基本数据结构
1.4 Python基础
快速初始化列表
myList = [0] * 6
print(myList)
快速建立“矩阵”
myList = [0] * 6
A = [myList] *3
print(A)
Python列表提供的方法
print((54).__add__(21)) # 75
Python字符串提供的方法
Python集合支持的运算
Python集合提供的方法
Python字典支持的运算
Python字典提供的方法
1.4.2 输入与输出
print("Hello","world",sep = "***",end=" ")
格式化字符串可用的类型声明
格式化修改符
2.2.1 大O记法
当问题规模为n时,解决问题所需的时间是T(n)
随着问题规模的增长,T(n)函数的某一部分会比其余部分增长得更快。数量级 → 当n增长时,T(n)增长最快的部分。
数量级常被称作大O记法,记作O(f(n))
常见的大O函数
2.2.2 异序词检测示例
如果一个字符串只是重排了另一个字符串的字符,那么这个字符串就是另一个的异序词,比如heart和earth,以及python和typhon。
计数法
def anagramSolution(s1,s2):
c1 = [0] * 26
c2 = [0] * 26
for i in range(len(s1)):
pos = ord(s1[i]) - ord("a")
c1[pos] = c1[pos] + 1
for i in range(len(s2)):
pos = ord(s2[i]) - ord("a")
c2[pos] = c2[pos] + 1
j = 0
stillOK = True
while j < 26 and stillOK:
if c1[j] == c2[j]:
j = j + 1
else:
stillOK = False
return stillOK
s1 = "heart"
s2 = "earth"
print(anagramSolution(s1,s2))
2.3 Python数据结构的性能
2.3.1 列表
创建列表
l = list(range(1000))
print(l)
2.3.2 字典
在包含操作中,字典速度比列表更快
3.2 线性数据结构
一旦某个元素被添加进来,它与前后元素的相对位置将保持不变。这样的数据集合经常被称为线性数据结构。
3.3 栈
LIFO(last-in first-out),后进先出
3.3.3 用Python实现栈
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)
也可以将列表的头部作为栈的顶端
3.3.4 匹配括号
from pythonds.basic import Stack
def parChecker(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
s = "((()))"
print(parChecker(s))
3.3.5 普通情况:匹配符号
from pythonds.basic import Stack
def matches(open,close):
opens = "([{"
closes = ")]}"
return opens.index(open) == closes.index(close)
def parChecker(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
s = "([{}])"
print(parChecker(s))
3.3.6 将十进制数转换成任意进制数
from pythonds.basic import Stack
def baseConverter(decNumber,base):
digits = "0123456789ABCDEF"
remstack = Stack()
while decNumber > 0:
rem = decNumber % base
remstack.push(rem)
decNumber = decNumber // base
newString = ""
while not remstack.isEmpty():
newString = newString + digits[remstack.pop()]
return newString
x = 4
print(baseConverter(x,2))
3.3.7 前序、中序和后序表达式
前序表达式和后序表达式是的运算顺序完全由运算符的位置决定
用Python实现从中序表达式到后序表达式的转换
from pythonds.basic import Stack
import string
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 string.ascii_uppercase:
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)
s = "( A + B ) * ( C + D )"
print(infixToPostfix(s))
用Python实现后序表达式的计算
from pythonds.basic import Stack
def doMath(op,op1,op2):
if op == "*":
return op1 * op2
elif op == "/":
return op1 / op2
elif op == "+":
return op1 + op2
else:
return op1 - op2
def postfixEval(postfixExpr):
operandStack = Stack()
tokenList = postfixExpr.split()
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()
s = "4 5 6 * +"
print(postfixEval(s))
3.4 队列
FIFO(first-in first-out) 先进先出
用Python实现队列
class Queue:
def __init__(self):
self.items = []
# 判空
def isEmpty(self):
return self.items == []
# 进队
def enqueue(self,item):
self.items.insert(0,item)
# 出队
def dequeue(self):
return self.items.pop()
# 队列大小
def size(self):
return len(self.items)
传土豆模拟程序
from pythonds.basic import Queue
def hotPotato(namelist,num):
simqueue = Queue()
for name in namelist:
simqueue.enqueue(name)
while simqueue.size() > 1:
for i in range(num):
simqueue.enqueue(simqueue.dequeue())
simqueue.dequeue()
return simqueue.dequeue()
names = ["Bill","David","Susan","Jane","Kent","Brad"]
print(hotPotato(names,7))
3.4.5 模拟:打印任务
import random
from pythonds.basic import Queue
class Printer:
def __init__(self,ppm):
self.pagerate = ppm
self.currentTask = None
self.timeRemaining = 0
def tick(self):
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)
if num == 180:
return True
else:
return False
def simulation(numSeconds,pagePerMinute):
labprinter = Printer(pagePerMinute)
printQueue = Queue()
waittingtimes = []
for currentSecond in range(numSeconds):
if newPrintTask():
task = Task(currentSecond)
printQueue.enqueue(task)
if (not labprinter.busy()) and (not printQueue.isEmpty()):
nexttask = printQueue.dequeue()
waittingtimes.append(nexttask.waitTime(currentSecond))
labprinter.startNext(nexttask)
labprinter.tick()
averageWait = sum(waittingtimes) / len(waittingtimes)
print("Average Wait %6.2f secs %3d tasks remaining." % (averageWait,printQueue.size()) )
for i in range(10):
simulation(3600,5)
3.5 双端队列
双端队列对在哪一端添加和移除元素没有任何限制,新元素既可以被添加到前端,也可以被添加到后端,同理,已有的元素也能从任意一端移除。
用Python实现双端队列
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)
3.5.4 回文检测器
from pythonds.basic import Deque
def palchecker(aString):
chardeque = Deque()
for ch in aString:
chardeque.addRear(ch)
stillEqual = True
while chardeque.size() > 1 and stillEqual:
first = chardeque.removeFront()
last = chardeque.removeRear()
if first != last:
stillEqual = False
return stillEqual
s = "roor"
print(palchecker(s))
3.6 列表
3.6.2 实现无序列表:链表
节点对象包含元素及指向下一个节点的引用
Node类:
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 length(self):
current = self.head
count = 0
while current != None:
count += 1
current = current.getNext()
return count
# 是否存在某元素
def search(self,item):
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
# 移除某元素
def remove(self,item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
# 在尾部添加节点
def append(self,item):
newnode = Node(item,None)
temp = self.head
if self.head == None:
self.head = newnode
else:
while temp.next != None:
temp = temp.next
temp.next = newnode
# 在链表中插入节点
def insert(self,position,newdata):
temp = self.head
j = 0
newnode = Node(newdata)
if self.length() < position:
print("error")
else:
while j < position - 1:
temp = temp.next
j += 1
newnode.next = temp.next
temp.next = newnode
# 删除某个节点
def pop(self,position):
temp = self.head
j = 0
if self.length() < position:
print("error")
else:
while j < position - 1:
temp = temp.next
j += 1
temp.next = temp.next.next
mylist = UnorderedList()
mylist.add(15)
mylist.add(20)
print(mylist.length())
print(mylist.search(15))
print("error")
else:
while j < position - 1:
temp = temp.next
j += 1
newnode.next = temp.next
temp.next = newnode
# 删除某个节点
def pop(self,position):
temp = self.head
j = 0
if self.length() < position:
print("error")
else:
while j < position - 1:
temp = temp.next
j += 1
temp.next = temp.next.next
mylist = UnorderedList()
mylist.add(15)
mylist.add(20)
print(mylist.length())
print(mylist.search(15))