稀疏矩阵运算器


         哎,搞了两周,烦人的数据结构课设终于搞完了。。。。。

老师要求用带行逻辑信息的三元组,加减乘,转制还好说,拿三元组搞还行,可求逆就不行了,没办法,搞了两种求逆的方法。一种是通过求伴随矩阵来搞另一种就是通过与单位矩阵结合,基本变换来求。不说了,把这几天的劳动成果附上。



/***********************建了个matrix.h头文件*************************/
#ifndef MATRIX_H_INCLUDED// 调用时需加stdio.h 和stdlib.h
#define MATRIX_H_INCLUDED
const int maxn = 1e3+100;
typedef double datatype ;
typedef struct node
{
	int i, j;
	datatype  val;
} node;
typedef struct spmartix
 {
	node data[maxn];
	int H[maxn];  //第i行起始位置
	int mu, nu, tu;  //稀疏矩阵行和列
} spmatrix;
typedef struct matrix
{
    datatype S[maxn][maxn];
    int row , col;
}matrix;
matrix *minit()
{
    matrix *M = ( matrix *) malloc ( sizeof(matrix));
    memset( M->S, 0, sizeof(M->S) );
    M->row=0;
    M->col=0;
    return M;
}
spmatrix *init()
{
	spmatrix *A = ( spmatrix * )malloc( sizeof ( spmatrix ) );
	memset(A->H,-1,sizeof(A->H));
	A->mu = 0;
	A->nu = 0;
	A->tu = 0;
	return A;
}
void create( spmatrix *A )
{
	printf( "是否文件输入 ?  y:文件输入 n:手动输入   ");
	char ans[20];

	scanf("%s",ans);
	if( ans[0] == 'y' || ans[0] == 'Y' )
	{

		FILE *fp;
		printf("请输入文件名: ");
		char file_name[100];
		scanf( "%s", file_name );
		fp = fopen( file_name, "r" );
		if( !fp )
		{
			printf( " 打开文件失败\n" );
			return ;
		}
		else
		{
			int num = 0;
			fscanf( fp,"%d%d", &A->mu,&A->nu);
			while( !feof(fp) )
			{
				fscanf(fp,"%d%d%lf",  &A->data[num].i,  &A->data[num].j,  &A->data[num].val);
				if( num == 0 || A->data[num].i != A->data[num-1].i )
				{
				    A->H[A->data[num].i] = num;
				}
				num++;
			}
			A->tu = num;
		}
		fclose( fp );
		return ;
	}
	else
	{
        printf( "请输入行和列:  " );
		scanf( "%d%d" , &A->mu, &A->nu );
		printf("请输入非零元素的个数:  ");
		scanf( "%d" , &A->tu);
		int num = 0;
		int i, j;
		int last=0,b;
		for( i = 0; i < A->tu ;i++)
		{
		    scanf( "%d%d%lf", &A->data[i].i, &A->data[i].j, &A->data[i].val );
		    if( i == 0 || A->data[i].i != A->data[i-1].i )
				{
				    A->H[A->data[i].i] = i;
				}

		}
	}
}
void print( spmatrix *A )
{
	int i,j,k;
	int num = 0 ;
	if( A->mu == 0 && A->nu == 0)
	{
		printf(" 处理失败\n");
		return ;
	}
	for( i = 1; i <=A->mu ; i++ )
	{
		for( j = 1 ; j <= A->nu ; j++)
		{
			if( j != 1) printf(" ");
			if( num != A->tu && i == A->data[num].i && j == A->data[num].j)
            {
                printf( "%5.0lf", A->data[num].val);
                num++;
            }
			else putchar( '0' );
		}
		printf("\n");
	}
}
void display(matrix *A)
{
    for( int i = 1; i <= A->row ; i++ )
    {
        for(int j = 1; j <= A->col ; j++)
        {
            if( j != 1)
            {
                printf(" ");
            }
            printf("%5.2lf",A->S[i][j]);
        }
        printf("\n");
    }
}
spmatrix *union_1( spmatrix *A ,spmatrix *B, int c )
{
	if( A->mu != B->mu || A->nu != B->nu )
	{
		printf( "处理失败\n" );
		return NULL;
	}
	spmatrix *C=init();
	int num = 0;
	int a, b;
	int i, j;
	a = 0;
	b = 0;
	while( a < A->tu && b < B->tu )
	{
		if( A->data[a].i == B->data[b].i && A->data[a].j == B->data[b].j )
		{
			if(	A->data[a].val + B->data[b].val *c != 0 )
			{
				 C->data[num].i = A->data[a].i;
				 C->data[num].j = A->data[a].j;
				 C->data[num++].val = A->data[a].val + B->data[b].val * c;
			}
			a++;
			b++;
		}
		else if( A->data[a].i == B->data[b].i )
		{
			if( A -> data[a].j < B->data[b].j )
			{
				C->data[num].i = A->data[a].i;
				C->data[num].j = A->data[a].j;
				C->data[num++].val = A->data[a].val;
				a++;
			}
			else
			{
                C->data[num].i = B->data[b].i;
				C->data[num].j = B->data[b].j ;
				C->data[num++].val = B->data[b].val * c;
				b++;
			}
		}
		else if( A->data[a].i < B->data[b].i )
		{
                C->data[num].i = A->data[a].i;
				C->data[num].j = A->data[a].j;
				C->data[num++].val = A->data[a].val;
				a++;
		}
		else if( A->data[a].i > B->data[b].i )
		{
                C->data[num].i = B->data[b].i;
				C->data[num].j = B->data[b].j;
				C->data[num++].val = B->data[b].val *c ;
				b++;
		}
	}
	while( a < A->tu )
	{
	    C->data[num].i = A->data[a].i;
        C->data[num].j = A->data[a].j;
        C->data[num++].val = A->data[a].val;
        a++;
	}
	while( b < B->tu )
	{
	    C->data[num].i = B->data[b].i;
        C->data[num].j = B->data[b].j;
        C->data[num++].val = B->data[b].val *c ;
        b++;
	}
	C->mu = A->mu ;
	C->nu = A->nu ;
	C->tu = num ;
	return C;
}
spmatrix *add( spmatrix *A, spmatrix *B )
{
	return union_1( A, B, 1 );
}
spmatrix *sub( spmatrix *A, spmatrix *B )
{
	return union_1( A, B, -1 );
}
spmatrix *zhuanzhi(spmatrix *A)
{
    spmatrix *B=init();
    int i,j;
    int num=0;
    for(i=1;i<=A->nu;i++)
    {
        for(j=1;j<=A->mu;j++)
        {
            if(A->H[j]!=-1&&A->data[A->H[j]].j==i)
            {
                int a=A->H[j];
                B->data[num].i=i;
                B->data[num].j=j;
                B->data[num].val=A->data[a].val;
                if(B->H[i]==-1)
                B->H[i]=num;
                num++;
                if(A->data[a+1].i==j)
                A->H[j]++;
                else A->H[j]=-1;
            }
        }
    }
    B->tu=num;
    B->mu=A->nu;
    B->nu=A->mu;
    return B;
}
spmatrix *mult(spmatrix *M,spmatrix *N)
{
	spmatrix *Q=init();
	Q->mu = M->mu;
	Q->nu = N->nu;
    spmatrix *B=zhuanzhi(N);
    free(N);
    N=B;
    if(M->nu!=B->nu)
    {
        printf("当前矩阵不能相乘\n");
        return NULL;
    }
    int i,j,num=0;
    for(i=1;i<=M->mu;i++)
    {
        int a=M->H[i];
        if(a==-1)
        continue;
        int last=1;
        int b=a;
        datatype sum=0;
        for(j=0;j<B->tu;j++)
        {
            if(b!=-1&&last==B->data[j].i)
            {
                while(b<M->tu&&M->data[b].i==i&&M->data[b].j<B->data[j].j)
                b++;
                if(b>M->tu||M->data[b].i>i)
                b=-1;
                if(b!=-1&&M->data[b].j==B->data[j].j)
                sum+=M->data[b].val*B->data[j].val;
            }
            else
            {
                if(sum!=0)
                {
                    Q->data[num].i=i;
                    Q->data[num].j=last;
                    Q->data[num].val=sum;
                    num++;
                }
                last=B->data[j].i;
                b=a;
                sum=0;
                j--;
            }
        }
        if(sum!=0)
        {
            Q->data[num].i=i;
            Q->data[num].j=last;
            Q->data[num].val=sum;
            num++;
        }

    }
    Q->tu=num;
    free(B);
    return Q;
}
matrix *transport( spmartix *A)
{
    matrix *B=minit();
    B->row = A->mu;
    B->col = A->nu;
    for( int i = 0 ; i < A-> tu ; i++ )
        B->S[A->data[i].i][A->data[i].j]=A->data[i].val;
    return B;
}
matrix *yuzi(int p,int q,matrix *A)
{
	int c, d,i,j;
	matrix *B=minit();
	for(c=1;c<A->row;c++)
	{
		for(d=1;d<A->col;d++)
		{
			if(c<p&&d<q)
				{B->S[c][d]=A->S[c][d];}
			else if(c<p&&d>=q)
				{B->S[c][d]=A->S[c][d+1];}
			else if(c>=p&&d<q)
				{B->S[c][d]=A->S[c+1][d];}
			else
				{B->S[c][d]=A->S[c+1][d+1];}
		}
	}
	B->row=A->row-1;
	B->col=A->col-1;
	return B;
}//求第p行,第q列所在元素的余子式
datatype zhi( matrix *A)
{
    int i,j,k;
    datatype ans=1.0;

    for( i = 1;i <= A->row; i++)
    {
        if(A->S[i][i]==0)
        {
            for(j=i+1;j<=A->row;i++)
            {
                if(A->S[j][i])
                break;
            }
            if( j > A->row)
            return 0;
            for(k=i;k<=A->col;k++)
            {
                int t=A->S[i][k];
                A->S[i][k]=A->S[j][k];
                A->S[j][k]=t;
            }
            if( j-i%2==1)
            ans*=-1;
        }
        for(j=i+1;j<=A->row;j++)
        {
            if(A->S[j][i]==0)
            continue;
            for(k=A->col;k>=i;k--)
            {
                A->S[j][k]-=A->S[j][i]/A->S[i][i]*A->S[i][k];
            }
        }
        ans*=A->S[i][i];

    }
    return ans;

}//行列式的值
datatype mo(matrix *A)
{
	if(A->row!=A->col)
    {
        printf("该行列式无法求值\n");
        exit(0);
    }
	else
		return (zhi(A));
}//矩阵的模
matrix *bansui(matrix *A)
{
	int p, q, x;
	matrix *B=minit();
	for(p=1;p<=A->row;p++)
	{
		for(q=1;q<=A->col;q++)
			{
			    if((p+q)%2==0) x=1;
			    else x=-1;
			    B->S[p][q]=x*mo(yuzi(q,p,A));
			}
	}
	B->row=A->row;
	B->col=A->col;
	return B;
}//求伴随矩阵
matrix *ni(matrix *A)
{
	int p, q;
	matrix *B=minit();
	matrix *C=minit();
	datatype a;
	a=mo(A);
	if(a==0)
		{printf("该矩阵的模为零,没有逆矩阵\n");exit(0);}
	else
	{
		B=bansui(A);
		for(p=1;p<=B->row;p++)
		{
			for(q=1;q<=B->col;q++)
			{
				C->S[p][q]=B->S[p][q]/a;
			}
		}
		C->row=B->row;
		C->col=B->col;
	}
	return C;
}
*/
//求逆矩阵

