递归 代数余子式计算行列式 && 逆矩阵的运算

上个星期,我们的线性代数老师让我们编程计算行列式,这个星期又让我们算逆矩阵

虽然这个老师上课老爱吹水,但是至少让我们编的程序是可行的

根据某定理:n阶行列式等于它的任一行的元素与其对应的代数余子式的乘积之和;即:

D=ai1*Ai1+ai2*Ai2+.....+ain*Ain(i= 1,2,3...n)

取i==1时展开:

D=a11*A11+a12*A12+...a1n*A1n;

设递归函数rec(n,D)为D行列的值;n:行列的阶;

根据定理按照第一行展开可得:

rec(n,D)=sumj ( (-1)^1+j * a1j * rec(n-1,A1j) ); A1j为a1j的代数余子式;sumj为求和

n==1 时,rec(1,D)==D;

#include<iostream>
#include<vector>
using std::vector;
double rec(int n, vector<double>D) {
	if (n == 1) {
		return D.back();
	}
	int e = 1;//设置符号
	double sum = 0;
	for (int k = 0; k < n; k++) {
		vector<double>d;
		for (int i = 1; i < n; i++) {//i==1表示从第一行开始,因为第0行是被展开的量;
			for (int j = 0; j < n; j++) {
				if (k == j)continue;     //划去同列元素;
				d.push_back(D[i*n + j]);

			}
		}
		sum += D[k] * e*rec(n - 1, d);
		e *= -1;
	}
	return sum;
}
int main() {
	int n;
	std::cin >> n;
	vector<double>d;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			double a;
			std::cin >> a;
			d.push_back(a);

		}
	}
	std::cout << rec(n, d);
	return 0;
}

 计算逆矩阵:

A^-1 =  A*/ | A |;   A*为伴随矩阵

概念不叙述了:

/*
各函数表示的含义:
project: 得到aij的余子式;
rec    : 计算行列式D的值
AT     : 将矩阵进行转置;
A_     : 计算A的逆矩阵;
*/
#include<iostream>
#include<vector>
#include<iomanip>
#include<cstring>
#include<cmath>
using std::vector;
const double eps = 1e-3;
vector<double>project(int n, vector<double>&D, int ii, int jj) {//分出余子式;
	vector<double>c;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (i == ii || j == jj)continue;
			c.push_back(D[i*n + j]);
		}
	}
	return c;
}

double rec(int n, vector<double>&D) {
	if (n == 1) {
		return D.back();
	}
	int e = 1;
	double sum = 0;

	for (int k = 0; k < n; k++) {
		vector<double>d;
		d = project(n, D, 0, k);
		sum += D[k] * e*rec(n - 1, d);
		e *= -1;
	}
	return sum;
}
vector<double>AT(int n, vector<double>&D) {//转置;
	vector<double>c;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			c.push_back(D[j*n + i]);
		}
	}
	return c;
}
vector<double>A_(int n, vector<double>&D) {//计算逆矩阵;
	vector<double>c;
	//先将每个元素的代数余子式计算出来;
	double A = rec(n, D);//计算D的行列值;
	if (A == 0)return c;//如果A为0则无逆矩阵:返回一个空向量判断;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			vector<double>Aij;
			Aij = project(n, D, i, j);
			double aij = rec(n - 1, Aij) / A;
			if ((i + j) & 1)aij *= -1;
			c.push_back(aij);
		}
	}
	//转置:
	c = AT(n, c);
	return c;
}
int main() {
	int n;
	std::cin >> n;
	vector<double>d;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			double a;
			std::cin >> a;
			d.push_back(a);

		}
	}

	vector<double>D = A_(n, d);

	//输出;
	//保留两位小数:
	if (D.empty()) {
		std::cout << "该矩阵为奇异阵";
		return 0;
	}

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (fabs(D[i*n + j]-int(D[i*n+j])) <= eps) {
				std::cout << std::setw(6) << int(D[i*n+j]); continue;
			}
			std::cout << std::fixed << std::setprecision(2) << std::setw(6) << D[i*n + j];
		}
		std::cout << '\n' << '\n';
	}
	return 0;
}

 分析一下时间复杂度:

行列式的计算rec:令rec(n)的复杂度为T(n)递归式执行了n次rec(n-1)

则有T(n)=nT(n-1)+o(1)

T(n) =n!

然后又是  A_函数n^2* T(n)=O(n^2*n!);

并且常数比较大,所以到n==10就不能秒算了  

时间复杂分析更新与2022-5-8

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值