一个好主意是确定每个附加任务会产生多少工作。这可能取决于算法的结构。
例如,假设您在城市中有一些虚拟汽车。在任何时候,您都希望每辆车都有一张地图,显示所有汽车的位置。
解决此问题的一种方法是:
每辆车{
确定我的位置;
每辆车{
将我的位置添加到这辆车的地图上;
}
}
这看起来很简单:查看第一辆车的位置,将其添加到其他所有车辆的地图中。然后查看第二辆车的位置,将其添加到其他每辆车的地图中。等等。
但是有一个可扩展性问题。当有 2 辆车时,此策略需要 4 个“添加我的位置”步骤;当有 3 辆车时,需要 9 个步骤。对于每个“位置更新”,您必须循环浏览整个汽车列表 - 每辆汽车都需要更新其位置。
忽略每辆汽车必须做多少其他事情(例如,计算单个汽车的位置可能需要固定数量的步骤),对于 N 辆汽车,运行此算法需要 N 2次“访问汽车” . 当你有 5 辆车和 25 步时,这没问题。但是当您添加汽车时,您会看到系统陷入困境。100辆车走10000步,101辆车走10201步!
更好的方法是撤消 for 循环的嵌套。
每辆车{
将我的职位添加到列表中;
}
每辆车{
给我一份主清单的更新副本;
}
使用这种策略,步数是 N 的倍数,而不是 N 2的倍数。所以 100 辆汽车需要 1 辆汽车 100 倍的工作量,而不是 10,000 倍的工作量。
这个概念有时用“大 O 表示法”表示——所需的步数是“N 的大 O”或“N 2的大 O ”。
请注意,此概念仅与可扩展性有关,而不是优化每辆车的步数。在这里,我们不在乎每辆车走 5 步还是 50 步——主要是 N 辆车走 (X * N) 步,而不是 (X * N 2 )。