You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现矩阵行交换逻辑 消除线性方程组主对角线零元素

问题背景

我们有代表线性系统增广矩阵的二维数组,要求调整行顺序,保证主对角线(行号等于列号的位置)不存在0值。比如下方6行7列的矩阵:

1.0  0.0  -1.0  -4.9  -5.9   -6.9   -7.9
0.0  1.0   2.0   4.4   5.4    6.4    7.4
0.0  0.0   0.0   5.7   5.7   -3.3   -3.3
0.0  0.0   0.0   2.9   2.9    2.9    2.9
0.0  0.0   0.0   7.0  -1.0   -3.0   -3.0
0.0  0.0 -20.0 -65.9 -89.9 -100.9  128.9

只需交换索引为2和5的行,即可满足主对角线无0的要求。

当前实现仅将首行删除后追加到矩阵末尾,无法实现精准的行交换,需要正确的逻辑定位需要交换的行。

现有实现代码

change_order函数

void change_order(double linear[6][7], unsigned int qty) {
    double aux[100];

    // dynamically create an array of pointers of size `m`
    double **matrix = (double **)malloc((qty + 1) * sizeof(double *));

    // dynamically allocate memory of size `n` for each row
    for (int r = 0; r < qty+ 1; r++) {
        matrix[r] = (double *)malloc((qty + 1) * sizeof(double));
    }
 
    for (int i = 0; i < qty; i++) {
        for (int j = 0; j < qty+ 1; j++) {
            if (i == 0)
                aux[j] = linear[i][j];
        }
    }

    for (int i = 0; i < qty; i++) {
        for (int j = 0; j < qty+ 1; j++) {
            matrix[i][j] = linear[i][j];
        }
    }

    remove_line(matrix, 0, qty);

    for (int i = 0; i < qty; i++) {
        for (int j = 0; j < qty+ 1; j++) {
            linear[i][j] = matrix[i][j];
        }
    }

    for (int i = 0; i < qty; i++) {
        for (int j = 0; j < qty+ 1; j++) {
            if (i == qty- 1) {
                linear[i][j] = aux[j];
            }
        }
    }
}

remove_line函数

void remove_line(double ** linear, int row, unsigned int qty) {
    qty--;

    free(linear[row]);
    while (row < qty) {
        linear[row] = linear[row + 1];
        row++;
    }
}

main测试函数

int main() {
    double matrix[][7] = {
        {1.0,  0.0,  -1.0,  -4.9,  -5.9,   -6.9,  -7.9},
        {0.0,  1.0,   2.0,   4.4,   5.4,    6.4,   7.4},
        {0.0 , 0.0,   0.0,   5.7,   5.7,   -3.3,  -3.3},
        {0.0 , 0.0,   0.0,   2.9,   2.9,    2.9,   2.9},
        {0.0 , 0.0,   0.0,   7.0,  -1.0,   -3.0,  -3.0},
        {0.0 , 0.0, -20.0, -65.9, -89.9, -100.9, 128.9}
    };

    change_order(matrix, 6);
}
示例输入输出

输入4行4列增广矩阵:

0   3   2   28
4   0   2   24
2   3   0   16
4   2   1    0  

调整后符合要求的输出:

4   0   2   24
2   3   0   16
4   2   1    0  
0   3   2   28
解决方案

核心逻辑

采用高斯消元中的部分主元选取逻辑即可实现精准行交换,步骤如下:

  • 定义浮点0值判断阈值,避免精度误差导致判断错误
  • 逐列遍历矩阵的主对角线位置(列号c从0到矩阵行数-1):
    • 若当前行c的主对角线元素linear[c][c]非0,直接进入下一列
    • 若为0,从当前行下方的所有行(行号r从c+1到行数-1)中,找第一个第c列元素非0的行
    • 交换当前行c和找到的行r的全部元素
    • 若下方所有行的第c列都是0,说明矩阵奇异,无法满足主对角线无0要求,可返回错误标识
  • 无需额外申请堆内存,直接在原矩阵上交换行即可,避免内存泄漏问题。

实现代码

#include <math.h>
// 浮点0判断阈值,可根据精度需求调整
#define EPS 1e-9

void change_order(double linear[6][7], unsigned int qty) {
    // 每行的元素个数是qty+1(增广矩阵多一列常数项)
    int col_count = qty + 1;
    for (int c = 0; c < qty; c++) {
        // 先判断当前主对角线元素是否非0
        if (fabs(linear[c][c]) > EPS) {
            continue;
        }
        // 找下方第一个第c列非0的行
        int target_row = -1;
        for (int r = c + 1; r < qty; r++) {
            if (fabs(linear[r][c]) > EPS) {
                target_row = r;
                break;
            }
        }
        // 没找到说明矩阵奇异
        if (target_row == -1) {
            // 可根据需求加错误处理,这里直接返回
            return;
        }
        // 交换两行所有元素
        for (int j = 0; j < col_count; j++) {
            double temp = linear[c][j];
            linear[c][j] = linear[target_row][j];
            linear[target_row][j] = temp;
        }
    }
}

逻辑验证

对题目给出的6行矩阵:遍历到c=2时,主对角线元素linear[2][2]为0,向下查找后找到行5的第2列值为-20非0,交换行2和行5即可满足要求。
对4行示例输入:遍历到c=0时主对角线元素为0,向下找到行1的第0列值为4非0,交换行0和行1后,后续主对角线元素均非0,输出结果和题目给出的示例完全一致。


内容的提问来源于stack exchange,提问作者Donald Vecox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 00:06:06