删除2D动态数组中的任意数量的列,并在删除列后调整矩阵大小

时间:2018-04-05 16:38:33

标签: c

我正在尝试从3D动态数组的每个切片中删除前20列。我猜想尝试为2D动态数组编写函数可以解决我将迭代3D数组的每个级别的问题。我在stackoverflow中得到了一个例子,我正在努力工作。

但问题是函数无法删除整列。相反,它只删除一个元素。谁能让我知道如何从2D动态数组中删除整列?

void removeColumn(int** matrix, int col){ 
  MATRIX_WIDTH--;   
   for(int i=0;i<MATRIX_HEIGHT; i++)   {
    while(col<MATRIX_WIDTH)
    {
      //move data to the left
      matrix[i][col]=matrix[i][col+1];
      col++;
    }   matrix[i] = realloc(matrix[i], sizeof(double)*MATRIX_WIDHT);   }

我的预期输出就像 样本输入:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

示例输出:

1 3 4
5 7 8
9 11 12
13 15 16

更新:这是使用@frslm建议后完全删除列的代码   但矩阵没有调整大小。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>


int** fill(size_t rows, size_t cols, int input[][cols])
{
    int i,j,count=1;
    int** result;
    result = malloc((rows)*sizeof(int*));
    for(i=0;i<rows;i++)
    {
        result[i]=malloc(cols*sizeof(int));
        for(j=0;j<cols;j++)
        {
            result[i][j]=count++;
        }
    }

    return result;
}


void printArray2D(size_t rows, size_t cols,int** input)
{
    int i,j;
    for(i=0;i<rows;i++)
    {
        for(j=0;j<cols;j++)
        {
            printf(" %4d",input[i][j]);
        }
        printf("\n");
    }
}

void removeColumn(int** matrix, int col2del , int rows, int cols){ 
    int MATRIX_WIDTH = cols;
    int MATRIX_HEIGHT = rows;

    MATRIX_WIDTH--;   
    for(int i=0;i<MATRIX_HEIGHT; i++) {
        int curr_col = col2del; 
        while(curr_col<MATRIX_WIDTH)
        {
            //move data to the left
            matrix[i][curr_col]=matrix[i][curr_col+1];
            curr_col++;
        }
        //matrix[i] = realloc(matrix[i], sizeof(int)*MATRIX_WIDTH); // <- int, not double
        matrix[i] = realloc(matrix[i], sizeof (matrix[i][0])*MATRIX_WIDTH); 
    }
}

int main()
{
    int arRow,arCol;
    arRow =8;
    arCol = 9;
    int ar[arRow][arCol];
    int **filled;
    filled = fill(arRow, arCol, ar);
    printArray2D(arRow,arCol,filled);
    removeColumn(filled, 3,arRow,arCol);
    printf("After 3rd Column Delete.......\n");
    printArray2D(arRow,arCol,filled);
    return(0);
}

输出:最后一列重复

    1    2    3    4    5    6    7    8    9
   10   11   12   13   14   15   16   17   18
   19   20   21   22   23   24   25   26   27
   28   29   30   31   32   33   34   35   36
   37   38   39   40   41   42   43   44   45
   46   47   48   49   50   51   52   53   54
   55   56   57   58   59   60   61   62   63
   64   65   66   67   68   69   70   71   72
After 3rd Column Delete.......
    1    2    3    5    6    7    8    9    9
   10   11   12   14   15   16   17   18   18
   19   20   21   23   24   25   26   27   27
   28   29   30   32   33   34   35   36   36
   37   38   39   41   42   43   44   45   45
   46   47   48   50   51   52   53   54   54
   55   56   57   59   60   61   62   63   63
   64   65   66   68   69   70   71   72   72

2 个答案:

答案 0 :(得分:2)

您递增col直到它到达第一行的末尾,但您从未为后续行重置它,这就是为什么您最终只删除第一行的列。

确保在每次迭代开始时重置col

void removeColumn(int** matrix, int col){ 
    MATRIX_WIDTH--;   
    for(int i=0;i<MATRIX_HEIGHT; i++) {
        int curr_col = col; // <- use a temporary `col` variable for each row
        while(curr_col<MATRIX_WIDTH)
        {
            //move data to the left
            matrix[i][curr_col]=matrix[i][curr_col+1];
            curr_col++;
        }
        matrix[i] = realloc(matrix[i], sizeof(int)*MATRIX_WIDTH); // <- int, not double
    }
}

修改(响应OP编辑):

确保removeColumn()在调整矩阵大小后更新列数(cols);一种方法是使用指针:int *cols作为参数而不是int cols(在调用此函数时不要忘记传入地址&arCol) 。另外,我建议摆脱不必要的MATRIX_HEIGHT变量:

void removeColumn(int** matrix, int col2del, int rows, int *cols){
    int MATRIX_WIDTH = --(*cols);

    for(int i=0;i<rows; i++) {
        int curr_col = col2del; 
        while(curr_col<MATRIX_WIDTH)
        {
            //move data to the left
            matrix[i][curr_col]=matrix[i][curr_col+1];
            curr_col++;
        }
        matrix[i] = realloc(matrix[i], sizeof(matrix[i][0])*MATRIX_WIDTH); 
    }
}

答案 1 :(得分:1)

如果您传递宽度和高度,并更新宽度,则会更容易:

void removeColumn(int** matrix, int col, int* width, int height)
{
    int j, i;
    for (j = 0; j < height; ++j) {
        if (col == *width-1) {
            continue;
        }
        for (i = col; i < *width; ++i) {
            matrix[j][i] = matrix[j][i+1];
        }
        // this is not necessary, but I'm adding as requested
        matrix[j] = realloc(
            matrix[j],
            sizeof(int) * (*width - 1)
        );
    }
    --(*width);
}

您还可以避免动态内存分配,避免内存碎片整理:

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int max_width, max_height;
    int width, height;
    int* values;
} matrix;

