Delete a column and a row in a square matrix in C

9.1k views Asked by At

I had a square matrix typed dynamically, correctly allocated

double **matrix;

I want to delete a "x" row and "x" column from that matrix, in a way like that:

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

I want to remove, for example, the 2nd row/column. The output had to be like this:

FINAL MATRIX:
1 3 4
9 11 12
13 15 16

I've tried to write down and test many algorithms, without success. How can I do?

3

There are 3 answers

4
David van rijn On BEST ANSWER

Well, to do this, you'll have to realise that in memory your matrix is actually a list of lists. This means that removing a column is slightly different from removing a row:

Assuming your syntax is matrix[row][column];

void removeColumn(int** matrix, int col){
  MATRIX_WIDTH--;
  //TODO check for empty matrix etc;
  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);
  }
void removeRow(int** matrix, int row){
  MATRIX_HEIGHT--;
  //TODO check for empty matrix etc.
  free(matrix[row]);
  while(row<MATRIX_HEIGHT)
  {
    //move data up
    matrix[row] = matrix[row+1];
    row++;
  }
}

so removeColumn iterates over each row, and deletes the appropriate item, and removeRow can just free the row, and overwrite its pointer.

NOTE that you have to keep track of the size of the matrix size yourself. In the example i used MATRIX_WIDTH and MATRIX_HEIGHT but you'll have to implement something for this. (Maybe a struct with width height and pointer in it.)

4
dimyr7 On

What I would do is split this matrix into 5 zones. 1) zone to be deleted. 2) Zone "before" the deleted index (it would be just 1 in your example matrix). 3) Zone "after" the deleted index (it would be 11,12,15,16 in your matrix). 4) and 5) Are the two remaining 'zones'. One would be (3, 4) the other would (9,13)

Just make a conditional for each of the 5 zones and copy.

double** matrix = (double**)malloc(sizeof(double)*n*n);
//fill in the matrix here
double** copy (double**)malloc(sizeof(double)*(n-1)*(n-1));
int i;
int j;
int deleteNum;  //what ever row you want to delete
for(i = 0; i < n; i++){
    for(j = 0; j < n; j++){
        if(i < deleteNum && j < deleteNum){
            copy[i][j] = matrix[i][j];
        }
        else if(deleteNum == i || deleteNum == j){
             //one of the rows/columns to be deletd
             //basically skip
        }
        else if(i < deleteNum && j > deleteNum){
             copy[i][j-1] = matrix[i][j];
        }
        else if(i > deleteNum && j < deleteNum){
             copy[i-1][j] = matrix[i][j]
        }
        else{
            copy[i-1][j-1] = matrix[i][j];
        }
    }
}
0
maqszur On

As I was looking for a answer to the similar problem but with matrix stored in linear space here's my solution (I'm using column-major order here, but if you're using row-major it only minor changes are needed)

void removeRow(float * arrayToRemove, const int & currentRows, const int & currentCols, const int & row)
{
    auto currDiff = 0;
    auto step = currentRows;
    auto elemNum = currentRows * currentCols;

    for (int i = row, stepCounter = 0; i < elemNum; ++i, ++stepCounter)
    {
        if (stepCounter % step == 0)
        {
            ++currDiff;
        }
        else
        {
            arrayToRemove[i - currDiff] = arrayToRemove[i];
        }
    }
}

void removeCol(float * arrayToRemove, const int & currentRows, const int & currentCols, const int & col)
{
    auto destination = arrayToRemove + (col * currentRows);
    auto source = arrayToRemove + ((col + 1) * currentRows);
    const auto elemsNum = (currentCols - (col + 1)) * currentRows;
    memcpy(destination, source, elemsNum * sizeof(float));
}