【发布时间】:2014-01-04 03:18:59
【问题描述】:
在 Java 中,假设我需要在代码中多次访问 array1[index]。
即使对于非常大的数组,我是否可以假设每个单独的数组访问都需要恒定的时间?
这在语言或底层架构之间会有所不同吗?
【问题讨论】:
标签: java optimization data-structures time-complexity
在 Java 中,假设我需要在代码中多次访问 array1[index]。
即使对于非常大的数组,我是否可以假设每个单独的数组访问都需要恒定的时间?
这在语言或底层架构之间会有所不同吗?
【问题讨论】:
标签: java optimization data-structures time-complexity
数组查找总是 O(1)。它不依赖于数组的大小。数组的基本思想是它包含具有固定大小的对象/引用,因此您只需执行size * index 即可获得您要查找的对象的位置。
所以它不像LinkedList(即O(n),也不是HashMap,即O(1) 摊销。
我认为大多数语言都是这种情况。 javascript 可能是一个例外,因此请务必检查您使用的语言的文档。
【讨论】:
O(1)。
对于 array1 大小为 N 的大值,我可以假设每个单个数组访问 (array1[index]) 需要恒定时间吗?
在 Java 中,是的。同样在 C、C++ 和 C# 中,除非可能超出范围的操作系统级内存分页问题。
此访问时间是否取决于语言(java 与 C++)或底层架构?
它可以,如果所讨论的语言将事物称为“数组”,而不是通常的“连续内存块”意义上的真正数组。 (JavaScript 会这样做;它的 Array ([]) 类型 is really a map;PHP 使用术语“数组”作为“关联数组”[例如,映射]的简写。)因此,对于给定的环境/语言,它是值得的检查该术语没有被滥用或随意使用。
【讨论】:
访问数组中的元素是常数时间(它只是计算地址偏移量)。对于您列出的所有语言,此行为都是一致的。虽然不应该假定它适用于所有语言,但它适用于大多数语言。
在缓存未命中/命中、管道等方面存在一些复杂性,但基本上是恒定时间。
List 并非如此。一些 List 实现为不同的操作提供了不同的性能特征。
扩展复杂性:
问题是“大型数组的访问速度会变慢”。正确答案是“是”。
就访问顺序而言,它将保持 O(1),但实际访问可能需要相当长的时间。例如,如果数组的大小导致您出现缓存未命中(因此数据需要从主内存获取到处理器的缓存)和/或内存分页问题(因此需要从磁盘获取数据),它将变得更慢,尽管那是任何大型数据集的属性,而不是数组。
在大多数情况下,这种差异并不值得担心。在您开始担心诸如缓存未命中之类的事情之前,我们正在谈论相当重的优化。然而,正如这个问题所说明的那样,这些事情是值得了解的:
Why is it faster to process a sorted array than an unsorted array?
由于处理器工作方式的细节,代码上看似无关的细节(数组的预排序)从表面上看应该总是花费相同的时间运行速度提高五倍。
【讨论】: