【问题标题】:Explain 2D array iteration with 1 loop用 1 个循环解释 2D 数组迭代
【发布时间】:2013-06-03 07:14:41
【问题描述】:

有人可以解释为什么这个算法适用于将二维数组迭代为一维数组吗?换句话说..只有一个循环?

const int Width = 6;
const int Height = 4;

int Array[Width][Height];

for (int I = 0; I < Width * Height; ++I)
{
    Array[I % Width][I / Width] = I; //This line :S
}

for (int I = 0; I < Height; ++I)
{
    for (int J = 0; J < Width; ++J)
    {
        std::cout<<Array[J][I]<<"  ";
    }
    std::cout<<"\n";
}

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    您没有将其用作一维数组。您仍在将其索引为 2D 数组。但是,您正在使用数学(模数和整数除法)根据数组的维度从一维索引中恢复二维索引。这是很正常的,但是像你这样做的那样在循环中执行此操作是不寻常的,因为它可能在计算上很昂贵。

    【讨论】:

    • 为什么会很贵?两个for循环不一样吗?哇..那个循环!我从来没有见过这样的循环。但是那个循环改变了数字的顺序。一个是列专业,另一个是行专业
    • 是的,忘记我的循环...这是专栏主要的。它昂贵的原因是您每次都要做大量的模和除法并重新计算这两个值,而使用嵌套循环您只是在迭代。
    • 但是@Mattingly 的帖子说它会自动为我计算数学,所以那不一样吗?
    • 是的,但是您正在这样做以及模数和除法。这是否真的发生将取决于编译器的优化智能,但我不想相信这一点。如果您热衷于实际上作为列优先数组在内存中布置的列优先数组,请查看我的旧答案 (stackoverflow.com/questions/15778377/…)。它是行优先的,但很容易修改为列优先。如果你打算主要做以列为主的操作,不妨考虑一下。
    【解决方案2】:

    了解其工作原理的最简单方法是自己插入数字。从0开始,我们会得到:

    Array[0 % 6][0 / 6] = Array[0][0]
    Array[1 % 6][1 / 6] = Array[1][0]
    ...
    Array[5 % 6][5 / 6] = Array[5][0]
    Array[6 % 6][6 / 6] = Array[0][1]
    ...
    Array[11 % 6][11 / 6] = Array[5][1]
    

    等等。因为它使用整数除法,所以每次我们遍历Width 值时,i / Width 都会多一个。利用i % Width,这将在特定i / Width 处循环每个值(在本例中为0 到5)。因为整数除法会截断,所以在i 成为Width 的下一个倍数之前,这将是相同的。

    【讨论】:

    • 我明白你的解释 :) 这与两个 for 循环相比有缺点吗?
    • 是的。首先,它对每个循环值使用模和除法,这可能是昂贵的操作 - 对于大型循环,这可能会增加相当多的开销。其次,与只执行两个循环相比,它稍微有些混淆。
    • 这真是太神奇了。感谢您的精彩解释。
    【解决方案3】:

    为二维数组分配的内存仍然是线性布局的。因此,如果您要检查变量 Array 中的内存,它将由 Widthints 后跟 Width ints 的数量... Height 次。

    如果 Width = 5,并且 Height = 2... Array 的内存看起来像这样(其中每个 [] set 是一个整数):

    [w0/h0][w1/h0][w2/h0][w3/h0][w4/h0][w0/h1][w1/h1][w2/h1][w3/h1][w4 /h1]

    当您使用 Array[j][i] 访问数组时,它只是自动为您计算,以正确偏移到线性内存块中。

    【讨论】:

    • 对...我的意思是说在单循环方法中去掉模和除法(并用'[I]'替换它)将导致相同的输出并提高性能.
    【解决方案4】:

    for (int x = 1, y = 1; y &lt;= 5; (x &lt; 5) ? (x++) : (x = 1, y++))

    对不起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      • 2020-10-28
      • 1970-01-01
      相关资源
      最近更新 更多