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



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

但问题是函数无法删除整列。相反,它只删除一个元素。谁能告诉我如何从 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

您递增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); 
}
}

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

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

添加

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

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

尽管如此,我认为我们应该尽量避免使用mallocrealloc进行大量动态分配,因为它们很慢(尽管大多数时候您不会注意到),它们会严重对内存进行碎片整理,并且您这样做的方式会产生许多不必要的缓存未命中。

您还应该将它们增长到超过所需的数量,例如,如果您不知道需要多次调整数组大小,则呈指数级增长。这就是哈希和动态数组通常(正确)实现的方式。

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

  • 为什么 realloc 会消耗大量内存?

  • https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/

  • http://gameprogrammingpatterns.com/data-locality.html

  • https://codefreakr.com/how-is-c-stl-implemented-internally/

  • http://gamesfromwithin.com/start-pre-allocating-and-stop-worrying

  • CppCon 2014:Mike Acton"面向数据的设计和C++">

当然,您可以使用动态内存,但最好了解其陷阱以便做出更好的决策。

最新更新