【问题标题】:Algorithm for determining the size of an array确定数组大小的算法
【发布时间】:2013-08-05 12:37:19
【问题描述】:

如何有效地确定数组的长度?

在寻找一种在 Intersystems Cache 中获取数组或全局大小的方法时,我开始思考如何实际确定数组大小。从那以后,我找到了解决我最初问题的方法,但是有效地确定数组大小的难题仍然困扰着我,所以这是我迄今为止想出的:

  1. 从索引 1 开始。
  2. 测试当前索引处的值。
  3. 如果找到值,则将索引加倍。
  4. 如果未找到值,则减去使用的倒数第二个索引。
  5. 继续第 4 步,将每次迭代中减去的值减半,直到索引小到足以再次找到值为止。
  6. 将索引加一,直到找不到值。
  7. 倒数第二个索引将是大小。

以一个大小为 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 情况通常会导致分段错误。
  • 我真的不明白如何在不破坏/弯曲一些内存访问规则的情况下实现这一点。那么开发这样的算法是否有必要/值得付出努力?

标签: arrays algorithm


【解决方案1】:

您似乎正在尝试重塑binary search。在您的示例中,一旦 64 失败,您将对 32 和 64 之间的区间进行二分搜索。因此,在 48 之后,您应该尝试的下一个值是 56。在 56 失败后,您将返回到 52。

一般来说,您应该能够在最多 2n 次迭代中获得最多包含 2^n 个元素的数组的大小。

【讨论】:

  • 很公平。我最初试图想出一种方法来暗示二分搜索的威力。
  • 二进制搜索仅在您有地板和天花板可供搜索时才有效。当您找到最小的 n 时,您就有了,其中 2^n 太小而 2^(n+1) 太大。
【解决方案2】:

不要单步执行最后的 2^(n-1) 到 (2^n)-1,而是对该空间进行二分搜索。所以基本上你的最后一个建议......无论哪种方式,你绝对不想使用静态增加尺寸。

随机观察:Cache ObjectScript 看起来很糟糕。

【讨论】:

  • 到目前为止还不错。它的语法非常难看,但我想我会习惯的。不过,我不经常使用它。
【解决方案3】:

您应该稍微修改一下您的算法。

1 Start at index 0.
2 Add 1 to index
4 Stash it
5 Test for a value at the current index.
6 If 
   a value is found, double the index, go to 4
   else - if 
        current index = stashed index + 1, stashed index is the size of array, quit
        else set the current index to a stashed value, go to 2

这不仅在第一次“结束”之前有效,而且直到结束。

【讨论】:

  • 是的,除非我弄错了,否则这或多或少是我在上一段的第一句话中想到的。
  • 是的,确实如此。而且它基本上是相同的二分搜索,但是翻过来了。
【解决方案4】:

在缓存中,如果您正在寻找具有整数索引的单维数组的大小,您需要做的就是

W $Order(Array(""),-1)

如果您的数组不是整数或多维数组,问题就来了...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多