摘要:1.计算领域的核心理念2.渐进记法3.图与树的实现4.提防黑盒子
1.计算领域的核心理念
算法---一个执行过程,包含了能够解决某个特定问题的有限步骤集。(图灵机可以理解为是这个待解决问题的正规描述形式)
图灵机---计算领域的理论核心,图灵机有着各种不同的具体实现,但每种实现都可以看做一个有限状态机:由一个有限的状态集(包括已完成部分)与各种用于触发读写操作及不同状态切换的潜在符号共同组成。(可以将其看做机器运行所需的规则)。
随机存取机---适用于更细粒度上的算法分析,从标准单处理器计算机中简化出的一种抽象模型,好比有一块可以直接存取的内存,而不是同图灵机那样的可滚动的纸带。
应具备的属性:
- 没有任何形式的并发执行,只有在执行完一条指令后才能执行其他指令。
- 所有标准基本操作,如算术运算 比较运算 以及内存存取,所耗费的时间都是常数级的,且没有更复杂的基本操作 如排序。
- 计算机字尽管有限,但必须足够大,大到能满足我们在解决问题中所有内存编址的需求,此外还要有一定的额外变量。
问题---就目标而言,问题实际就是输入与输出之间的某种关系,更精确的讲,就是指一组集合对之间的数学意义上的关系,并且借由指定这种关系的过程,问题会被确定下来。
编码---对输入 0 1 编码,问题实例的大小,可以简单看成编码它所需的内存大小(通常与编码本身的确切属性没太大关系)。
2.渐进记法
append insert 的例子;
研究算法分析时要关注的重点:常数单位上的差距(通常取决于一些特定事物如通用编程语言的性能,硬件速度等);焦点 集中在那些能够独立于具体实现之外的属性。
2.1. 渐进记法是用于分析算法与数据结构的重要工具,核心思想为提供一种资源保护形式,主要用于分析某项功能在应对一定规模参数输入时所需要的资源(时间 内存 等)
渐进记法使用由希腊字母构成的记号体系。Ο记法代表渐进上界,Ω记法代表渐进下界,Θ记法代表前两种记法的交集。
2.2. 渐进记法 简化了我们面临的数学问题。
时间复杂度 | 相关名称 | 相关示例及说明 |
Θ(1) | 常数级 | 哈希表的查询与修改 |
Θ(lgn) | 对数级 | 二分搜索 |
Θ(n) | 线性级 | 列表遍历 |
Θ(nlgn) | 线性对数级 | 任意值得最优化排序,其复杂度等同于Θ(lgn!) |
Θ(n2) | 平方级 | 拿n个对象进行相互比对 |
Θ(n3) | 立方级 | Floyd-Warshall算法 |
Ο(nk) | 多项式级 | 基于n的k层嵌套循环(k为整数,k>0) |
Ω(kn) | 指数级 | 每n项产生一个子集(k>1) |
Θ(n!) | 阶乘级 | 对n个值执行全排列操作 |
多项式级与指数级分割着易处理问题和难处理问题,仅一般而言。
几条简单规则:加法运算中,只以阶数最高的被加数为准;乘法运算中,常数因子忽略不计;保持相关上下界的严谨性;Θ(f) + Θ(g) = Θ(f+g);Θ(f) * Θ(g) = Θ(f*g)。
三种重要情况:1.最好情况(理想输入时的运行时间)2.最坏情况(所能给的最佳保证)3.平均情况(回避)
实证式算法评估:1.当没有把握时,就把可能的解决方案都试一遍。2.用timeit模块进行计时:
import timeit timeit.timeit("x = 2 + 2") $命令行环境调用 $ python -m timeit -s"omport mymodule as m" "m.myfunction()"
3.使用profiler找出瓶颈:给出关于执行时间都都花在哪里的详细信息,从而确定代码中需要优化的部分。当主函数是main()时,执行下列代码,可以给出各个函数的运行时间。(可以使用Python Call Graph 工具可视化的看到代码的调用情况)
import cProfile cProfile.run('main()')
4.绘制出结果。matplotlib绘制工具包
5.根据计时比对结果做出判断
6.通过相关实验对渐进时间做出判断
3.图Graph与树Tree的实现
图结构可以用来表现似乎所有类型的结构与系统,而树结构只是图结构的一种特殊情况但相当普遍。如果我们的问题可以用树结构来描述时,基本上已经有了有效的解决方案。
从七桥问题开始:全面介绍图论 https://www.jiqizhixin.com/articles/2018-03-11-2 (https://medium.freecodecamp.org/i-dont-understand-graph-theory-1c96572a1401)
数据结构与算法 图论 https://zhuanlan.zhihu.com/p/25498681
入门图论与网络分析 含python代码 https://www.jiqizhixin.com/articles/2018-08-07-16
3.1邻接列表
#简单明了的邻接集表示方法 a,b,c,d,e,f,g,h = range(8) N = [ {b,c,d,e,f}, #a {c,e}, #b {d}, #c {e}, #d {f}, #e {c,g,h}, #f {f,h}, #g {f,g}, #h ] >>>b in N[a] True >>>len(N[f]) 3
如果某些代码存在于某个源文件里,而我们又想在交互解释其中研究的话,使用python的 - i 开关来运行:
python -i listing.py
#其他表示方法 #邻接列表 成员检测时速度放缓 a,b,c,d,e,f,g,h = range(8) N = [ [b,c,d,e,f], #a [c,e], #b [d], #c [e], #d [f], #e [c,g,h], #f [f,h], #g [f,g], #h ] #加权邻接字典 a,b,c,d,e,f,g,h = range(8) N = [ {b:2,c:1,d:3,e:9,f:4], #a {c:4,e:3}, #b {d:5}, #c {e:1}, #d {f:2}, #e {c:5,g:6,h:7}, #f {f:2,h:6}, #g {f:3,g:4}, #h ] #邻接集的字典表示法 类似字符类的邻接列表(成本略低) a,b,c,d,e,f,g,h = range(8) N = { 'a': set('bcdef'), #a 'b': set('ce'), #b 'c': set('d'), #c 'd': set('e'), #d 'e': set('f'), #e 'f': set('cgh'), #f 'g': set('fh'), #g 'h': set('fg'), #h } #一个图的最佳表示法 取决于 我们要用它做什么
3.2邻接矩阵
节点编号从0 到V-1,用0 和1 来充当真值(无权图中),对角线上的值全为0 ,在无向图邻接矩阵关于对角线对称相等,
#用嵌套list实现的邻接矩阵 a,b,c,d,e,f,g,h = range(8) N = [ [0,1,1,1,1,1,0,0], #a [0,0,1,0,1,0,0,0], #b [0,0,0,1,0,0,0,0], #c [0,0,0,0,1,0,0,0], #d [0,0,0,0,0,1,0,0], #e [0,0,1,0,0,1,0,0], #f [0,0,0,0,0,1,0,1], #g [0,0,0,0,0,1,1,0], #h ] #可以更改不同的权值 #非法的权值就设置为极大值, float('inf') inf = float('inf') #权值为 inf
3.3树的实现
树本身就是图的特殊情况,但许多特定问题用特定的树结构更容易实现。
#简单的树结构 表示为二叉列表 >>>T = [["a","b"],["c"],["d",["e","f"]]] >>>T[0][1] 'b' >>>T[2][1][0] 'e' #二叉树类 class Tree: def __init__(self,left,right): self.left = left self.right = right >>>t = Tree(Tree("a","b"),Tree("c","d")) >>>t.right.left 'c' #多路搜索类 class Tree: def __init__(self,kids,next=None): self.kids = self.val = kids self.next = next >>>t = Tree(Tree("a"),Tree("b",Tree("c",Tree("d"))))) >>>t.kids.next.next.val 'c'
参考:Bunch模式 https://www.cnblogs.com/GF66/p/9785485.html
3.4存在多种表示法
空泛的判断句子没有,我们更应该针对具体问题思考该任务的渐进性能。
最主要的为以上介绍的两种。另外,需注意编程中没有注意就用到的图实现(隐式)
参考:图结构库
python-graph : https://github.com/pmatiello/python-graph
Graph-tool : https://graph-tool.skewed.de/
此外还有 Pygr 基于图结构的数据库 Gato基于图结构的动画工具箱 PADS基于图结构的算法集
4.提防黑箱子
编程时,我们必须依赖一些并不是自己编写的组件,称为黑箱子。不注意的话,Python和机器本身的很多机制会成为我们的绊脚石。
- 当性能成为重要问题时,要注重分析实际而不是相信直觉
- 当正确性至关重要时,最好用不同的实现方法核实答案
4.1隐性平方级操作
4.2浮点运算的麻烦
5.小结
基础概念,渐进记法与图结构,黑箱子......
加油 嘿嘿嘿!