来自Richard Bird, Pearls of Functional Algorithm Design (2010),第6页:
对于纯函数式编程器,更新操作采用数组大小的对数时间。公平地说,程序程序员也很欣赏恒定时间索引和更新 只有当数组很小时才有可能。
在什么条件下数组有非恒定时间访问?这与CPU缓存有关吗?
答案 0 :(得分:5)
大多数现代机器架构都试图提供小型单位时间内存访问。
他们失败了。相反,我们看到不同速度的缓存层。
问题很简单:光速。如果你需要一个巨大的记忆[数组](在极端情况下,想象一个像仙女座星系大小的记忆),它将占用巨大的空间,光线不能在短时间内穿越巨大的空间。信息的传播速度不能超过光速。你从一开始就被物理学搞砸了。
所以你能做的最好的事情就是建立记忆的一部分"附近"其中光仅需要几分之一纳秒来遍历(因此寄存器和L1缓存),并且部分内存远离磁盘驱动器(磁盘驱动器)。其他实际的复杂情况随之而来,例如电容(想想惯性),以减缓对更远的物品的访问。
现在,如果您愿意将最远的内存元素的访问时间作为" unit"时间,是的,访问所有内容需要相同的时间,例如,O(1)。在实际计算中,我们大多数时候都会以这种方式处理RAM内存,而我们会忽略其他较慢的设备,以避免搞砸我们的简单模型。
然后你会发现那些对此并不满意的人,瞧,你有人优化缓存线访问。因此理论上它可能是O(1),对于小数组(适合第一级缓存)就像O(1)一样,但它通常不在实践中。
一个极端实际的例子是一个不适合主存储器的阵列;现在,数组访问可能会导致从磁盘进行分页。
有时即使在这种情况下我们也不在乎。谷歌本质上是一个巨大的缓存。我们倾向于将Google搜索视为O(1)。
答案 1 :(得分:2)
橘子会变成红色吗?
是的,由于多种原因,它们可能会变红 -
关键是,我认为你问的问题,实际上是关于两个正交概念。即 -
Big O Notation - " 在数学中,大O符号描述了当参数倾向于特定值或无穷大时函数的限制行为,通常是在更简单的函数方面。"
VS
实用性(硬件和软件),一个优秀的软件工程师应该注意,同时架构/设计他们的应用程序和编写代码。
换句话说,虽然Big O Notation的概念可以称为学术性的,但它是最合适的分类算法复杂性(时间/空间)的方式..那就是它结束了。 没有必要在正交问题上混淆水域。
要明确的是,我不说人们不应该知道底层实施细节和工作情况,这会影响您编写的软件的性能..但是有没有必要将两者混合在一起。例如,说 -
是否有意义数组没有持续时间访问(带索引),因为 -
就像我的苹果和橙色的例子一样,当你阅读我越来越荒谬的例子时,希望我想说明的一点是明确的。
结论 - 任何一天,我都会回答问题" Do Arrays有持续时间O(1)访问权限(带索引)&# 34;,因为是..毫无疑问或ifs和buts,他们确实。
修改强>
换句话说 - 如果O(1)不是答案..那么O(log n),O(n log n),O(n ^ 2)或O(n ^ 3)都不是.....当然不是42。
答案 2 :(得分:1)
他在谈论计算模型,特别是基于单词的RAM机器
RAM机器是与实际计算机非常相似的形式化:我们将计算机存储器建模为每个w位的大型存储器字,我们可以在O(1)时间内读/写任何字
但我们还有一些重要的事情要定义:一个词应该有多大?
我们需要字大小w≥Ω(log n)才能至少解决输入的n个部分。 因此,基于字的RAM通常假定字长为O(log n)
但是让机器的单词长度取决于输入的大小看起来很奇怪和不切实际
如果我们保持字长固定怎么办?然后即使在指针之后需要Ω(log n)时间来读取整个指针
我们需要Ω(log n)字来存储指针和Ω(log n)时间来访问输入元素
答案 3 :(得分:0)
如果一种语言支持稀疏数组,则访问该数组必须通过一个目录,而一个树形结构的目录将具有非线性访问时间。或者你的意思是现实条件? ; - )