版权声明:转载请说明Zhonglihao原创 https://blog.csdn.net/xeonmm1/article/details/88084466
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdlib.h>
#include "stdio.h"
void MatrixPrint(double* arr, const int row, const int col);
double* MatrixInverse(double* arr_in, const int n);
void MatrixPivotExchange(double* arr, double* arr_inv, const int n, const int row);
int _tmain(int argc, _TCHAR* argv[])
{
//统一使用一维数组实现
const int row_A = 3;
const int col_A = 3;
double Mat_A[row_A*col_A] = { 1, 1, 1, 6, 3, 2, 3, 4, 3 };
//计算逆阵
double *Mat_A_Inv = MatrixInverse(Mat_A, row_A);
//打印原始矩阵和逆阵
MatrixPrint(Mat_A, row_A, col_A);
MatrixPrint(Mat_A_Inv, row_A, col_A);
system("Pause");
return 0;
}
double* MatrixInverse(double* arr_in, const int n)
{
int len = n * n;
int i;
int col_scan, row_scan, resi_row_scan; //主行扫描 余行消除主元扫描
double pivot; //主元缓存
//复制一份拷贝以防止改变原有数组
double *arr = (double *)malloc(len * sizeof(double));
for (i = 0; i < len; i++) arr[i] = arr_in[i];
//申请内存 置0 对角线置1
double *arr_inv = (double *)malloc(len * sizeof(double));
if (arr_inv == NULL) return NULL;
for (i = 0; i < len; i++)
{
if ((int)(i / n) == (int)(i % n))
arr_inv[i] = 1;
else
arr_inv[i] = 0;
}
//开始计算逆阵
for (row_scan = 0; row_scan < n; row_scan++)
{
//列主元换位
MatrixPivotExchange(arr, arr_inv, n, row_scan);
//原矩阵与增广矩阵行元素均需要除以列主元
pivot = arr[row_scan * (n + 1)];
for (col_scan = row_scan; col_scan < n; col_scan++) // 下三角
{
arr[row_scan * n + col_scan] = arr[row_scan * n + col_scan] / pivot;
}
for (col_scan = 0; col_scan < n; col_scan++) //逆阵区全部都要计算
{
arr_inv[row_scan * n + col_scan] = arr_inv[row_scan * n + col_scan] / pivot;
}
//通过主元行消除其余行首位元素
for (resi_row_scan = row_scan + 1; resi_row_scan < n; resi_row_scan++)
{
pivot = arr[resi_row_scan * n + row_scan];
for (col_scan = row_scan; col_scan < n; col_scan++) //下三角
{
arr[resi_row_scan * n + col_scan] = arr[resi_row_scan * n + col_scan] - pivot * arr[row_scan * n + col_scan];
}
for (col_scan = 0; col_scan < n; col_scan++) //逆阵区全部都要计算
{
arr_inv[resi_row_scan * n + col_scan] = arr_inv[resi_row_scan * n + col_scan] - pivot * arr_inv[row_scan * n + col_scan];
}
}
}
//反三角往上消除
for (row_scan = n - 1; row_scan >= 0; row_scan--)
{
for (resi_row_scan = row_scan - 1; resi_row_scan >= 0; resi_row_scan--)
{
pivot = arr[resi_row_scan * n + row_scan];
arr[resi_row_scan * n + row_scan] = 0;
for (col_scan = 0; col_scan < n; col_scan++) //逆阵区全部都要计算
{
arr_inv[resi_row_scan * n + col_scan] = arr_inv[resi_row_scan * n + col_scan] - pivot * arr_inv[row_scan * n + col_scan];
}
}
}
free(arr);
return arr_inv;
}
//列主元换位
void MatrixPivotExchange(double* arr, double* arr_inv, const int n, const int row) //row为现在处理的行
{
int row_scan, col_scan; //循环标记
int col = row; //列主元的扫描列 就是输入的行
double max_value = arr[row * (n + 1)]; //输入时行的列主元值
int max_value_row = row; //记录最大列主元的所在行
double cmp_calue = 0;
double temp = 0;
int org_index, max_index;
//找到列主元的最大值所在行
for (row_scan = row + 1; row_scan < n; row_scan++)
{
cmp_calue = arr[row_scan * n + col];
if (max_value < cmp_calue)
{
max_value = cmp_calue;
max_value_row = row_scan;
}
}
//原矩阵与逆阵均需要换行
if (row != max_value_row)
{
for (col_scan = 0; col_scan < n; col_scan++)
{
org_index = row * n + col_scan;
max_index = max_value_row * n + col_scan;
temp = arr[org_index];
arr[org_index] = arr[max_index];
arr[max_index] = temp;
//兼容单矩阵和逆阵
if (arr_inv != NULL)
{
temp = arr_inv[org_index];
arr_inv[org_index] = arr_inv[max_index];
arr_inv[max_index] = temp;
}
}
}
return;
}
//矩阵打印方法
void MatrixPrint(double* arr, const int row, const int col)
{
int len = row * col;
int i,col_count;
for (i = 0, col_count = 0; i < len; i++)
{
printf("%f\t", arr[i]);
//单换行
if (++col_count >= col)
{
printf("\n");
col_count = 0;
}
}
//跳空换行
printf("\n");
return;
}