Как переписать массив из порядка строк в порядок столбцов?

У меня есть этот двойной цикл 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; } } 

Есть ли подход / метод переписывания от одного к другому?

Когда я пытаюсь переписать последний порядок столбцов, данные становятся искаженными. Разве это нельзя переписать?

Sandra

Это никогда не будет очень быстрым, так как у вас, вероятно, будет несколько промахов в кеше, вам придется либо перейти на одну матрицу с большим шагом, либо другим, и этого избежать не удастся. Проблема здесь в том, что компьютеру нравится, чтобы последовательные обращения к памяти были близки друг к другу, что в вашем алгоритме не так, индексирование array_a пропускает по высоте элементы за раз из-за возраста высоты столбца . Чтобы исправить это, вы можете переключаться вокруг циклов, но тогда у вас будет такая же проблема с термином width (height-1 -row) в array_b.

Вы можете переписать один из массивов в соответствии с порядком другого, но тогда у вас будет такая же проблема в коде, который переписывает, так что это зависит от того, нужно ли вам делать подобные вещи более одного раза на то же самое, если вы это сделаете, тогда имеет смысл сначала переписать одну из таких матриц, как описанная Poita_, иначе вам лучше оставить алгоритм таким, какой есть.

Поскольку вопрос отмечен как C ++, я расскажу о том, как можно получить доступ к matrixм-столбцами или манипулировать ими с помощью Boost.Multiarray (это может быть полезно для других, сталкивающихся с аналогичной проблемой). Я считаю, что Boost является расширением стандартной библиотеки C ++. Не стесняйтесь игнорировать этот ответ, если вам не нравится / использовать Boost. 🙂

 #include  #include  #include  // Prints the contents of a matrix to standard output template  void printMatrix(const M& matrix) { int height = matrix.shape()[0]; int width = matrix.shape()[1]; for (int row=0; row 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 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 

Как вы можете видеть, вы можете оставить исходные данные в своем основном формате столбца и использовать boost::multi_array_ref с настраиваемыми спецификациями хранилища для непосредственного управления данными (как если бы они были boost::multi_array_ref ) с использованием matrix[row][col] обозначение.

Если бы matrix проходила часто по строкам, то лучше было бы перенести ее в реальную матрицу основных строк, как показано в последней части моего примера.

Поэтому вы хотите переключиться с чего-то вроде:

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

в

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

?

Пытаться

 for (int i = 0; i < width; ++i) for (int j = 0; j < height; ++j) array_b[ i * height + j ] = array_a[ j * width + i ]; 

Если обычная замена строки является обычной, напишите свой собственный class массива.

Данные фактически не должны перемещать только интерфейс, который обращается к данным, чтобы знать, как получить доступ к данным.

 #include  class Matrix { public: Matrix(int width,int height) :data(width,std::vector(height)) ,rowOrder(true) { } int& operator()(int x,int y) { return at(x,y); } int const& operator()(int x,int y) const { return const_cast(*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 > data; bool rowOrder; }; 

Разве это не причина ваших данных? Все отрицательные значения обнуляются:

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