【发布时间】:2013-08-05 12:37:19
【问题描述】:
如何有效地确定数组的长度?
在寻找一种在 Intersystems Cache 中获取数组或全局大小的方法时,我开始思考如何实际确定数组大小。从那以后,我找到了解决我最初问题的方法,但是有效地确定数组大小的难题仍然困扰着我,所以这是我迄今为止想出的:
- 从索引 1 开始。
- 测试当前索引处的值。
- 如果找到值,则将索引加倍。
- 如果未找到值,则减去使用的倒数第二个索引。
- 继续第 4 步,将每次迭代中减去的值减半,直到索引小到足以再次找到值为止。
- 将索引加一,直到找不到值。
- 倒数第二个索引将是大小。
以一个大小为 52 的数组为例:
1 - OK
2 - OK
4 - OK
8 - OK
16 - OK
32 - OK
64 - OVER
48 - OK (64-16)
49 - OK
50 - OK
51 - OK
52 - OK
53 - OVER
这似乎很公平,因为我在 13 次迭代中得到了数组的长度,但是,如果我的数组大小增加到 63,它会将迭代次数增加 10 - 与数组增加的大小相同。
对于一个相当小的数组,我可以认为我对最后几个循环的敲击几乎是可以接受的,即使数组长度只是小于 2 的幂,但是如果我使用一个非常大的数组会发生什么,比如说 2097152 (2^21 - 1) 个元素?这意味着我将在 21 次迭代中达到第一个“结束”,将索引降低到 1572864 并开始一个非常长的循环(1572864 次迭代)。在这个例子中,我并没有完全“赢得”那么多。
现在我可以通过再次增加指数的 2 次方来优化这一点,但这一切都让我想知道:有没有更好的方法呢?我什至在正确的轨道上吗?只使用静态增加尺寸会更好吗?
【问题讨论】:
-
什么语言?某些语言使用显式存储数组大小的结构,因此始终只是一个值读取操作
-
是的,这将是理想的解决方案,因为没有迭代。我只是想知道一个好的算法,所以为了争论,我们假设我们不能简单地存储数组大小。 :)
-
如果你没有数组的大小,你怎么知道最后一个元素在哪里?您的示例提出了问题 - 您无法假设数组的大小为 52,然后推导出一个算法来查找该大小。您必须首先假设您(和您的算法)不知道数组的大小。
-
你说的叫二分查找。您不需要在第一次溢出后开始线性化。您可以继续获取最后一个 OK 和 OVER 地址之间的中间地址。请注意,通常这是不可能的,因为 OVER 情况通常会导致分段错误。
-
我真的不明白如何在不破坏/弯曲一些内存访问规则的情况下实现这一点。那么开发这样的算法是否有必要/值得付出努力?