数据结构(python)
在紧张的备考日语的过程中抽时间刷一下北京大学的python数据结构。查缺补漏。
/整除 >>>divmod(9,5) (1,4) /复数 >>>import cmath >>>(1+2j)*(1+3j) (-5+5j) >>>(1+4j).imag 4.0 >>>(1+4j).real 1.0
早就已经知道的C语言要想使用一个变量必须先初始化,Python的变量机制是引用数据对象,例如赋值语句‘a = 0’是创建a这个变量然后指向数值0,变量可以指向任意一个数据对象,变量的类型会随着变量的变化而变化。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>>a = 0 2 >>>type(a) 3 <class 'int'> 4 5 >>>a = '0' 6 >>>type(a) 7 <class 'str'>
由于变量的上一个性质,变量间的指向会因为前一个变量发生变化而变化。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>>alist = [1,2,3] 2 >>>blist = [alist] * 3 3 >>>blist 4 [[1,2,3],[1,2,3],[1,2,3]] 5 >>>alist[1] = 'a' 6 >>>blist 7 [[1,'a',3],[1,'a',3],[1,'a',3]]
Python集合(set)是不重复元素的无序组合。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>>a = {1,2,3} 2 >>>b = {2,3,4} 3 >>>a|b 4 {1,2,3,4} 5 >>>a&b 6 {2,3} 7 >>>a-b 8 {1} 9 >>>b-a 10 {4) 11 >>>a^b 12 {1,4} 13 >>>/ < ,<= ,> ,>= 子集,真子集,超集,真超集
调用函数:所有可以调用的事物成为callable。函数的参数写在括号里,多个参数之间用逗号隔开。如果不加括号则表示对他的调用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>>import math 2 >>>a = math,sqrt(9) 3 >>>a 4 3.0 5 >>>a = math.sqrt 6 >>>a(9) 7 3.0
从键盘输入:input()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /默认输入的数据格式为str 2 >>>name = input('please input your name:') 3 please input your name:delete 4 >>>a,b = input().split() 5 1 2 6 >>>type(a) 7 <class 'str'>
栈、队列和树:具体的不再罗列,参见PDF。
递归:在程序中将问题不断缩减成小问题,通过不断调用自身来达到解决问题的目的。
递归三定律:
1,递归算法必须有一个基本结束条件(最小规模问题的直接解决)
2,递归算法必须能改变状态向基本结束条件演进(减小问题规模)
3,递归算法必须调用自身(解决减小了规模的相同问题)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 improt turtle 2 t = turtle.Turtle() 3 w = turtle.Screen() 4 5 def draw(_t , len): 6 if len > 0: 7 _t.forward(len) 8 _t.right(90) 9 draw(_t,len-5) 10 11 draw(t,100)
动态规划问题:动态规划算法通常基于一个递推公式及一个或多个初始状态。 当前子问题的解将由上一次子问题的解推出。使用动态规划来解题只需要多项式时间复杂度, 因此它比回溯法、暴力法等要快许多。问题的解决依赖于上一个子问题解决。即状态和状态转移方程的建立,以找零钱为例。
给定change,求解最少的硬币数量。
递归穷举的方法因为迭代深度和迭代次数而受限。
解决方法是将重复步骤去重
例:[1,5,10]
找零:28
求 : minNum
解决方法:
d(28) = d(10+18) = d(18) + 1
d(28) = d(5 + 23) = d(23) + 1
d(28) = d(1 + 27) = d(27) + 1
if d(28) < d(18)+1 : minNum = d(18)+1
在这里发现递归可以完成。先写一个递归版本。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def reC(coinsList,change): 2 minCount = change 3 for i in [c for c in coinList if c <= change]: 4 if reC(coinsList,change - i) + 1 < minCount: 5 minCount = reC(coinsList,change - i) 6 return minCount
测试发现递归完全可以实现找零。但是增大找零的数目会发现编译器因为递归的调用次数增加而崩溃。
为了对他进行改进,可以引入容器的概念,将一些重复计算量进行优化。
例如:d(0) = 0; d(1) = d(0) + 1 = 0+1 ; d(2) = d(0) + 2 = d(1) + 1,自下而上采用递推方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def dp(coinsList , change , minCount) : 2 for cents in range(change + i): 3 coinCount = cents 4 for i in [c for c in coinList if c <= cents]: 5 if minCount[cents-j] + 1 < coinCount: 6 coinCount = minCount[cents - j] + 1 7 minCoins[cents] = coinCount 8 return coinCount
二分查找:适用于有序数列。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def binaryFind(list,goal): 2 left = 0 3 right = len(list) - 1 4 result = False 5 while left < right and not result: 6 middle = (left + right)//2 7 if list[middle] == goal: 8 result = True 9 elif list[middle] < goal: 10 left = middle + 1 11 else: 12 right = middle - 1 13 return result
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def dpBinaryfind(list,goal): 2 if len(list) == 0: 3 return False 4 else: 5 middle = len(list)//2 6 if list(middle) == goal: 7 return True 8 elif list(middle) < goal: 9 return dpBinaryfind(list[middle : ],goal) 10 else: 11 return dpBinaryfind(list[: middle],goal)
以上。