Chinaunix首页 | 论坛 | 博客
  • 博客访问: 66324
  • 博文数量: 19
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 165
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-13 16:29
文章分类

全部博文(19)

文章存档

2010年(9)

2009年(10)

我的朋友

分类:

2009-10-31 11:47:48

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

算法介绍
 矩阵求逆在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;i   for(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;j   b[j]=c[j][p]; 
  for(i=0;i   for(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;i      a[i][k-1]=a[i][k-1]/a[k-1][k-1]; 
     for(i=k;i      for(j=k;j       a[i][j]=a[i][j]-a[i][k-1]*a[k-1][j]; 
      for(i=k;i       b[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;j      sum=sum+a[i][j]*b[j]; 
     b[i]=(b[i]-sum)/a[i][i]; 
     sum=0; 
    } 
    for(j=0;j     c[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;i            for (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;i                mid = mid * ( *(p+i*n+j%n) );
            result+=mid;
        }
  
        for(m=0;m        {                      
            mid=1;         //逆序相减
            for(i=0,j=n-1-m+n; i                mid=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;i        for(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; j            printf("%10G ",*p++);
        printf("\n");
    }
    printf("--------------\n");
}
阅读(2238) | 评论(0) | 转发(0) |
0

上一篇:移动ip白皮书

下一篇:C语言中的内存控制

给主人留下些什么吧!~~