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要求,可返回错误标识
- 若当前行c的主对角线元素
- 无需额外申请堆内存,直接在原矩阵上交换行即可,避免内存泄漏问题。
实现代码
#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
相关产品推荐
相关产品推荐