void removeColumn(matrix* matrix, int col)
{
    int y, i;
    for (y = 0; y < matrix->height; ++y) {
        if (col == matrix->width-1) {
            continue;
        }
        i = col + matrix->height * y;
        while (i < matrix->width) {
            matrix->values[i] = matrix->values[++i];
        }
    }
    --matrix->width;
}

void printMatrix(matrix* matrix)
{
    int y, x;
    for (y = 0; y < matrix->height; ++y) {
        for (x = 0; x < matrix->width; ++x) {
            printf("%d ", matrix->values[x + matrix->width * y]);
        }
        printf("\n");
    }
}

int main ()
{
    int y, x = 0;
    matrix matrix;
    matrix.max_width = 4;
    matrix.max_height = 4;
    matrix.width = 4;
    matrix.height = 4;
    int values[4][4];
    matrix.values = &values;
    for (y = 0; y < matrix.height; ++y) {
        for (x = 0; x < matrix.width; ++x) {
            int i = x + matrix.width * y;
            matrix.values[i] = i % 10;
        }
    }

    printMatrix(&matrix);
    removeColumn(&matrix, 1);
    printf("===\n");
    printMatrix(&matrix);
}

使用:https://www.tutorialspoint.com/compile_c_online.php

进行测试

<强> ADDED

  

但是当数组大小太大时,我们还有其他选择吗?   但使用动态数组

如果要制作可调整大小的数组,则在分配数组时可以使用单个malloc,并在realloc大于width时使用max_widthheight将大于max_height

尽管如此,我认为我们应该尽量避免使用mallocrealloc进行大量动态分配,因为它们会变慢(尽管大部分时间你都没有注意到) ,它们可以对内存进行严格的碎片整理,并且它的方式会产生大量不必要的缓存未命中。

如果你不知道你需要多次调整阵列的大小,你也应该增加它们的数量,例如,指数增长。这通常是(正确地)实现了哈希和动态数组。

例如,您可能会发现几个没有动态内存的JSON,XML和HTML C库以避免其陷阱,并且在许多专业视频游戏中,可能会使用巨大的malloc来避免大量的这些并且简单数组被大量使用。

当然,您可以使用动态内存,但要更好地理解其陷阱以获得更好的决策。