行列式的计算

行列式的众多正经的不正经的计算方法就属线性代数的内容了,这里不过多讨论,主要介绍代码中会用到的两种:

  1. 公式计算
    行列式值的计算公式为
    ∣a11a12⋯a1na21a22⋯a2n⋮⋮⋯⋮an1an2⋯ann∣=∑p1p2⋯pn(−1)τ(p1p2⋯pn)a1p1a2p2⋯anpn\left| \begin{array}{cccc} a_{11} & a_{12} & \cdots & a_{1 n} \\ a_{21} & a_{22} & \cdots & a_{2 n} \\ \vdots & \vdots & \cdots & \vdots \\ a_{n 1} & a_{n 2} & \cdots & a_{n n} \end{array} \right| =\sum_{p_1p_{2} \cdots p_{n}}(-1)^{\tau\left(p_{1} p_{2} \cdots p_{n}\right)} a_{1 p_{1}} a_{2 p_{2}} \cdots a_{n p_{n}} ∣∣∣∣∣∣∣∣∣​a11​a21​⋮an1​​a12​a22​⋮an2​​⋯⋯⋯⋯​a1n​a2n​⋮ann​​∣∣∣∣∣∣∣∣∣​=p1​p2​⋯pn​∑​(−1)τ(p1​p2​⋯pn​)a1p1​​a2p2​​⋯anpn​​
    其中τ\tauτ是序列p1p2p3p4⋯p_1p_2p_3p_4\cdotsp1​p2​p3​p4​⋯中的逆序对数且各pip_ipi​互不相同。
  2. 利用代数余子式进行计算
    结论:行列式等于它任意一行(列)的各元素与其对应的代数式余子式乘积之和。
    ∣a11a12⋯a1na21a22⋯a2n⋮⋮⋮⋮an1an2⋯ann∣=a11∣a22a23⋯a2n⋮⋮⋮⋮an2an3⋯ann∣−a12∣a22a23⋯a2n⋮⋮⋮⋮an2an3⋯ann∣+⋯+(−1)1+na1n∣a21a22⋯a2,n−1⋮⋮⋮⋮an1an2⋯an,n−1∣\begin{aligned} \left|\begin{array}{cccc} a_{11} & a_{12} & \cdots & a_{1 n} \\ a_{21} & a_{22} & \cdots & a_{2 n} \\ \vdots & \vdots & \vdots & \vdots \\ a_{n 1} & a_{n 2} & \cdots & a_{n n} \end{array}\right|=& a_{11}\left|\begin{array}{cccc} a_{22} & a_{23} & \cdots & a_{2 n} \\ \vdots & \vdots & \vdots & \vdots \\ a_{n 2} & a_{n 3} & \cdots & a_{n n} \end{array}\right|-a_{12}\left|\begin{array}{cccc} a_{22} & a_{23} & \cdots & a_{2 n} \\ \vdots & \vdots & \vdots & \vdots \\ a_{n 2} & a_{n 3} & \cdots & a_{n n} \end{array}\right| +\cdots+(-1)^{1+n} a_{1 n}\left|\begin{array}{cccc} a_{21} & a_{22} & \cdots & a_{2, n-1} \\ \vdots & \vdots & \vdots & \vdots \\ a_{n 1} & a_{n 2} & \cdots & a_{n, n-1} \end{array}\right| \end{aligned} ∣∣∣∣∣∣∣∣∣​a11​a21​⋮an1​​a12​a22​⋮an2​​⋯⋯⋮⋯​a1n​a2n​⋮ann​​∣∣∣∣∣∣∣∣∣​=​a11​∣∣∣∣∣∣∣​a22​⋮an2​​a23​⋮an3​​⋯⋮⋯​a2n​⋮ann​​∣∣∣∣∣∣∣​−a12​∣∣∣∣∣∣∣​a22​⋮an2​​a23​⋮an3​​⋯⋮⋯​a2n​⋮ann​​∣∣∣∣∣∣∣​+⋯+(−1)1+na1n​∣∣∣∣∣∣∣​a21​⋮an1​​a22​⋮an2​​⋯⋮⋯​a2,n−1​⋮an,n−1​​∣∣∣∣∣∣∣​​

