【问题标题】:Swapping Columns/Rows of 1-Dimensional Arrays in C在 C 中交换一维数组的列/行
【发布时间】:2017-10-30 16:36:12
【问题描述】:

尝试在一维数组中创建两个矩阵函数(一个用于交换列,一个用于交换行)。显然,它们在结构上是相似的。

void col_swap(int a[], int col1, int col2, int colSize, int rowSize) {
  int d[size];
  int space = col2 - col1;
  for (int i = 0; i < rowSize; i++) {
    for (int j = 0; j < colSize; j++) {
      if (i == (col1 - 1) || i == (j * (col1-1))) {
        d[i+space] = a[i];
      } else if (i == (col2 - 1) || i == (j * (col2-1))) {
        d[i-space] = a[i];
      } else {
        d[i] = a[i];
      }
    }
    printf("%d  ", d[i]);
      if ((i+1) % colSize == 0) {
          printf("\n");
      }
  }
}

是的,矩阵必须是一维数组。这也不能完全发挥作用。

编辑:COL1COL2 分别不是“矩阵的第一列”和“矩阵的第二列”。它们是我们想要切换的矩阵的任意两列。

void row_swap(int a[], int row1, int row2, int rowSize, int colSize) {
  for (int i = 0; i < colSize; i++) {
    int temp = a[i*rowSize+row1];
    a[i*rowSize+row1] = a[i*rowSize+row2];
    a[i*rowSize+row2] = temp;
  }
  for (int i = 0; i < size; i++) {
    if (i % colSize == 0) {
      printf("\n");
    }
    printf("%d ", a[i]);
  }
}

我有上面的 row_swap 函数,但是当我给它一个矩阵时

1, 4,
2, 3,
3, 2,
4, 1

返回

1, 3
2, 4
3, 1
4, 2

【问题讨论】:

  • c 大师可以在这里纠正我,但我很确定二维数组 NxM 在内存中看起来与 NxM 维一维数组完全相同 - 因此可以在两者中访问方式(单支架或双支架,在尺寸范围内)。另外,什么不起作用,你怀疑什么等等?
  • @kabanus 你即将被纠正:你在第一部分是正确的,但你的结论是错误的,see this question。我仍然想知道为什么必须使用一维数组来存储矩阵。
  • @FelixPalmen 谢谢。这是在编译器中强制执行的吗?我不知道C 编译器会这么严格。
  • @kabanus 不,这使得它更多成问题,就像许多可能导致未定义行为的 C 代码;)
  • @FelixPalmen 啊,这就是它如此可爱的原因。

标签: c arrays matrix linear-algebra


【解决方案1】:

这比你想象的要容易得多。

所以你想交换col1col2,这里的矩阵有rowsize 的行数和colsize 的列数。

void col_swap(int a[], int col1, int col2, int colSize, int rowSize) {
  for(int i=0;i<rowSize;i++){
    int t=a[i*colSize+col1];
    a[i*colSize+col1]=a[i*colSize+col2];
    a[i*colSize+col2]=t; 
  }
}

想想这里有什么不同。我们刚刚计算清楚了该位置的逻辑。然后一切都与标准交换相同。

更结构上你可以这样做:-

void swap(int *a,int*b)
{
    int t=*a;
    *a=*b;
    *b=t;
}
void col_swap(int a[], int col1, int col2, int colSize, int rowSize) {
  for(int i=0;i<rowSize;i++){
    swap(&a[i*colSize+col1],&a[i*colSize+col2]); 
  }
}

行交换将是相同的。如果将行视为列,则类似于列交换,反之亦然。

其次,您为什么要通过使用一维数组中的二维数组来使事情复杂化?

这很难在生产级代码或更具体的软件中使用。为什么不使用二维数组本身?您应该使用它而不是这样做。


方法是什么?

阅读问题后,我只是用纸来了解我想要做什么以及它如何从二维数组映射到一维数组。这有助于很多时间。然后首先对第一个解决方案进行编码。我可以看到我也可以在 Row 交换的情况下重用交换部分。所以我把它拿出来放在另一个函数swap

示例输入输出示例:

int a[]={1,2,3,4,5,6,7,8,9,10,11,12};
    col_swap(a,1,2,3,4);

// 1 2 3 
// 4 5 6 
// 7 8 9 
// 10 11 12

// 1 3 2 
// 4 6 5 
// 7 9 8 
// 10 12 11

再次考虑:

col_swap(a,0,2,3,4); 在同一个数组上会导致

// 3 2 1
// 6 5 4
// 9 8 7
// 12 11 10

我在代码中使用了 0 索引。因此,在提供输入列时要小心。

另外一个功能是:-

void row_swap(int a[], int row1, int row2, int colSize, int rowSize) {
  for(int i=0;i<colSize;i++){
    swap(&a[colSize*row1+i],&a[row2*colSize+i]); 
  }
}

【讨论】:

  • 感谢您的回复,但这并不是我真正想要的。这就是我认为我误会了你的地方。参数 col1 和 col2 不是“第一列”和“第二列”。它们是我们想要切换的矩阵的任意 2 列。因此,每当我们循环遍历原始矩阵时,我们都必须查看数字是否在正确的列中,然后将其与另一列中的数字进行切换。它是一维数组的原因是 b/c 这是一个类的赋值。
  • 我很确定应该检查一下数字是否在我们尝试交换的列中。例如,如果我们有一个 4x3 矩阵,并且我们想要交换第 2 列和第 3 列,我们必须确保我们不会将第 1 列和第 4 列中的值与任何东西交换;我认为这发生在你的代码中。 (现在没有工具可以检查,所以这只是我所看到的)
  • 是的,哈哈。抱歉,我只是有点困惑,但它现在可以工作了。谢谢。
  • 如果我现在想交换行,我是否只需将每个 colSize 替换为 rowSize,反之亦然?还是没有那么简单……
  • 我遇到了行交换的问题(我已经编辑了主帖以显示函数和结果)
【解决方案2】:

如果您使用的是 C99,则指向 Variable Length Arrays 的指针可以使索引更容易:

void col_swap(int a[], int col1, int col2, int colSize, int rowSize)
{
    // Cast 'a' to a pointer to a variable length array of size 'colSize'
    int (*a2d_matrix)[colSize] = (int (*)[colSize])a;

    // Now we can index into a (through a2d_matrix) as if it really is
    // a 2 dimensional matrix
    for(int r = 0; r < rowSize; r++)
    {
        int temp = a2d_matrix[r][col1];
        a2d_matrix[r][col1] = a2d_matrix[r][col2];
        a2d_matrix[r][col2] = temp; 
    }
}

我经常使用这种方法。请注意,这可能适用于 C11 及更高版本,但可变长度数组在 C11 标准中是可选的。因此,请检查您的编译器对可选 C11 功能的支持。据我所知,所有主要供应商都支持 C11 中的 VLA。

【讨论】:

  • 这也违反了严格的别名。您可能遇到此类演员阵容的糟糕问题。
  • @FelixPalmen 实际上我前段时间问过this question 这个定义很好,经过各种回答和讨论后,一致认为这并没有违反严格的别名。我正在阅读您的链接答案,但这似乎表明相反...
  • @FelixPalmen 如果您认为接受的答案不正确,也许您可​​以为我刚刚引用的问题添加答案?我会很感激的。
  • 很难构造出这样的构造会失败的东西,所以它主要是出于学术兴趣,但我认为分配对象的情况不同 -> 它没有声明的类型(因此没有数组类型)。如果您添加 language-lawyer 标记,您链接的问题可能会收到 很多 的讨论:)
猜你喜欢
  • 2021-03-29
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多