一、前言
最近在捣鼓C++,学到线代的行列式之后就想着来捣鼓一下求行列式的值。主要原因是当时群里有人在捣鼓着用上下三角来求值,所以我最后就去玩定义法求值了。
二、n阶行列式的定义
从定义中我们可以看出值计算公式由三个部分组成:分别是逆序数r,行列式中n项的相乘并相加,以及全排列 j1 、j2 、j3......jn。
三、代码实现
1.首先我们先构架好基本框架:
#include <iostream>
#include <cmath>
using namespace std;
const int u = 10; //最大阶数限制
int main()
{
int finalanswer;
int arr[u][u];
cout << "请输入行列式的阶数" << endl;
cin >> n;
for (int i = 0; i < n; i++) //给行列式的每项进行赋值
{
cout << endl;
for (int h = 0; h < n; h++)
{
cout << "a" << i + 1 << h + 1 << " 的值:";
cin >> arr[i][h];
}
}
}
cmath的头文件是因为接下来的逆序数需要用到pow(或者你也可以用for循环?)
2.排列数
int a[u]; //需要进行排列的数的数组
for (i = 0; i < n; i++) //给排列赋值
{
a[i] = i + 1;
}
定义中的j1,j2,jn就是排列数,通过排列数来最后得出所需要相加的所有的项的值。
3.逆序数
int Reverse(int n, int a[]) //逆序数
{
int t = 0;
for (int i = 1; i < n; i++)
{
for (int h = 0; h < i; h++)
{
if (a[i]<a[h])
{
t = t + 1;
}
}
}
return t;
}
逆序数的算法比较简单,只需要用两层for检测某一位的数的前几位有多少数比他大即可。
4.求全排列
void Perm(int start, int end, int a[]) start=0 end为行列式阶数
{
if (start == end)
{
for (int j = 0; j < end; j++)
{
cout << a[j] << " ";
}
cout << endl;
}
for (int i = start; i < end; i++)
{
swap(a[start], a[i]);
Perm(start + 1, end, a);
swap(a[i], a[start]);
}
}
这是用递归法求全排列的一种方法,参考了这位大哥的方法: https://blog.csdn.net/hf19931101/article/details/79452799
其中start = 0,end就是行列式的阶数,也就是n。具体的解析可以看上面链接的。
5.计算行列式每个项的值
行列式最终的值是由几个项相加而成的,而那几个项则是由n个行列式中的元素相乘而得来的,而项中每项元素的列(行)下标则是1 2 3 ... n的某一种排列,而所有的项的列(行)下标就构成了1 2 3 ... n 的所有排列情况。
int Answer(int arr[u][u], int a[], int n, int t) //计算行列式的每项的值
{
int answer = 0;
int temp_answer = 1;
int t_2 = 0;
for (int i = 0; i < n; i++)
{
temp_answer = temp_answer * arr[i][a[i]-1];
}
t_2 = pow(-1, t);
answer = temp_answer * t_2;
return answer;
}
t 就是该项的各个元素的列(行)下标所对应的逆序数。temp_answer是该项中元素的累乘。t_2则是 - 1 的t次方。
6.所有项相加得出最终结果
我们定义一个Final_Answer来作为最终结果,并且将Answer函数和Perm函数以及Reverse相融合。
void Perm(int start, int end, int a[], int arr[10][10], int &Final_Answer)
{
if (start == end)
{
Final_Answer = Final_Answer + Answer(arr, a, end, Reverse(end, a));
return;
}
for (int i = start; i < end; i++)
{
swap(a[start], a[i]);
Perm(start + 1, end, a, arr, Final_Answer);
swap(a[i], a[start]);
}
}
Final_Answer的值是一个值传递,因此我们用&来进行引用(或者利用指针)。Reverse函数所在的位置就是Answer函数的 t ,也就是逆序数。最后再在main函数之中调用并cout一下即可。
Perm(0, n, a, arr, Final_Answer);
cout << "行列式的值为: " << Final_Answer << endl;
7.全部代码
#include <iostream>
#include <cmath>
using namespace std;
int Reverse(int n, int a[])
{
int t = 0;
for (int i = 1; i < n; i++)
{
for (int h = 0; h < i; h++)
{
if (a[i]<a[h])
{
t = t + 1;
}
}
}
return t;
}
int Answer(int arr[10][10], int a[], int n, int t)
{
int answer = 0;
int temp_answer = 1;
int t_2 = 0;
for (int i = 0; i < n; i++)
{
temp_answer = temp_answer * arr[i][a[i]-1];
}
t_2 = pow(-1, t);
answer = temp_answer * t_2;
return answer;
}
void Perm(int start, int end, int a[], int arr[10][10], int &Final_Answer)
{
if (start == end)
{
Final_Answer = Final_Answer + Answer(arr, a, end, Reverse(end, a));
return;
}
for (int i = start; i < end; i++)
{
swap(a[start], a[i]);
Perm(start + 1, end, a, arr, Final_Answer);
swap(a[i], a[start]);
}
}
int main()
{
int Final_Answer = 0;
int i, n, a[10];
int arr[10][10];
cout << "请输入行列式的阶数" << endl;
cin >> n;
for (i = 0; i < n; i++) //给排列赋值
{
a[i] = i + 1;
}
for (int i = 0; i < n; i++)
{
cout << endl;
for (int h = 0; h < n; h++)
{
cout << "a" << i + 1 << h + 1 << " 的值:";
cin >> arr[i][h];
}
}
Perm(0, n, a, arr, Final_Answer);
cout << "行列式的值为: " << Final_Answer << endl;
return 0;
}