1. 5阶矩阵行列式的计算

∣a00a01a02a03a04a10a11a12a13a14a20a21a22a23a24a30a31a32a33a34a40a41a42a43a44∣=∑j0j1j2j3j4(−1)τ(j0j1j2j3j4)a0j0a1j1a2j2a3j3a4j4\left| \begin{array}{cccc} a_{00}&a_{01} & a_{02} & a_{03}&a_{04} \\ a_{10}&a_{11} & a_{12} & a_{13}&a_{14} \\ a_{20}&a_{21} & a_{22} & a_{23}&a_{24}\\ a_{30}&a_{31} & a_{32} & a_{33}&a_{34}\\ a_{40}&a_{41} & a_{42} & a_{43}&a_{44} \\ \end{array} \right| =\sum_{j_0j_1j_2j_3j_4 }(-1)^{\tau\left(j_0j_1j_2j_3j_4 \right)} a_{0 j_{0}} a_{1j_1} a_{2j_2}a_{3j_3}a_{4j_4} ∣∣∣∣∣∣∣∣∣∣​a00​a10​a20​a30​a40​​a01​a11​a21​a31​a41​​a02​a12​a22​a32​a42​​a03​a13​a23​a33​a43​​a04​a14​a24​a34​a44​​∣∣∣∣∣∣∣∣∣∣​=j0​j1​j2​j3​j4​∑​(−1)τ(j0​j1​j2​j3​j4​)a0j0​​a1j1​​a2j2​​a3j3​​a4j4​​
C++代码实现

#include<iostream>
#include<string>using namespace std;int main()
{   double a[5][5] = { 0 };double result = 0;int j0, j1, j2, j3, j4, inverse, flag;//输入矩阵cout << "请输入矩阵的25个数据:";for (int i = 0; i < 5; ++i)for (int j = 0; j < 5; ++j)cin >> a[i][j];for (j0 = 0; j0 < 4; ++j0){inverse = 0;                    //逆序对初值for (j1 = 0; j1 < 4; ++j1){if (j1 == j0)  continue;    //排除j1和j0相等的情况else if (j1 < j0) ++inverse;//若j1<j0,则逆序数+1for (j2 = 0; j2 < 4; ++j2) {if (j2 == j0 || j2 == j1) continue;inverse += (j2 < j0) + (j2 < j1);//若j2<j0 则(j2<j0)的值为1;若j2>j0 则(j2<j0)的值为0for (j3 = 0; j3 < 4; ++j3) {if (j3 == j2 || j3 == j1 || j3 == j0)continue;inverse += (j3 < j2) + (j3 < j1) + (j3 < j0);for (j4 = 0; j4 < 4; ++j4)if (j4 == j3 || j4 == j2 || j4 == j1 || j4 == j0) continue;//j4可以不利用枚举法//j4 = 10 - j0 - j1 - j2 - j3;inverse += (j4 < j3) + (j4 < j2) + (j4 < j1) + (j4 < j0);flag = (inverse % 2 == 0 ? 1 : -1);result += flag * a[0][j0] * a[1][j1] * a[2][j2] * a[3][j3] * a[4][j4];}}}}for (int m = 0; m < 5; ++m) {for (int n = 0; n < 5; ++n)cout << a[m][n] << " ";cout << endl;}cout << "行列式的值是" << result << endl;return 0;
}

运行结果如下:
注:为了能够简单验证结果的正确性,所以取的矩阵比较“好看”。

2. n阶矩阵行列式的计算

对于n阶矩阵来说,由于并不能在编程时确定其矩阵大小,上述方法则显得不是那么恰当,在这里利用指针构造动态数组进行计算。

动态数组和普通数组的最大区别在于,它的规模可以是运行程序过程种某一变量的值或某一表达式的计算结果,而普通数组的长度必须是在编译时就能确定的常量。

注:动态数组不能为数组元素赋初值

C++代码实现

