递归方法计算行列式
1.功能介绍
主要功能为求算n阶行列式的值,理论上,n没有限制。
采用的数学方法为:不断进行拉普拉斯展开,直至化为二阶行列式。
代码行数:功能代码约100行左右。
2.编码过程分析
- 首先编码求取二阶行列式的函数
- 编码求取三阶行列式的函数
此时要复用求取二阶行列式的函数
将三阶行列式进行展开 - 将求二阶与三阶合并到一个函数中
通过条件控制语句进行划分
此时实现了最简单的递归情况 - 将二阶三阶的情况扩展到n阶
3.源码
#include<stdio.h>
#include<math.h> //pow求子式符号
#include<stdlib.h> //动态内存分配
float *InputMatrix (int n);
float CalculateSecondDimension(float *matrix);
float CalculateMatrix(float *matrix,int n);
void GetSubmatrix(float *matrix,float *submatrix,int n,int neglect_line);
void PrintMatrix(float *matrix,int n);
int main()
{
float *matrix=NULL;
float result;
int line_number;
printf("Please enter matrix size n(1<=n<20):");
scanf("%d",&line_number);
matrix=InputMatrix(line_number);
PrintMatrix(matrix,line_number);
result=CalculateMatrix(matrix,line_number);
printf("result = %f\n",result);
free(matrix);
return 0;
}
/*功能:创建并输入所求行列式
参数:行列式的行数
返回值:指向该行列式第一个元素的指针
*/
float *InputMatrix (int n)
{
int i,j;
float *matrix;
matrix=(float *)calloc(n*n,sizeof(float));
printf("Please input matrix line by line:\n");
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%f",&matrix[i*n+j]);
}
}
return matrix;
}
/*功能:输出一个行列式的所有元素
参数:指向该行列式第一个元素的指针matrix
行列式行数n
*/
void PrintMatrix(float *matrix,int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%6.1f\t",matrix[i*n+j]);
}
printf("\n");
}
}
/*功能:计算行列式matrix的值
参数:指向行列式第一个元素的指针matrix,行列式行数n
返回值:行列式matrix的值
主要方法:递归,拉普拉斯展开
*/
float CalculateMatrix(float *matrix,int n)
{
int i;
float sum=0;
float submatrix_value;
if(n==2)
{
return matrix[0]*matrix[3]-matrix[1]*matrix[2];
}
else
{
for(i=0; i<n; i++)
{
float *submatrix=NULL;
submatrix=(float *)calloc((n-1)*(n-1),sizeof(float));
GetSubmatrix(matrix,submatrix,n,i);
submatrix_value=CalculateMatrix(submatrix,n-1);
free(submatrix);
sum=sum+powf(-1,i)*matrix[i]*submatrix_value;
}
return sum;
}
}
/*功能:求行列式的一个子式(去掉第0行和第neglect_line列)
参数:指向原行列式第一个元素的指针matrix
指向子式第一个元素的指针submatrix
需要去掉的那一列neglect_line
*/
void GetSubmatrix(float *matrix,float *submatrix,int n,int neglect_line)
{
int i,j,k;
for(i=0;i<n-1;i++)
{
for(j=0,k=0;j<n-1;k++)
{
if(k!=neglect_line)
{
submatrix[i*(n-1)+j]=matrix[(i+1)*n+k];
j++;
}
}
}
}
4.处理细节
- 数据结构:
存储行列式使用的是指针类型,而不是数组类型
优点:方便作为参数在各个函数间进行传递
下面详细解释:
一想到行列式,我们会认为用数组储存更直观,更好理解
在实现三阶行列式的计算时,用二维数组没有问题
但是当扩展到高阶时
随之而来的有两个问题:- 因为我们使用的方法是拉普拉斯展开
就必须要求一个高阶行列式的子式
当我们存储这个子式时,想继续使用数组类型就变得很困难
困难首先表现在对数组的创建上
众所周知,C语言中对数组进行创建时,元素个数必须为常量
而子式的行数并不确定
其必定是由一个未知数,所以无法完成数组的创建 - 同理的,在函数对二维数组(一维数组就没有这个问题)进行参数传递时,列数量也必须为常数,即a[ ][N]
而N同问题1,也应该为变量
- 因为我们使用的方法是拉普拉斯展开
5.不足之处
- 频繁地进行动态内存的分配来对行列式及其子式进行储存
是否会产生对内存的大量占用,
或者常见的因内存问题而产生的安全问题?