/*
spmatrix *zhuanzhi(spmatrix *A)
{
    spmatrix *B=init();
    int i,j;
    int num=0;
    for(i=1;i<=A->nu;i++)
    {
        for(j=1;j<=A->mu;j++)
        {
            if(A->H[j]!=-1&&A->data[A->H[j]].j==i)
            {
                int a=A->H[j];
                B->data[num].i=i;
                B->data[num].j=j;
                B->data[num].val=A->data[a].val;
                if(B->H[i]==-1)
                B->H[i]=num;
                num++;
                if(A->data[a+1].i==j)
                A->H[j]++;
                else A->H[j]=-1;
            }
        }
    }
    B->tu=num;
    B->mu=A->nu;
    B->nu=A->mu;
    return B;
}*/
matrix *inversion( spmatrix *A)
{
    matrix *C = minit();
    int i,j,k;
    C->row = A->mu;
    C->col = A->nu * 2;
    for( i = 0 ; i < A->tu; i++ )
    {
        C->S[A->data[i].i][A->data[i].j] = A->data[i].val;
    }
    for( i = 1; i <= A->mu; i++ )
    {
        C->S[i][A->nu+i] = 1;
    }
    for( i = 1; i <= A->mu; i++ )
    {
        if(C->S[i][i] == 0 )
        {
            for( j=i+1; j<= A->mu ; j++ )
            {
                if( C->S[j][i] != 0 )
                {
                    break;
                }
            }
            if( j > A->mu )
            {
                printf(" 无逆\n");
                return NULL;
            }
            for( k = 0; k <= C->col ; k++ )
            {
                int t;
                t = C->S[i][k];
                C->S[i][k] = C->S[j][k];
                C->S[j][k] = t;
            }
        }

        for( j = C->col; j >=i; j-- )
        {
            C->S[i][j] /= C->S[i][i];
        }
        for( j = 1; j <= C->row;j++)
        {
            if( j == i )
            continue;
            if( C->S[j][i] != 0)
            {
                for( k = C->col; k >= i; k-- )
                {
                    C->S[j][k] = C->S[j][k] - C->S[i][k]*C->S[j][i];
                }
            }
        }
    }
    for( i = 1; i <= C->row; i++ )
    {
        for( j = 1; j <= C->row ; j++ )
        {
            C->S[i][j] = C->S[i][j+C->row];
        }
    }
    C->col /= 2;
    return C;

}
#endif // MATRIX_H_INCLUDED
//主函数
<pre name="code" class="cpp">#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "matrix.h"
int menu_start(int a)
{
    int i,j;
    if( a == 0 )
    printf( "\n\t\t\t\t\t\t  欢迎使用矩阵计算器\n\n" );
    printf("*");
    for( i = 0; i < 117; i++ )
    printf("-");
    printf("*\n");
    printf("|\t\t\t\t\t\t\t功能\t\t\t\t\t\t\t\t      |\n");
    for( j = 0 ; j < 2 ; j++ )
    {
        printf("|");
        for( i = 0; i < 117; i++ )
            printf(" ");
        printf("|\n");
    }
    printf("|\t\t\t\t\t操作  #1:                -----------------矩阵加法\t\t\t\t      |\n");
    printf("|\t\t\t\t\t操作  #2:                -----------------矩阵减法\t\t\t\t      |\n");
    printf("|\t\t\t\t\t操作  #3:                -----------------矩阵乘法\t\t\t\t      |\n");
    printf("|\t\t\t\t\t操作  #4:                -----------------矩阵求逆\t\t\t\t      |\n");
    printf("|\t\t\t\t\t操作  #5:                -----------------矩阵转置\t\t\t\t      |\n");
    printf("|\t\t\t\t\t操作  #6:                -----------------行列式值\t\t\t\t      |\n");
    printf("|\t\t\t\t\t操作  #7:                -----------------退出\t\t\t\t\t      |\n");
    printf("|");
    for( i = 0; i < 117; i++ )
    printf(" ");
    printf("|\n");
    printf("*");
    for( i = 0; i < 117; i++ )
    printf("-");
    printf("*\n\n\n\n\n");
    printf("\t\t\t\t\t请输入所需操作序号 :    ");
    int b;
    scanf( "%d" ,&b);
    return b;
}
int main()
{
    int a;
    a = menu_start(0);
    while( a != 7 )
    {
        system( "CLS" );
        printf( " 请输入一个矩阵 \n");
        spmatrix *A = init() ;
        create ( A );
        system( "CLS" );
        switch ( a )
        {
            case 1 :
            {
                printf(" 请输入另一个矩阵 \n");
                spmatrix *B= init();
                create ( B );
                system( "CLS" );
                spmatrix *C = add( A, B);
                free(B);
                if(!C)
                break;
                printf("两矩阵和为\n");
                print ( C );
                free ( C );
                break;
            }
            case 2 :
            {
                printf(" 请输入另一个矩阵 \n");
                spmatrix *B= init();
                create ( B );
                system("PAUSE");
                system( "CLS" );
                spmatrix *C = sub( A, B);
                free(B);
                if(!C)
                break;
                printf(" 两矩阵差为\n" );
                print ( C );
                free(C);

                break;
            }
            case 3 :
            {

                printf(" 请输入另一个矩阵 \n");
                spmatrix *B= init();
                create ( B );
                system( "CLS" );
                spmatrix *C = mult( A, B);
                if(!C)
                break;
                printf(" 两矩阵相乘为\n" );
                print ( C );
                free(C);
                break;
            }
            case 4 :
            {

                matrix *B= transport(A);
                if(!B)
                break;
                matrix *C = ni(B);
                if(!C)
                break;
                printf(" 该矩阵求逆为\n" );
                printf("FIRST :\n");
                display(C);
                free(C);
                C=inversion(A);
                if(!C)
                break;
                printf("SECOND :\n");
                display(C);
                free(B);
                free(C);
                break;
            }
            case 5 :
            {
               spmatrix *C=zhuanzhi(A);
               if(!C)
               break;
                printf(" 该矩阵转置为\n" );
                print(C);
                free(C);
                break;
            }
            case 6 :
            {
                matrix *B= transport(A);
                if(!B)
                {
                    break;
                }
                int b=0;

                datatype ans=mo(B,b);
                if(b==0)
                printf(" 该矩阵行列式值为:  %8.2lf\n",ans );
                free(B);
                break;
            }
        }
        free(A);
        system( "PAUSE") ;
        system( "CLS" );
        a = menu_start ( 1 );
    }
    system( "CLS" );
    printf("\n\n\n\n\t\t\t\t\t\tBYE-BYE\n\n\n\n\n");
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值