#include <stdio.h>
#include <iostream>
using namespace std;int det(int n, int** mat)//取矩阵的第一列进行运算
{int mov = 0;//记录a,b矩阵相对应的行数是否发生了改变int flag;int sum = 0;if (n == 1) return mat[0][0];int** b = new int* [n - 1];//创建第一列的n-1阶代数余子式矩阵for (int z = 0; z < n-1; ++z)b[z] = new int[n-1];//为每一行申请空间for (int i = 0; i < n; ++i){for (int j = 0; j < n - 1; ++j) {mov = i > j ? 0 : 1;//b中行数小于此时a中所取行数即i时,可直接将a中j行搬到b中j行;//b中行数大于此时a中所取行数即i时,需将a中第j+1行搬运到b中j行;for (int k = 0; k < n - 1; ++k)//开始一行一行的搬运b[j][k] = mat[j + mov][k + 1];//k+1是因为在搬运过程中不取mat中第一列}if (i % 2 == 0) flag = 1;else flag = -1;//判断符号的正负,因为所取值为mat[0][i],所以需判断1+1+i=i+2的奇偶sum += flag * mat[i][0] * det(n - 1, b);}delete[] b;return sum;
}
int main()
{int n = 0;//矩阵阶数cout << "输入矩阵阶数:" << endl;cin >> n;int** a = new int* [n];//所要求的矩阵,因为矩阵阶数不是常数,so不能直接创建数组,以指针的形式呈现。for (int z = 0; z < n; ++z)a[z] = new int[n];//为每一行申请空间cout << "输入矩阵:" << endl;for (int x = 0; x < n; ++x)for (int y = 0; y < n; ++y)cin >> a[x][y];for (int x = 0; x < n; ++x){cout << endl;for (int y = 0; y < n; ++y)cout << a[x][y] << " ";}cout << endl;cout << "矩阵行列式的值为:" << det(n, a);for (int p = 0; p < n; ++p)delete[] a[p];delete[]a;return 0;
}

灵感来源于:https://blog.csdn.net/sinat_36219858/article/details/54016698
这篇博文并未利用二级指针,而是利用数组储存了全部矩阵信息。

运行结果如下:

注:为了能够简单验证结果的正确性,所以取的矩阵比较“好看”。

当然,如果真的只是为了算个矩阵,仍旧强推MATLAB。

3. 踩坑记录

  • 5阶矩阵的代码编写还是比较容易的,可以在此基础上进行改进,比如求个6阶,7阶也是可以的。
  • n阶代码的确编了很长时间,可能是由于一学期不学线代+一学期不敲代码的原因,出了一些奇奇怪怪的错:
  1. 循环的位置一定要看对,语句一定要放在正确的循环里。
  2. 指针的基本操作要熟悉,要不不是忘了申请空间就是忘了释放空间
  3. 行列要分清,不然。。。像我一样把 mat[i][0]mat[i][0]mat[i][0]写成mat[0][i]mat[0][i]mat[0][i]盯一下午?
  • 顺便提醒一下,n阶的代码在VS上运行会报很多警告,大概是它跟多级2指针有仇,可以给大家看一眼:

    so,最后看不下去,用的codeblocks:

    距上一篇博客怕是已经半年了,这半年几乎没敲过代码(因为不上有关的课了)。下学期会学数据结构,so趁开学前几天把C++复习一下~

