根据条件移动矩阵列

时间:2019-05-14 11:12:03

标签: c function

我正在尝试用C语言编写一个函数,该函数将NxM矩阵作为输入,如果发现空列,则根据用户的选择将非空列移至矩阵的左侧或右侧空列可以是1,2或更多。

作为一个例子。假设下面的矩阵:

矩阵元素是:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 0 1 0 8
2| 1 3 0 3 0 1 0 0
3| 3 0 0 0 0 8 0 0
4| 0 0 0 2 6 0 0 4

如您所见,只有第3列和第7列完全为空(全为0)。我想要一个函数,如果用户选择l(左),它将把不为空的列向左移动。因此它将返回:

矩阵元素是:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 1 8 0 0
2| 1 3 3 0 1 0 0 0
3| 3 0 0 0 8 0 0 0
4| 0 0 2 6 0 4 0 0

如果用户选择r(代表右),它将把非空列移到右边,因此函数将返回:

矩阵元素是:

   1 2 3 4 5 6 7 8
------------------
1| 0 0 1 6 0 0 1 8 
2| 0 0 1 3 3 0 1 0 
3| 0 0 3 0 0 0 8 0 
4| 0 0 0 0 2 6 0 4 

这是我的第一个方法:

   void PushL(int (*arr), int rows, int cols){ //function to move columns to left 
    for(int i = 0; i < rows; i++)
        for(int j = 0;j < cols; j++){
                if(arr[i*cols+j] == 0)
                    for(int k = j + 1; k < cols; k++){
                        if(arr[i*cols+k] != 0){
                            arr[i*cols+j] = arr[i*cols+k];
                            arr[i*cols+k] = 0;
                            break;
                         }

                     }

           }

}

3 个答案:

答案 0 :(得分:1)

这可能不是唯一的问题,但是原始帖子中显示的两个代码段都缺少{}符号,这对于假定的意图至关重要。 (请参见/// here

void PushR(int (*arr), int rows, int cols){
    for(int i = rows; i > 0; i--)
        for(int j = cols;j > 0; j--){
                if(arr[i*cols+j] == 0)
                    for(int k = j + 1; k < cols; k++){
                        if(arr[i*cols+k] != 0)
                        { /// here
                            arr[i*cols+j] = arr[i*cols+k];
                            arr[i*cols+k] = 0;/// without {} these lines will be executed
                            break;            /// regardless of if evaluation
                        } /// and here
                    }
        }
}

(C中的缩进仅出于可读性,并不控制执行流程。)

要使代码对以后将要维护的代码更具可读性,最好消除所有关于意图的歧义:(包括在括号中未明确知道意图的花括号。)

void PushR(int (*arr), int rows, int cols){
    for(int i = rows; i > 0; i--) {/// added here
        for(int j = cols;j > 0; j--){
            if(arr[i*cols+j] == 0) { /// added here
               for(int k = j + 1; k < cols; k++){
                   if(arr[i*cols+k] != 0) { /// here
                       arr[i*cols+j] = arr[i*cols+k];
                       arr[i*cols+k] = 0;
                       break;
                   } /// and here
                }
            }
        }
     }    
 }

答案 1 :(得分:1)

出于有关{}丢失的问题,您的程序无法正常工作,因为您只考虑值等于0的单元格,还是不考虑同一列中的其他单元格。

您需要先确定该列是否全部包含 ,然后才能决定是否将其移动

为此:

int onlyZero(int (*arr), int col, int rows, int cols)
{
  const int sup = cols*rows;

  for (int i = 0; i != sup; i += cols) {
    if (arr[i + col] != 0)
      return 0;
  }

  return 1;
}

如果列 col 仅包含0,则返回1,否则返回0

要复制另一列:

void copyColumn(int (*arr), int fromCol, int toCol, int rows, int cols)
{
  int sup = cols*rows;

  for (int i = 0; i != sup; i += cols)
    arr[i + toCol] = arr[i + fromCol];
}

并重置列:

void resetColumn(int (*arr), int col, int rows, int cols)
{
  int sup = cols*rows;

  for (int i = 0; i != sup; i += cols)
    arr[i + col] = 0;
}

使用这些功能,即使这样也不是更快的方法:

void PushL(int (*arr), int rows, int cols)
{
  int receiver = 0;

  for (int col = 0; col != cols; ++col) {
    if (!onlyZero(arr, col, rows, cols)) {
      if (receiver != col)
        copyColumn(arr, col, receiver, rows, cols);
      receiver += 1;
    }
  }

  while (receiver != cols)
    resetColumn(arr, receiver++, rows, cols);
}

添加

void pr(int (*arr), int rows, int cols)
{
  for (int row = 0; row != rows; ++row) {
    for (int col = 0; col != cols; ++col) {
      printf("%d ", arr[row*cols + col]);
    }
    putchar('\n');
  }
  putchar('\n');
}

int main()
{
  int a[] = { 
    1, 6, 0, 0, 0, 1, 0, 8,
    1, 3, 0, 3, 0, 1, 0, 0,
    3, 0, 0, 0, 0, 8, 0, 0,
    0, 0, 0, 2, 6, 0, 0, 4
  };

  pr(a, 4, 8);
  PushL(a, 4, 8);
  pr(a, 4, 8);
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall m.c
pi@raspberrypi:/tmp $ ./a.out
1 6 0 0 0 1 0 8 
1 3 0 3 0 1 0 0 
3 0 0 0 0 8 0 0 
0 0 0 2 6 0 0 4 

1 6 0 0 1 8 0 0 
1 3 3 0 1 0 0 0 
3 0 0 0 8 0 0 0 
0 0 2 6 0 4 0 0 

我让您执行与PushL非常接近的PushR

PushR PushL 的对称符号:

void PushR(int (*arr), int rows, int cols)
{
  int receiver = cols - 1;

  for (int col = cols-1; col != -1; --col) {
    if (!onlyZero(arr, col, rows, cols)) {
      if (receiver != col)
        copyColumn(arr, col, receiver, rows, cols); 
      receiver -= 1;
    }
  } 

  while (receiver != -1) 
    resetColumn(arr, receiver--, rows, cols);
} 

答案 2 :(得分:0)

void test()
{
    int p[4][9] = {
        1 , 1, 6, 0, 0, 0, 1, 0, 8,
        2 , 1, 3, 0, 3, 0, 1, 0, 0,
        3 , 3, 0, 0, 0, 0, 8, 0, 0,
        4 , 0, 0, 0, 2, 6, 0, 0, 4 };
    int pp[4][9] = {};


    int say = 0;

    for (int i = 0; i < 9; i++)
    { 
        bool ok = false;
        for (int j = 0; j < 4; j++)
        {
            if (p[j][i] != 0)
                ok = true;
        }

        if (ok)
        { 
            for (int j = 0; j < 4; j++)
                pp[j][say] = p[j][i];
            say++;
        }

    }


    for (int j = 0; j < 4; j++)
    for (int i = 0; i < 9; i++)
    {
        printf("%d ", pp[j][i]);
        if (i == 8) printf("\n");
    }

}