如何解决如何交换二维数组的行
我第一次遇到这种情况,我想知道是否有任何“最佳方法”或至少是一个好的做法。
如何交换二维数组的行?
例如:
FROM --> TO
1 1 1 2 2 2
2 2 2 1 1 1
3 3 3 3 3 3
-
使用
memcpy
? -
感谢老式的
for
将两行的元素一一交换? -
有一个动态分配的指向
int
的指针数组(而不是二维数组)并交换指针? -
其他方式?
解决方法
IMO memcpy
是最好的方式
通用函数:
void *swapRows(void *array,size_t rows,size_t columns,size_t row1,size_t row2,size_t elemsize)
{
size_t rowsize = columns * elemsize;
unsigned char *carray = array;
if(row1 != row2 && row1 < rows && row2 < rows)
{
void *tempRow = malloc(rowsize);
if(tempRow && array)
{
size_t row1offset = row1 * elemsize * columns;
size_t row2offset = row2 * elemsize * columns;
memcpy(tempRow,carray + row1offset,rowsize);
memcpy(carray + row1offset,carray + row2offset,rowsize);
memcpy(carray + row2offset,tempRow,rowsize);
}
free(temprow)
}
return array;
}
和一些原始基准
void __attribute__((noinline)) *swapRows(volatile void *array,size_t elemsize)
{
size_t rowsize = columns * elemsize;
unsigned char *carray = (void *)array;
if(row1 != row2 && row1 < rows && row2 < rows)
{
void *tempRow = malloc(rowsize);
if(tempRow && array)
{
size_t row1offset = row1 * elemsize * columns;
size_t row2offset = row2 * elemsize * columns;
memcpy(tempRow,rowsize);
}
free(tempRow);
}
return array;
}
#define SWAPROWS(type,array,rows,columns,r1,r2) \
do {\
for(size_t c = 0; c < columns; c++)\
{ \
type tmp = array[r1][c];\
array[r1][c] = array[r2][c];\
array[r2][c] = tmp; \
}\
}while(0)
int main(void)
{
clock_t start,end;
volatile int array[5][2000];
double time_spent;
for (size_t row = 0; row < 5; row++)
for(size_t c = 0; c < 2000; c++)
array[row][c] = row;
start = clock();
for(int i = 0; i < 1000; i++)
SWAPROWS(int,5,2000,2,3);
end = clock();
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("%f\n",time_spent);
start = clock();
for(int i = 0; i < 1000; i++)
swapRows(array,3,sizeof(int));
end = clock();
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("%f\n",time_spent);
}
结果
Program returned: 0
Program stdout
0.001735
0.000388
,
使用 memcpy?
如果数据按行主顺序排列,这意味着每一行都是一个连续的内存块,那么这可能是一个很好的工具。一个完全通用的解决方案需要对行大小设置一些上限,以避免分配巨大的临时行并破坏 L1 缓存(16 kB 可能是合理的最大副本块大小)。
多亏了旧的for
,将两行的元素一一交换?
这对于小行或由于其他原因必须以列优先顺序存储的数据非常有用。
有一个动态分配的指向 int 的指针数组(而不是二维数组)并交换指针?
当然值得进行基准测试,但除非行交换是您的主要用例之一,否则这可能会降低其他操作的性能,从而适得其反。
这是另一种选择:
以行优先顺序连续存储数据,而不是移动行,而是保留一个单独的行索引数组,其中真正存储了每一行。在您的示例中,这将是 [1,2]。这将使行移动像指针解决方案一样高效,同时不会减慢其他操作,例如分配、释放、求和等。
,我们实际上是想就地交换还是生成一个元素转置的新数组?
如果您尝试就地交换,那么数组是正方形吗?现在它变得非常有趣!我忽略了这一点,但是有一些有趣的算法可以有效地获取实际使用第二个聚合维度查看的一维数组,并将其就地转置到同一个一维数组存储中。
但如果你只是做一个方阵或复制,那么:
如果这些值是简单的整数,那么 memcpy 就有点矫枉过正了——你不妨简单地通过一个临时值来分配这些值。没有 memcpy 可以有效流式传输的长序列。
如果元素大于整数,那么将数组设为指针数组会使转置代码在您复制指针时变得容易,但您可能会在代码中的其他任何地方支付额外费用来管理所指向的数据,以及每次访问数据时的额外取消引用。转置可能不是代码中最慢的部分!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。