行列式的计算(c++)——公式法(5阶)和递推法(n阶)相关推荐

  1. 算法笔记方法论3 递推法与递归法

    你站在桥上看风景看风景的人在楼上看你明月装饰了你的窗子你装饰了别人的梦--卞之琳 递推算法的特点 一个问题的求解需要大量重复计算,在已知的条件和所求问题之间总存在着某种相互联系的关系,在计算时,我们需 ...

  2. C/C++程序设计常用算法——递推法

    文档声明: 以下资料均属于本人在学习过程中产出的学习笔记,如果错误或者遗漏之处,请多多指正.并且该文档在后期会随着学习的深入不断补充完善. 资料仅供学习交流使用. 作者:Aliven888 1.简述 ...

  3. 递推法与递归法2022.3.14

    递推法与递归法2022.3.14 递推法是用于数值求解的一个重要算法. 存储型的递归和递推: 存储就加个数组就好了吧. 三角形递推,先赋好值然后从后往前递推.甚至都不需要额外的空间,最后返回a[1][ ...

  4. 随机数字信号处理实验报告三——Levinson和Burg递推法MATLAB实现

    完整的实验报告下载连接https://download.csdn.net/download/LIsaWinLee/14884452 一.实验原理 随机信号的功率谱密度用来描述信号的能量特征随频率的变化 ...

  5. 递推(一):递推法的基本思想

    所谓递推,是指从已知的初始条件出发,依据某种递推关系,逐次推出所要求的各中间结果及最后结果.其中初始条件或是问题本身已经给定,或是通过对问题的分析与化简后确定. 利用递推算法求问题规模为n的解的基本思 ...

  6. 记忆化搜素,和递推法

    记忆化搜素是动态规划的改进,------自上而下,就是在递归重叠子问题时候,对子问题的重复问题的对策,就是一开始对所有子问题进行赋值(一般为-1)这样的标记方法来区分是否被查找过. 递推----也是动 ...

  7. 常见算法思想2:递推法

    递推法 递推算法犹如稳重的有经验的老将,使用"稳扎稳打"的策略,不断利用已有的信息推导出新的东西. 在日常应用中有如下两种递推算法: (1)顺推法:从已知条件出发,逐步推算出要解决 ...

  8. 随机信号处理AR模型Yule_Walker方程直接解法和Levinson_Durbin递推法的MATLAB与Python实现

    AR模型 AR模型的系统函数H(z)可以表示为: 我们的目的就是要求解系统函数的参数a和增益G. Yule_Walker方程 矩阵形式 根据生成的矩阵,可以解出p个参数 ,再根据自相关函数,可以求出系 ...

  9. 银行存款(C语言,递推法)

    题目: 母亲为儿子sun 4年的大学生活准备了一笔存款,方式是整取零存,规定sun 每个月月底取下一个月的生活费.假设银行年利息为1.71%,计算该母亲每个月至少要存入多少钱? 算法分析: 可采用逆推 ...

  10. 算法设计 之 递推法

    2019独角兽企业重金招聘Python工程师标准>>> 递推法就是根据已知条件,分析推导出问题中的联系,然后一步一步进行推倒直至得到结果. 根据具体问题我们需要选择是正推还是逆推来解 ...

最新文章

  1. FPGA和DSP间基于SRIO的高速通信系统设计
  2. ubuntu16禁用utc时间
  3. 安卓初学者必看实例,(手机GPS简单编程访问)
  4. 凯撒(Caesar)密码加密解密c语言
  5. xenserver 挂载磁盘 xe sr-create_视频号挂载小商店,仅需3步!
  6. [bzoj1036][ZJOI2008]树的统计Count
  7. 常见30种数学建模模型_11.12|认识数学模型与数学建模许可
  8. 深入浅出C/C++中的正则表达式库(一)--GNU Regex Library
  9. 第一章-第一题(小学生四则运算)--By郭青云
  10. Zemax实现微透镜阵列光束整形(原理+仿真)
  11. java 音频倍速播放_如何让视频加速播放
  12. pygame: libpng warning: iCCP: known incorrect sRGB profile 报错
  13. 怎样做好邮箱安全,什么邮箱安全又好用,如何安全管理邮箱
  14. 长时间 正在加载个人设置 开机很慢
  15. 雨量水位监测站 水情监测
  16. 【openEuler】x2openEuler工具使用
  17. 高端大气上档次的管理后台模板
  18. 华为od统一考试B卷【机器人走迷宫】Java 实现
  19. 微信小程序--上传图片加水印
  20. Excel按某一列或多列合并行

热门文章

  1. ImportError: _C.cpython-37m-x86_64-linux-gnu.so: undefined symbol:_ZN3c107Warning4warnENS_14SourceL
  2. NSFC: 国内外研究现状的几种节奏
  3. “点击欺诈”恶意软件藏有更大的威胁?
  4. 前端开发:JS中setTimeout和setInterval的对比使用
  5. JS_02_函数_运算符_循环
  6. 家用pc游戏菜单_为什么仍然必须登录到家用PC?
  7. Centos7 安装Nat123
  8. svn基于mysql认证_Svn基于mysql做登陆认证
  9. 中移动“屠龙”术一刀封喉 免费WAP祸福莫名 【时评】
  10. Window对象(1)