C++ 如何将数组从行顺序重写为列顺序?

C++ 如何将数组从行顺序重写为列顺序?,c++,c,C++,C,我有一个双for循环,其中我有行顺序和列顺序数组索引,这对性能应该是不利的 for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { /* Column-major order */ d = array_a[col*height +row]; if (d < 0) { d = 0; } /* Row-major

我有一个双for循环,其中我有行顺序和列顺序数组索引,这对性能应该是不利的

  for (int row = 0; row < height; row++) {
    for (int col = 0; col < width; col++) {

      /* Column-major order */
      d = array_a[col*height +row];

      if (d < 0) { d = 0; }

      /* Row-major order */
      /* Map from x=0,y=0 at buttom left corner to
         0,0 at top left corner */
      array_b[width*(height-1 -row) + col] = d;

    }
  }
for(int row=0;row
是否有一种方法/途径可以将一个重写到另一个

当我试图重写最后一个到列的顺序时,数据会发生倾斜。不能重写吗


Sandra这不是导致数据倾斜的原因吗?所有负值都被调零:

if (d < 0) { d = 0; }
如果(d<0){d=0;}

所以您希望从以下内容切换:

0  1  2  3
4  5  6  7
8  9  10 11

?

试一试

for(int i=0;i
这永远不会很快,因为您可能会有大量缓存未命中,您要么必须跳转到一个具有大音高的矩阵,要么跳转到另一个矩阵,这是无法避免的。这里的问题是,计算机喜欢连续的内存访问靠得很近,在您的算法中,由于
col*height
项,数组a的索引一次跳过高度元素。要解决这个问题,您可以切换for循环,但是在
array\u b
中的
width*(height-1-row)
术语也会遇到同样的问题


你可以重写其中一个数组来匹配另一个数组的顺序,但是在重写的代码中,你会遇到完全相同的问题,所以这取决于你是否需要对同一个数据做多次类似的事情,如果你这样做,那么先重写其中一个矩阵是有意义的,如Poita_u所述,否则,最好保持算法不变。

如果交换行或排序很常见,则编写自己的数组类

数据实际上不必移动,只是访问数据的接口需要知道如何访问数据

#include <vector>
class Matrix
{
  public:
    Matrix(int width,int height)
        :data(width,std::vector<int>(height))
        ,rowOrder(true)
    {
    }
    int& operator()(int x,int y)
    {
        return at(x,y);
    }
    int const& operator()(int x,int y) const
    {
        return const_cast<Matrix&>(*this).at(x,y);
    }

    void switchRowOrder()
    {
        rowOrder = !rowOrder;
    }

  private:
    int& at(int x,int y)
    {
        int& result = (rowOrder)
                            ?data[x][y]  // row Order Access
                            :data[y][x]; // col Order Access

        // Note there is no code to swap around the content of the data internally.
        return result;
    }

    std::vector<std::vector<int> >  data;
    bool rowOrder;
};
#包括
类矩阵
{
公众:
矩阵(整数宽度、整数高度)
:数据(宽度、标准::矢量(高度))
,行顺序(true)
{
}
int运算符()(int x,int y)
{
返回(x,y);
}
int const&运算符()(int x,int y)const
{
在(x,y)处返回常量投射(*this.);
}
void switchRowOrder()
{
rowOrder=!rowOrder;
}
私人:
int&at(int x,int y)
{
int&result=(行顺序)
?数据[x][y]//行顺序访问
:data[y][x];//列顺序访问
//注意,没有代码可以在内部交换数据内容。
返回结果;
}
std::矢量数据;
布尔-罗沃德;
};

<>代码> < p>因为问题是标记C++,我将提供一个答案,说明如何访问/操纵列主矩阵可以使用(它可能对其他面临类似问题的人有用)。我认为Boost是C++标准库的扩展。如果您不喜欢/使用Boost,请忽略此答案。:-)

如您所见,您可以将源数据保留为列主格式,并使用带有自定义存储规范的
boost::multi_array_ref
使用
matrix[row][col]
符号直接操作数据(就好像它是行主数据一样)


如果矩阵经常以行主方式遍历,那么最好将其转换为实际的行主矩阵,如我的示例的最后一部分所示

不,我希望新代码的输出与现在完全相同。当前代码有效。我只是假设它很慢,因为我混合了行顺序索引和列顺序索引。所以我希望将行顺序重写为列顺序。实际上,C通常以行主顺序存储信息(行是连续存储的)。最有效的方法(vis-a-vis,localityofreference)是将列主数组重新排序为row-major。然后是否可以将第一个数组重写为row-ordered?还是我被混音困住了?没有比这更好的表现了。你必须接触矩阵中几乎所有的值,因此没有比O(WxH)更复杂的了。@Poita_uuuo复杂度不是这里唯一的问题,速度慢的很大一部分可能还在于一个或另一个数组将导致大量缓存未命中。一个简单的解决方案是编写一个理解这个概念的数组类。只需调用开关行顺序。底层数据不需要移动,接口只需交换访问参数。@Martin:boost::multi_数组已经支持这一点。为什么每个人都忽略了那个美妙的图书馆???不是这里发明的综合症?:-)@显然,在生产代码中使用正确的工具。但这不是关于图书馆的问题。这是一个关于技术和代码敏捷性的问题。OP显然是在试图理解该语言的一些更基本的概念,而不是试图理解所有可用库。@Martin:我明白你的意思。:-)我想OP希望在从列主调转换到行主调后Y轴翻转。我知道。我不能做所有的工作。鉴于上述基本概念,可以在不实际移动数据的情况下维护许多不同的配置。您甚至可以插入基于策略的访问功能。当您开始添加策略时,它将开始看起来非常像boost::multi_array;这正是我一直在寻找的。我来过几次这个S-O页面,没有看到这个答案,因为它在页面底部。谢谢如果忽略bigO复杂性中的常量
for (int i = 0; i < width; ++i)
  for (int j = 0; j < height; ++j)
    array_b[ i * height + j ] = array_a[ j * width + i ];
