C++ 数据结构(一)绪论(4)算法分析

本文介绍了C++中算法分析的主要任务和方法,重点讨论了级数在算法复杂度分析中的应用,包括算数级数、幂方级数、几何级数、收敛级数、调和级数和对数级数。并通过取非极端元素的问题展示了如何利用这些级数概念来理解和分析算法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源:我的博客站 OceanicKang |《C++ 数据结构(一)绪论(4)算法分析》

上一篇:《C++ 数据结构(一)绪论(3)复杂度》

主要任务

算法分析的两个主要任务 = 正确性(不变性 * 单调性) + 复杂度

C++ 等高级语言的 基本指令,均等效于常数条 RAM 的 基本指令

在渐进意义下,二者大体相当于:

  • 分支转向:goto // 算法的灵魂;出于结构化考虑,被隐藏了
  • 迭代循环:for()、while()、… // 本质上就是 “if + goto"
  • 调用 + 递归(自我调用) // 本质上也是 goto

主要方法

复杂度分析的主要方法:

  • 迭代:级数求和
  • 递归:递归跟踪 + 递推方程
  • 猜测 + 验证

级数

算数级数

与末项平方同阶

T ( n ) = 1 + 2 + ⋯ + n = n ( n + 1 ) 2 = O ( n 2 ) T(n) = 1 + 2 + \cdots + n = \frac{n(n+1)}{2} = O(n^2) T(n)=1+2++n=2n(n+1)=O(n2)

幂方级数

比幂次高出 一阶

∑ k = 0 n k d ≈ ∫ 0 n x d + 1   d x = 1 d + 1 x d + 1 ∣ 0 n = 1 d + 1 n d + 1 = O ( n d + 1 ) \sum_{k=0}^{n} k^d \approx \int_{0}^{n} x^{d+1} \ dx = \frac{1}{d+1} x^{d+1} |_0^n = \frac{1}{d+1} n^{d+1} = O(n^{d+1}) k=0nkd0nxd+1 dx=d+11xd+10n=d+11nd+1=O(nd+1)

T 2 ( n ) = 1 2 + 2 2 + 3 2 + ⋯ + n 2 = n ( n + 1 ) ( 2 n + 1 ) 6 = O ( n 3 ) T_2 (n) = 1^2 + 2^2 + 3^2 + \cdots + n^2 = \frac{n(n+1)(2n+1)}{6} = O(n^3) T2(n)=12+22+32++n2=6n(n+1)(2n+1)=O(n3)

T 3 ( n ) = 1 3 + 2 3 + 3 3 + ⋯ + n 3 = n 2 ( n + 1 ) 2 4 = O ( n 4 ) T_3 (n) = 1^3 + 2^3 + 3^3 + \cdots + n^3 = \frac{n^2(n+1)^2}{4} = O(n^4) T3(n)=13+23+33++n3=4n2(n+1)2=O(n4)

