/*

算法没有做过什么改动,加上了内存释放的部分。

算法介绍

矩阵求逆在3D程序中很常见,主要应用于求Billboard矩阵。按照定义的计算方法乘法运算,严重影响了性能。在需要大量Billboard矩阵运算时,矩阵求逆的优化能极大提高性能。这里要介绍的矩阵求逆算法称为全选主元高斯-约旦法。

高斯-约旦法(全选主元)求逆的步骤如下:

首先,对于 k 从 0 到 n - 1 作如下几步:

从第 k 行、第 k 列开始的右下角子阵中选取绝对值最大的元素,并记住次元素所在的行号和列号,在通过行交换和列交换将它交换到主元素位置上。

这一步称为全选主元。

m(k, k) = 1 / m(k, k)

m(k, j) = m(k, j) * m(k, k),j = 0, 1, ..., n-1;j != k

m(i, j) = m(i, j) - m(i, k) * m(k, j),i, j = 0, 1, ..., n-1;i, j != k

m(i, k) = -m(i, k) * m(k, k),i = 0, 1, ..., n-1;i != k

最后,根据在全选主元过程中所记录的行、列交换的信息进行恢复,恢复的原则如下:在全选主元过程中,先交换的行(列)后进行恢复;

原来的行(列)交换用列(行)交换来恢复。

*/

#include   #include   #include   void   main(void)

