Big O 表示法在最坏的情况下为您提供算法的复杂性,并且主要用于了解当必须处理的数据量增加时算法将如何随着执行时间的增长而增长。例如(C风格的语法,这个不重要):
List<int> ls = new List<int>(); (1) O(1)
for (int i = 0; i < ls.count; i++) (2) O(1)
foo(i); (3) O(log n) (efficient function)
Cost analysis:
(1) cost: O(1), constant cost
(2) cost: O(1), (int i = 0;)
O(1), (i < ls.count)
O(1), (i++)
---- total: O(1) (constant cost), but it repeats n times (ls.count)
(3) cost: O(log n) (assume it, just an example),
but it repeats n times as it is inside the loop
因此,在渐近符号中,它的成本为:O(n log n)(效率不高)在本例中是一个合理的结果,但以本例为例:
List<int> ls = new List<int>(); (1) O(1)
for (int i = 0; i < ls.count; i++) (2) O(1)
if ( (i mod 2) == 0) ) (*) O(1) (constant cost)
foo(i); (3) O(log n)
相同的算法,但有一个带有条件的新行。在这种情况下,渐近符号将选择最坏的情况,并得出与上述 O(n log n) 相同的结果,此时很容易检测到 (3) 步骤将只执行一半。
数据只是示例,可能并不准确,只是试图说明大 O 表示法的行为。它主要为您提供数据增长时算法的行为(您的算法将是线性的,指数的,对数的,...),但这并不是每个人都知道的“效率”,或者几乎,这不是唯一的“效率”的意思。
但是,这种方法可以检测到“不可能的过程”(对不起,不知道确切的英文单词)算法,这是在早期步骤中需要大量时间来处理的算法(想想例如,阶乘或非常大的矩阵)。
如果您想要进行真实世界的效率研究,您可能更喜欢收集一些真实世界的数据,并使用这些数据对您的算法行为进行真实世界的基准测试。这不是数学风格,但在大多数情况下会更精确(但不是在最坏的情况下!;))。
希望这会有所帮助。