#include <vector>
class Matrix
{
  public:
    Matrix(int width,int height)
        :data(width,std::vector<int>(height))
        ,rowOrder(true)
    {
    }
    int& operator()(int x,int y)
    {
        return at(x,y);
    }
    int const& operator()(int x,int y) const
    {
        return const_cast<Matrix&>(*this).at(x,y);
    }

    void switchRowOrder()
    {
        rowOrder = !rowOrder;
    }

  private:
    int& at(int x,int y)
    {
        int& result = (rowOrder)
                            ?data[x][y]  // row Order Access
                            :data[y][x]; // col Order Access

        // Note there is no code to swap around the content of the data internally.
        return result;
    }

    std::vector<std::vector<int> >  data;
    bool rowOrder;
};
#include <algorithm>
#include <iostream>
#include <boost/multi_array.hpp>

// Prints the contents of a matrix to standard output
template <class M> void printMatrix(const M& matrix)
{
    int height = matrix.shape()[0];
    int width = matrix.shape()[1];
    for (int row=0; row<height; ++row)
    {
        for (int col=0; col<width; ++col)
        {
            std::cout << matrix[row][col] << " ";
        }
        std::cout << "\n";
    }
}

int main()
{
    // Source matrix data is in column-major format in memory,
    // with data starting at bottom-left corner.
    double data[] =
    {
        3, 7, 11,
        2, 6, 10,
        1, 5, 9,
        0, 4, 8
    };
    int width=4, height=3;

    // Store rows, then columns (column-major)
    int ordering[] = {0,1};

    // Store rows in descending order (flips Y axis)
    bool ascending[] = {true,false};

    // Create a multi_array that references the existing data,
    // with custom storage specifications.
    typedef boost::multi_array_ref<double, 2> Matrix;
    typedef boost::general_storage_order<2> Storage;
    Matrix matrix(
        data,
        boost::extents[height][width],
        Storage(ordering, ascending)
    );

    // Access source data as if it's row major
    printMatrix(matrix);
    std::cout << "\n";

    // Transpose source data to an actual row-major matrix
    // boost::multi_array is row-major by default
    boost::multi_array<double, 2> matrix2(boost::extents[height][width]);
    std::copy(matrix.begin(), matrix.end(), matrix2.begin());
    printMatrix(matrix2);
}
0 1 2 3
4 5 6 7
8 9 10 11

0 1 2 3
4 5 6 7
8 9 10 11