{

int   n;

printf("请输入你所求解的逆矩阵的阶数:n=");

scanf("%d",&n);

float   choose_the_main(float   **a,float   *b,int   k,int   n);

void   input_output(float   **a,float   **c,float   **q,int   n);

void   course(float   **a,float   **c,float   **q,float   *b,int   n);

float   **a,*b,**c,**q;

int   i;

//没有free(),有内存泄露。

a=(float   **)malloc(sizeof(float   *)*n);

b=(float   *)malloc(sizeof(float   )*n);

c=(float   **)malloc(sizeof(float   *)*n);

q=(float   **)malloc(sizeof(float   *)*n);

for(i=0;i{

*(a+i)=(float   *)malloc(sizeof(float   )*n);

*(c+i)=(float   *)malloc(sizeof(float   )*n);

*(q+i)=(float   *)malloc(sizeof(float   )*n);

}

printf("您现在做的是%d阶矩阵的逆矩阵求解\n",n);

input_output(a,c,q,n);

course(a,c,q,b,n);

//释放内存

//ly-2009-10-31

for(i=0;i{

free(*(a+i));

*(a+i) = NULL;

free(*(c+i));

*(c+i) = NULL;

free(*(q+i));

*(q+i) = NULL;

}

free(*a);

free(b);

free(*c);

free(*q);

//

}

float   choose_the_main(float   **a,float   *b,int   k,int   n)

{

float   d,t;

int   l,i,j;

d=a[k-1][k-1];

l=k-1;

for(i=k;i{

if(fabs(a[i][k-1]>fabs(d)))

{

d=a[i][k-1];

l=i;

}

}

if(d==0)

printf("The   system   is   error!\n");

else

{

if(l!=k-1)

{

for(j=k-1;j{

t=a[l][j];

a[l][j]=a[k-1][j];

a[k-1][j]=t;

}

t=b[l];b[l]=b[k-1];b[k-1]=t;

}

}

return   (d);

}

/*a: 原始矩阵;c: 单位矩阵*/

void   input_output(float   **a,float   **c,float   **q,int   n)

{

int   i,j;

printf("请按行的顺序依次输入矩阵中元素的值(共%d项):",n*n);

for(i=0;i<=n-1;i++)

for(j=0;j<=n-1;j++)

scanf("%f",&a[i][j]);

for(i=0;ifor(j=0;j<=n-1;j++)

{

if(i==j)   c[i][j]=1;

else   c[i][j]=0;

q[i][j]=a[i][j];

}

printf("您输入的(AE)矩阵为(利用(AE)-->(E(A的逆)):\n");

for(i=0;i<=n-1;i++)

{

for(j=0;j<=n-1;j++)

printf("%.5f     ",a[i][j]);

for(j=0;j<=n-1;j++)

printf("%.5f     ",c[i][j]);

printf("\n");

}

printf("\n");

}

void   course(float   **a,float   **c,float   **q,float   *b,int   n)

{

float   sum=0,h;

int   i,j,k,p,flag=0;

for(p=0;p{

for(j=0;jb[j]=c[j][p];

for(i=0;ifor(j=0;j<=n-1;j++)

{

a[i][j]=q[i][j];

}

for(k=1;k<=n-1;k++)

{

h=choose_the_main(a,b,k,n);  //选主元

if(h==0)

{

printf("因为矩阵的行列式的值为0,所以不能用此程序做!程序退出!\n");

flag=1;

break;

}

else

{

for(i=k;ia[i][k-1]=a[i][k-1]/a[k-1][k-1];

for(i=k;ifor(j=k;ja[i][j]=a[i][j]-a[i][k-1]*a[k-1][j];

for(i=k;ib[i]=b[i]-(a[i][k-1]*b[k-1]);

}

}

if(flag==1)   break;

if(h!=0)

{

b[n-1]=b[n-1]/a[n-1][n-1];

for(i=n-2;i>=0;i--)

{

for(j=i+1;jsum=sum+a[i][j]*b[j];

b[i]=(b[i]-sum)/a[i][i];

sum=0;

}

for(j=0;jc[j][p]=b[j];

}

}

if(flag==0)

{

printf("所求矩阵的逆矩阵为:\n");

for(i=0;i<=n-1;i++)

{

for(j=0;j<=n-1;j++)

printf("%.5f     ",c[i][j]);

printf("\n");

}

}

}

//8888888888888888888888888888888888888888888888888888888888888888888

//传统方法:

//***************************

//求任何一个矩阵的逆矩阵

//ly-09-10-27:求逆的传统方法,通过求代数余子式

//***************************

#include #include

void main( void )

{

float *buffer,*p;  //定义数组首地址指针变量

short int row,num; //定义矩阵行数row及矩阵元素个数

short int i,j;

float determ;     //定义矩阵的行列式

float comput_D(float *p,short int n);     //求矩阵的行列式

float Creat_M(float *p, short int m,short int n,short int k); //求代数余子式

void Print( float *p,short int n);    //打印n×n的矩阵

printf("\nPlease input the number of rows: ");

scanf("%d",&row);

num=2 * row * row;

buffer = (float *)calloc(num, sizeof(float));    //分配内存单元

p=buffer;

if(p != NULL)

{

for(i=0;i{

printf("Input the number of %d row ",i+1);

for(j=0;j{

scanf("%f",p++);

}

}

}

else

printf( "Can't allocate memory\n" );

printf("\nThe original matrix is:\n");

Print(buffer,row);    //打印该矩阵

determ=comput_D(buffer,row);    //求整个矩阵的行列式

p=buffer + row * row;

if (determ != 0)

{

for (i=0;ifor (j=0; j*(p+j*row+i)=  Creat_M(buffer,i,j,row)/determ;

printf("The determinant is %G\n",determ);

p=buffer + row * row;

printf("\nThe inverse matrix is:\n");

Print(p,row);    //打印该矩阵

}

else

printf("The determnant is 0, and there is no inverse matrix !\n");

free( buffer );

}

//--------------------------------------------------------

//功能:求矩阵 n X n 的行列式

//入口参数:矩阵首地址 p;矩阵行数 n

//返回值:矩阵的行列式值

//--------------------------------------------------------

float comput_D(float *p,short int n)

{

short int i,j,m;        //i--row; j--column

short int lop=0;

float result=0;

float mid=1;

if (n!=1)

{

lop=(n==2)?1:n;    //控制求和循环次数,若为2阶,则循环1次,否则为n次

for(m=0;m{

mid=1;         //顺序求和

for(i=0,j=m;imid = mid * ( *(p+i*n+j%n) );

result+=mid;

}

for(m=0;m{

mid=1;         //逆序相减

for(i=0,j=n-1-m+n; imid=mid * ( *(p+i*n+j%n));

result-=mid;

}

}

else result=*p;

return(result);

}

//----------------------------------------------------

//功能:求k×k矩阵中元素A(mn)的代数余子式

//入口参数:k×k矩阵首地址;元素A的下标m,n; 矩阵行数 k

//返回值: k×k矩阵中元素A(mn)的代数余子式

//----------------------------------------------------

float Creat_M(float *p, short int m,short int n,short int k)

{

short int len;

short int i,j;

float mid_result=0;

short int quo=1;

float *p_creat,*p_mid;

len=(k-1)*(k-1);

p_creat = (float *)calloc(len, sizeof(float));    //分配内存单元

p_mid=p_creat;

for(i=0;ifor(j=0;j{

if (i!=m && j!=n)

*p_mid++ =* (p+i*k+j);

}

//    Print(p_creat,k-1);

quo = (m + n) %2==0 ? 1:-1;

mid_result = (float ) quo * comput_D(p_creat,k-1);

free(p_creat);

return(mid_result);

}

//-------------------------------------------

//功能:打印n×n的矩阵

//入口参数:n×n矩阵的首地址;该矩阵的行数 n

//返回值: 无

//-------------------------------------------

void Print( float *p,short int n)

{

int i,j;

for (i=0;i{

for (j=0; jprintf("%10G ",*p++);

printf("\n");

}

printf("--------------\n");

}

全选主元matlab,全选主元高斯-约当法实矩阵求逆及传统方法求逆相关推荐

  1. 高斯约当法矩阵求逆(Matlab实现)

    数学模型到具体算法仍有一段距离,需要考虑计算机执行速度和"四舍五入"等问题,这里主要利用矩阵的初等变换进行矩阵求逆,也就是高斯约当法,代码如下: 主函数:main.m %测试 A= ...

  2. 用高斯约当法求逆矩阵​​​​​​​​​​​​​​​​​​​​​A-1

    原矩阵:                   求. 用高斯约当法求逆矩阵. #include<iostream> #include<cstdio> #include<cs ...

  3. matlab 全1矩阵,matlab全为1的矩阵

    生成一个 m 行 n 列的零矩阵,m=n 时可简写为 zeros(n) 生成一个 m 行 n 列的元素全为 1 的矩阵, m=n 时可写为 ones(n) 生成一个主对角线全为 1 的 m 行 n 列 ...

  4. 部分选主元matlab,部分选主元的Doolittle分解 | 学步园

    步骤: 假设用紧凑格式的Doolittle法已经完成了第 r-1 (1<=r<=n) 步分解,第 r 步分解,首先在数组 A 的第 r 列主对角元以下(含主对角元) 选主元,具体步骤: 1 ...

  5. 全相位fft matlab,全相位FFT问题——全相位时移相位差法 请教!!!

    最近学习王兆华教授的全相位FFT方面的知识,对于全相位时移相位差法有点疑问,望高手们解答. 全相位时移相位差法的采样长度为3N-1,倘若将其分为三段:1~N.N+1~2N-1.2N~3N-1,来模拟一 ...

  6. 全维观测器matlab,全维状态观测器详解.ppt

    全维状态观测器 xp座机电话号码8 状态重构和状态观测器 状态重构即状态观测器的提出,主要是为了解决状态反馈在性能上的不可替代性和在物理上的不能实现性的矛盾. (1)不可替代性:先前各节中极点配置,镇 ...

  7. 高斯约当法求逆矩阵的算法实现(C++)

    #include"iostream.h" #include"math.h" void main() { float a[10][10],A[10][10],b[ ...

  8. 湘潭2017 ccpc中南地区邀请赛 Determinant 高斯约当求逆矩阵

    链接  http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1260 要求逆矩阵还是第一次见到 题意  给定一个n-1*n的矩阵, ...

  9. 矩阵求逆(全选主元高斯-约当消去法)

    矩阵求逆(实矩阵) 具体的C实现: #include "stdlib.h"#include "math.h"#include "stdio.h&quo ...

最新文章

  1. 火墙之firewalld
  2. 微信小程序modal自定义文本框
  3. SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图)
  4. jsp需要多少java基础_Java基础——JSP(一)
  5. uva 11178(几何)
  6. ASP.NET页生命周期介绍:阶段,事件及其他
  7. HDOJ(HDU) 2123 An easy problem(简单题...)
  8. _Linux中删除特殊名称文件的多种方式
  9. TOMCAT SSL 配置
  10. Servlet(四):转发与重定向、路径问题
  11. VS2019详细安装教程
  12. 【SequoiaDB|巨杉数据库】巨杉数据库快速入门
  13. 人工智能的数学基础------- 矩阵迹与相似矩阵的本质
  14. tinymce vue 部分工具不显示_vue项目中使用tinymce编辑器的步骤详解
  15. 在win7系统下使用TortoiseGit(乌龟git)简单操作Git@OSC
  16. eclipse上插入中文到mysql,但是navicat显示问号《网上很多方法都没用》,最终google到了精品
  17. excel如何拆分数据
  18. OTG 线结构原理及注意事项
  19. 折腾win7:保护眼睛,修改资源管理器背景颜色 xp适用
  20. inno setup怎么检测系统是否安装了vcredist_x86 exe

热门文章

  1. Excel - 表格设置数字下拉数值不变不递增
  2. uni-app 华为离线推送 Assist_HW: get hms token failed:6003: certificate fingerprint error
  3. 办理广东林业调查规划设计资质最新申报标准
  4. 微型计算机键盘连接在,树莓派推出Pi 400型微型计算机 主机藏在键盘里连接显示器即可使用...
  5. 互联网的“达尔文”式猜想
  6. Linux 环境保存【终端打印信息】到特定文件
  7. 云帆大数据学院_hadoop 2.2.0源码编译
  8. 批量转换用户的共存模式--Skype for Business to Teams
  9. 总线体现在硬件上就是计算机主板,计算机考试练习题
  10. POI在指定excel插入行java