T 4 ( n ) = 1 4 + 2 4 + 3 4 + ⋯ + n 4 = n ( n + 1 ) ( 2 n + 1 ) ( 3 n 2 + 3 n − 1 30 = O ( n 5 ) T_4 (n) = 1^4 + 2^4 + 3^4 + \cdots + n^4 = \frac{n(n+1)(2n+1)(3n^2+3n-1}{30} = O(n^5) T4(n)=14+24+34++n4=30n(n+1)(2n+1)(3n2+3n1=O(n5)

几何级数

与末项同阶

T a ( n ) = a 0 + a 1 + ⋯ + a n = a n + 1 − 1 a − 1 = O ( a n ) T_a (n) = a^0 + a^1 + \cdots + a^n = \frac{a^{n+1} - 1}{a-1} = O(a^n) Ta(n)=a0+a1++an=a1an+11=O(an)

1 + 2 + 4 + ⋯ + 2 n = 2 n + 1 − 1 = O ( 2 n + 1 ) = O ( 2 n ) 1 + 2 + 4 + \cdots + 2^n = 2^{n+1} - 1 = O(2^{n+1}) = O(2^n) 1+2+4++2n=2n+11=O(2n+1)=O(2n)

收敛级数

2 + 3 2 + 4 3 + ⋯ + n n − 1 = 1 − 1 n = O ( 1 ) 2 + \frac{3}{2} + \frac{4}{3} + \cdots + \frac{n}{n-1} = 1 - \frac{1}{n} = O(1) 2+23+34++n1n=1n1=O(1)

1 + 1 2 2 + ⋯ + 1 n 2 &lt; 1 + 1 2 2 + ⋯ = π 2 6 = O ( 1 ) 1 + \frac{1}{2^2} + \cdots + \frac{1}{n^2} &lt; 1 + \frac{1}{2^2} + \cdots = \frac{\pi^2}{6} = O(1) 1+221++n21<1+221+=6π2=O(1)

1 3 + 1 7 + 1 8 + 1 15 + 1 24 + 1 26 + 1 31 + 1 35 + ⋯ = 1 = O ( 1 ) \frac{1}{3} + \frac{1}{7} + \frac{1}{8} + \frac{1}{15} + \frac{1}{24} + \frac{1}{26} + \frac{1}{31} + \frac{1}{35} + \cdots = 1 = O(1) 31+71+81+151+241+261+311+351+=1=O(1)

调和级数

h ( n ) = 1 + 1 2 + 1 3 + ⋯ + 1 n = Θ ( log ⁡ n ) h(n) = 1 + \frac{1}{2} + \frac{1}{3} + \cdots + \frac{1}{n} = \Theta (\log n) h(n)=1+21+31++n1=Θ(logn)

对数级数

log ⁡ 1 + log ⁡ 2 + log ⁡ 3 + ⋯ + log ⁡ n = log ⁡ ( n ! ) = Θ ( n log ⁡ n ) \log 1 + \log 2 + \log 3 + \cdots + \log n = \log (n!) = \Theta (n \log n) log1+log2+log3++logn=log(n!)=Θ(nlogn)

循环 VS 级数

for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
        function(i, j);

算数级数: ∑ i = 0 n − 1 n = n + n + ⋯ + n = n ∗ n = O ( n 2 ) \sum_{i=0}^{n-1} n = n + n + \cdots + n = n * n = O(n^2) i=0n1n=n+n++n=nn=O(n2)

1.png


for (int i = 0; i < n; i++)
    for (int j = 0; j < i; j++)
        function(i, j);

算数级数: ∑ i = 0 n − 1 i = 0 + 1 + ⋯ + ( n − 1 ) = n ( n − 1 ) 2 = O ( n 2 ) \sum_{i=0}^{n-1} i = 0 + 1 + \cdots + (n-1) = \frac{n(n-1)}{2} = O(n^2) i=0n1i=0+1++(n1)=2n(n1)=O(n2)

2.png


for (int i = 0; i < n; i++)
    for (int j = 0; j < i; j += 2013)
        function(i, j);

算数级数:…

3.png


for (int i = 1; i < n; i <<= 1)
    for (int j = 0; j < i; j++)
        function(i, j);

几何级数: 1 + 2 + 4 + ⋯ + 2 ⌊ log ⁡ 2 ( n − 1 ) ⌋ = ∑ k = 0 ⌊ log ⁡ 2 ( n − 1 ) ⌋ 2 k = 2 ⌈ log ⁡ 2 n ⌉ = O ( n ) 1 + 2 + 4 + \cdots + 2^{ \lfloor \log_2 (n-1) \rfloor } = \sum_{k=0}^{ \lfloor \log_2 (n-1) \rfloor } 2^k = 2^{ \lceil \log_2 n \rceil } = O(n) 1+2+4++2log2(n1)=k=0log2(n1)2k=2log2n=O(n)

4.png


for (int i = 0; i <= n; i++)
    for (int j = 1; j < i; j += j)
        function(i, j);

几何级数:

∑ k = 0 n ⌈ log ⁡ 2 i ⌉ = O ( n log ⁡ n ) &ThickSpace; ( i = 0 , 1 , 2 , 3   4 , 5   8 , 9   16 , ⋯ &ThinSpace; ) = 0 + 0 + 1 + 2 ∗ 2 + 3 ∗ 4 + 4 ∗ 8 + ⋯ = ∑ k = 0 ⋯ log ⁡ n ( k ∗ 2 k − 1 ) = O ( log ⁡ n ∗ 2 log ⁡ n ) \sum_{k=0}^{n} \lceil \log_2 i \rceil = O(n \log n) \; (i = 0, 1, 2, 3~4, 5~8, 9~16, \cdots ) = 0 + 0 + 1 + 2 * 2 + 3 * 4 + 4 * 8 + \cdots = \sum_{k=0 \cdots \log n} (k * 2^{k-1}) = O(\log n * 2^{\log n}) k=0nlog2i=O(nlogn)(i=0,1,2,3 4,5 8,9 16,)=0+0+1+22+34+48+=k=0logn(k2k1)=O(logn2logn)

5.png

示例

取非极端元素

问题

给定整数子集 S,|S| = n ≥ 3

找出元素 a ∈ S,a ≠ max(S) 且 a ≠ min(S)

算法

从 S 中任取三个元素 {x, y, z}

若 S 以数组形式给出,不妨取前三个

由于 S 是集合,这三个元素必 互异

确定并排除其中的最小、最大值

不妨设 x = max{x, y, z}, y = min{x, y, z}

输出剩下的元素 z

总结

无论输入规模 n 多大,上述算法需要的执行时间都不变

T ( n ) = 常 数 = O ( 1 ) = Ω ( 1 ) = Θ ( 1 ) T(n) = 常数 = O(1) = \Omega (1) = \Theta (1) T(n)==O(1)=Ω(1)=Θ(1)

下一篇:《C++ 数据结构(一)绪论(5)迭代与递归(1)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值