基于C中的1D数组索引提取3D数组

时间:2019-01-07 11:07:40

标签: c

我有一个1D数组arr = {6,2,1,7}和3D数组mat_1,我需要按降序对1D数组进行排序,然后提取与1D数组index = {3,0,1,2}的最大索引相对应的3D数组按照下面的代码。

以下代码可以正常工作,但是我正在使用额外的内存mat_2mat_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;

}

2 个答案:

答案 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");
    }