分析原则
1、 只关注“最坏情况”。
2、 忽略常数和低阶项。 —— 常数的大小本就依赖于具体环境
3、 只能预测趋势。 ——复杂度低不一定耗时少,最坏情况不见得总是出现,粗糙的评判
意义
1、 揭示问题本质上的难易程度。
- 能够用多项式算法求解的问题 => 易解
- 只能用指数或阶乘算法求解的问题 => 不易解
2、 粗糙的定量评判也比经验性的定性评判好。
- 只凭少量实例得到的判断很难得到有价值的结论。
函数增长的渐近记号
Big O
𝒇(𝒏)=𝑶(𝒈(𝒏)),当且仅当:存在大于零的常数𝒄,𝒏0>𝟎,使得对所有的𝒏≥𝒏0,都有𝒇(𝒏)≤𝒄𝒈(𝒏)
BigOmega
𝒇(𝒏)=𝛀(𝒈(𝒏)),当且仅当:存在大于零的常数𝒄,𝒏0,使得对所有的𝒏≥𝒏0,都有𝒇(𝒏)≥𝒄𝒈(𝒏)
BigTheta
𝒇(𝒏)=𝚯(𝒈(𝒏)),当且仅当:如果存在正数c1,c2和n0,对于所有的n>=n0,有c1*g(n)<=f(n)<=c2*g(n)
比较
1、O是一个算法最坏情况的度量(g(n)是这个算法的上界,用上界来衡量,是最坏的情况)
2、Big Omega是最好情况的度量(g(n)是这个算法复杂度的下界,用下界来衡量,是最好的情况)
3、Big Theta表达了一个算法的区间,不会好于某某,不会坏于某某
分析方法
在该课程学习过程中,我们大多数都是以最坏情况来分析算法复杂度的,也就是O。下面给出两种最坏情况的分析方法。
Navie分析
- 以循环为重点。
- 循环次数按照最坏情况估计。
- 循环内的操作次数也按最坏情况估计。
- 二者相乘即作为分析结果
# 以冒泡排序为例分析Navie分析可行的情况 下面给出python的代码
def bubble_sort(array):
for i in range(1, len(array)): # 最坏情况为n次
for j in range(0, len(array)-i): #最坏情况为n次
if array[j] > array[j+1]: # 最坏情况为1次
array[j], array[j+1] = array[j+1], array[j] #最坏情况为1次
return array
# 复杂度为 O(n^2)
# 以BFS为例分析Navie分析不可行的情况 下面给出BFS的伪码
# B=所有灰色点构成的集合
# 将所有V中的点标记为白色
# 将s标记为灰色
B.EnQueue(s);
while B非空 # 最多n次
d=B.DeQueue();
for d的所有邻居t # 最多m次
if t的标记为白色
B.EnQueue(t);
将t标记为灰色
将d标记为“黑色”;
# 按Navie分析 复杂度为O(nm)
'''
最坏情况的确是一次循环中检查m条边。但在那种实例下,其他循环岂不是根本不用检查了?'
因此BFS用Navie分析并不合理,不能以循环为重点 而是应该是数据结构也就是BFS维护的队列为核心分析,下面引出聚合分析
''
聚合分析
- 以数据结构为核心。
- 将整个程序看作一个总体。
- 考察数据结构的操作次数。
# 还是以BFS为例分析聚合分析可行的情况
# B=所有灰色点构成的集合
# 将所有V中的点标记为白色
# 将s标记为灰色
B.EnQueue(s);
while B非空 # 最多n次
d=B.DeQueue();
for d的所有邻居t # 最多m次
if t的标记为白色
B.EnQueue(t);
将t标记为灰色
将d标记为“黑色”;
# 总的入队次数是n;总的出队次数是n
# 图中一共有m条边;无向图每条边会被检查2次;有向图每条边会被检查1次
# 按聚合分析 复杂度为O(n+m)
# 分析正确!
- 本文链接:http://mlinku.top/2021/12/20/%E5%A4%8D%E6%9D%82%E5%BA%A6%E5%88%86%E6%9E%90/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。