我有一个1D数组arr = {6,2,1,7}
和3D数组mat_1
,我需要按降序对1D数组进行排序,然后提取与1D数组index = {3,0,1,2}
的最大索引相对应的3D数组按照下面的代码。
以下代码可以正常工作,但是我正在使用额外的内存mat_2
从mat_1
复制元素,然后将第一个mat_2[0][:][:]
和第四个mat_2[3][:][:]
数据提取到mat_1
,因为数组索引arr[0] and arr[3]
大于arr[1] and arr[2]
。
我将使用约1024 x 1024 x 20的大型矩阵,并且需要避免使用mat_2
之类的额外内存。请提出一种无需使用mat_1
mat_2
的替代方法
#include <stdio.h>
#include <string.h>
#define LENGTH 4
#define ROWS 2
#define COLS 4
void sorted_order (int *arr, int n, int *idx);
void swap (int *x, int *y);
int main()
{
int arr[LENGTH] = {6,2,1,7},idx[LENGTH];
int mat_1[LENGTH][ROWS][COLS] = {{{6,6,6,6},{6,6,6,6}},{{2,2,2,2},{2,2,2,2}},{{1,1,1,1},{1,1,1,1}},{{7,7,7,7},{7,7,7,7}}};
int mat_2[LENGTH][ROWS][COLS] = {{{0}}};
int len=LENGTH,half = LENGTH/2,index, row, col;
//sort array: Array index after sorting = {3,0,1,2}
sorted_order (arr, len, idx);
memcpy(mat_2, mat_1, len * sizeof *mat_1);
for(index = 0; index < half; index++)
{
memcpy(mat_1+index,mat_2[idx[index]], len * sizeof *mat_2);
}
for(index = 0; index < half; index++){
for(row = 0; row < ROWS; row++){
for(col = 0; col < COLS; col++){
printf("%d\t",mat_1[index][row][col]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
答案 0 :(得分:2)
先提出建议先行缓慢
一种方法是按照交换1D数组的相同顺序交换值来进行处理。交换arr[i]
和arr[j]
时,您也交换mat_1[i]
和mat_1[j]
您不需要复制3D数组,但是当然会消耗更多的CPU,请在O(n * log(n))中选择一种类型
第二个建议先验地更快,使用1D数组索引= {3,0,1,2},添加一个1D数组来存储3D数组中的索引,因此在开始时matIdx = {0,1,2 ,3},然后将它们进行比较:
索引0:您想要idx [0] = 3但您有matIdx [0] = 0 =>您在matIdx中搜索,其中3是3,它在索引3处,因此交换了mat [0]和mat [3 ],则将matIdx更新为{3,1,2,0}
索引1:您希望idx [1] = 0,但是您有matIdx [1] = 1 =>您在matIdx中搜索,其中0为索引3,所以它交换了mat [1]和mat [3 ],则将matIdx更新为{3,0,2,1}
索引2:您想要idx [2] = 1但您有matIdx [2] = 2 =>您在matIdx中搜索其中1且它在索引3处,因此交换了mat [2]和mat [3 ],则将matIdx更新为{3,0,1,2}
当然对于索引2可以简化,因为它们是最后2个位置,所以有顺序,或者您只需要交换,我继续没有进行优化就可以解释
这样一来,您在Mat中进行最坏的n次交换时,复杂度只是在matIdx中搜索索引,但这与在mat中交换值的时间相比可能没什么了
可以实现(我没有您的功能sorted_order
,所以我不使用它):
#include <stdio.h>
#include <string.h>
#define LENGTH 4
#define ROWS 2
#define COLS 4
/*void sorted_order (int *arr, int n, int *idx);*/
/* exchange mat[i] and mat[j] and update matIdx, i > j */
void swap(int mat[][ROWS][COLS], int matIdx[], int i, int j)
{
int temp[ROWS][COLS];
memcpy(temp, mat[j], sizeof(mat[0]));
memcpy(mat[j], mat[i], sizeof(mat[0]));
memcpy(mat[i], temp, sizeof(mat[0]));
matIdx[i] = j;
}
/* return the index in matIdx where what is */
int findIdx(int matIdx[], int from , int what)
{
while (matIdx[from] != what)
from += 1;
return from;
}
int main()
{
int mat[LENGTH][ROWS][COLS] = {{{6,6,6,6},{6,6,6,6}},{{2,2,2,2},{2,2,2,2}},{{1,1,1,1},{1,1,1,1}},{{7,7,7,7},{7,7,7,7}}};
int idx[LENGTH] = {3,0,1,2}; /* idx is normaly set by your function sorted_order */
int matIdx[LENGTH];
int index;
/* initialize matIdx */
for (index = 0; index != LENGTH; ++index)
matIdx[index] = index;
/* sort except the last element */
for(index = 0; index != LENGTH - 2; index++){
if (idx[index] != matIdx[index]) {
// need to exchange
swap(mat, matIdx, findIdx(matIdx, index + 1, idx[index]), index);
}
}
/* last 2 elements */
if (idx[LENGTH - 2] != matIdx[LENGTH - 2]) {
// need to exchange
swap(mat, matIdx, LENGTH - 1, LENGTH - 2);
}
/* print result */
for(index = 0; index < LENGTH; index++){
int row;
for(row = 0; row < ROWS; row++){
int col;
for(col = 0; col < COLS; col++){
printf("%d\t",mat[index][row][col]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
执行写道:
7 7 7 7
7 7 7 7
6 6 6 6
6 6 6 6
2 2 2 2
2 2 2 2
1 1 1 1
1 1 1 1
答案 1 :(得分:0)
如果我了解您的逻辑,
看来您可以完全跳过复制到mat_2
的过程,而只需使用mat_1
来访问idx
,就像这样:
for(index = 0; index < half; index++){
for(row = 0; row < ROWS; row++){
for(col = 0; col < COLS; col++){
printf("%d\t",mat_1[idx[index]][row][col]);
}
printf("\n");
}
printf("\n");
}