稀疏矩阵三元存储下的计算器

又是一个实验题:三元数组存储稀疏矩阵,同时实现基本的加法,减法,乘法,求逆

             思路:

                         首先规范好输入情况

                         明确三元数组的数据结构和输入特征(   行优先输入 

                                                                                   )

                         

                          将稀疏矩阵建立成三元数组和三元数组转化输出

                          数组的加法,减法(

                                                         根据输入的行与列来判断是否可以进行 

                                                         最后的运算结果仍是稀疏矩阵 

                                                          输出结果为矩阵

                                                         )

   思路实现

       

                         明确三元数组的数据结构和输入特征(   行优先输入 

                                                                                   )

             

typedef struct 
{
    int row;
    int col;
    ElementType value;
}Triple;

typedef struct 
{
    Triple data[MAXSIZE];
    int rows,cols,nums;//非零起
}TSMatrix;

  

                          将稀疏矩阵建立成三元数组和三元数组转化输出

PtrTSMatrix CreatMatrix( void )
{

    int count = 0;
     PtrTSMatrix Matrix;
    Matrix  = ( PtrTSMatrix )malloc( sizeof( TSMatrix ) );
     if( Matrix == NULL )
     {
         printf("Not Space
 ");
         exit( 0 );
     }

     printf("输入行与列
");
     scanf("%d%d",&Matrix->rows,&Matrix->cols);

     printf("输入矩阵的元素的行,列,值( -1 结束 ,行优先)
");
     scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
     while( Matrix->data[count].row != -1 )
     {
         count++;
         scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
         if( Matrix->data[count].row < Matrix->data[count-1].row && Matrix->data[count].row!=-1 )
        {
            printf("未按行输出:
");
            getchar();
            exit(0);
        }//if
     }//while
    Matrix->nums = count;

     return Matrix;

}/* CreatMatrix */

/* print the matrix Matrix by using matrix */
void PrintMatrix( PtrTSMatrix Matrix )
{
      int i,j;
      int count = 0;
      
      for( i=0; i<Matrix->rows; i++ )
      {
          for( j=0; j<Matrix->cols; j++ )
          {
              if( count<Matrix->nums && i==Matrix->data[count].row-1 && j==Matrix->data[count].col-1 )
              {
                  printf("%2d",Matrix->data[count].value);
                  count++;
              }
              else
              {
                  printf("%2d",0);
              }//if-else
          }//for
          printf("
");
      }//for
}/* PrintMatrix */

PtrTSMatrix CreatMatrix( void )
{

    int count = 0;
     PtrTSMatrix Matrix;
    Matrix  = ( PtrTSMatrix )malloc( sizeof( TSMatrix ) );
     if( Matrix == NULL )
     {
         printf("Not Space
 ");
         exit( 0 );
     }

     printf("输入行与列
");
     scanf("%d%d",&Matrix->rows,&Matrix->cols);

     printf("输入矩阵的元素的行,列,值( -1 结束 ,行优先)
");
     scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
     while( Matrix->data[count].row != -1 )
     {
         count++;
         scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
         if( Matrix->data[count].row < Matrix->data[count-1].row && Matrix->data[count].row!=-1 )
        {
            printf("未按行输出:
");
            getchar();
            exit(0);
        }//if
     }//while
    Matrix->nums = count;

     return Matrix;

}/* CreatMatrix */

                          数组的加法,减法(

                                                         根据输入的行与列来判断是否可以进行 

                                                         最后的运算结果仍是稀疏矩阵 

                                                        )

     一般人最先想到的是两个for循环吧,那么算法的效率为 O( M *N ),我将算法稍稍改进了一下,优化到了 O(M+N ),具体思路如下

1 1
2 2 2
3 3 3

 x

 vaule
     

 类似上面那个三元组,在一个矩阵中想要确认位置需要x,y两个数据,实际上我可以把它回归到它在内存中存储得形式,即是线性存储,每一元素有唯一得一个对应值(假设矩阵为3×3),这样在就可以在一次循环中比较了

1 1
5 2
9 3
flag  vaule 
   

                       

              while( 没有一个三元组被遍历完 )

               {

                          if(俩个三元组位置相同)

                          {

                                 将两个三元组得位置信息和和传递给新的三元组

                                 两个三元组都向后移一位

                         }

                        elseif(  其中一个三元组的元素在另一个之前 )

                        {

                               将位于前面得元素的位置信息和值传给新得三元组

                               向后移一位

                          }

              } 

/* Plus A and B ,return C */
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
    int i=0,j=0;//标记追逐 A  B 
    PtrTSMatrix C;//存放和

   if( A->rows!=B->rows || A->cols!=B->cols )
   {
       return NULL;
   }
   
   C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
   C->rows = A->rows;
   C->cols = A->cols;
   C->nums = -1; //初始化
   
   while( i<A->nums && j<B->nums )
   {
       if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
       {
           if( A->data[i].value+B->data[j].value != 0 )
           {
             C->nums++;
             C->data[C->nums].col = A->data[i].col;
             C->data[C->nums].row = A->data[i].row;
             C->data[C->nums].value = A->data[i].value+B->data[j].value;
           }
           i++;
           j++;//标记后移
       }
       else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
       {
             C->nums++;
             C->data[C->nums].col = A->data[i].col;
             C->data[C->nums].row = A->data[i].row;
             C->data[C->nums].value = A->data[i].value;
             i++;
       }
       else
       {
             C->nums++;
             C->data[C->nums].col = B->data[j].col;
             C->data[C->nums].row = B->data[j].row;
             C->data[C->nums].value = B->data[j].value;
             j++;
       }//if-else

   }//while,

   if( i == A->nums )
   {
       while( j < B->nums )
       {
             C->nums++;
             C->data[C->nums].col = B->data[j].col;
             C->data[C->nums].row = B->data[j].row;
             C->data[C->nums].value = B->data[j].value;
             j++;
       }
   }
   else 
   {
       while( i < A->nums )
       {
             C->nums++;
             C->data[C->nums].col = A->data[i].col;
             C->data[C->nums].row = A->data[i].row;
             C->data[C->nums].value = A->data[i].value;
             i++;
       }
   }//if-else

   C->nums++;

   return C;
}//AddMatrix

    矩阵乘法的实现:

          原文链接  (详细的解释了原理和B矩阵的两个辅助矩阵构造,但对于算法的实现没有详讲)

         总得来说,在稀疏矩阵中,C=A乘B是对应行和对应列中非零值的事,例如在A 中  i  行中的第一个非零值 A[i][j],可以和它相乘的只有B的 j 行的非零值B[j][k],而且相乘结果还是放在C[i][k]中,这样把A中的非零值都与

       如果给你一张纸来计算A×B,你肯定会先是A的第一行和B的第一列相乘,放在C[0][0]的位置,之后是和B的第二列相乘,放在C[0][1]中,当B的列算到头后,再从A的第二行开始,是吧?但要让计算机对三元组这样操作显然不行,因为你很难确定B三元组的任意一列(当然你要转置,我自然不说什么)。

那么该怎么做呢? 

     A 0 1 0 1      B 1 0 0      C = ?            

        0 0 1 0         3 2 0

                                 0 1 0

                                 0 0 2                                        

 首先从A中取的第一个值,这个值是 [ 1 2 1 ]([]内的值分别表示其x,y,vaule),那么在整个乘法过程中能和这个值相乘的也只有B中的第二行的[ 2  1 3 ] ,[ 2 2 2]

并且是放在C的第一行中的不同列的。那么能这么干嘛

(1).从A三元组中按顺序取一值 [ x  y  z ],那么找到对应的B的y 

  

PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
	int i=0,j=0;//标记追逐 A  B 
	PtrTSMatrix C;//存放和

   if( A->rows!=B->rows || A->cols!=B->cols )
   {
	   return NULL;
   }
   
   C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
   C->rows = A->rows;
   C->cols = A->cols;
   C->nums = -1; //初始化
   
   while( i<A->nums && j<B->nums )
   {
	   if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
	   {
		   if( A->data[i].value+B->data[j].value != 0 )
		   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value+B->data[j].value;
		   }
		   i++;
		   j++;//标记后移
	   }
	   else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
	   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value;
             i++;
	   }
	   else
	   {
             C->nums++;
			 C->data[C->nums].col = B->data[j].col;
			 C->data[C->nums].row = B->data[j].row;
			 C->data[C->nums].value = B->data[j].value;
			 j++;
	   }//if-else

   }//while,

   if( i == A->nums )
   {
	   while( j < B->nums )
	   {
             C->nums++;
			 C->data[C->nums].col = B->data[j].col;
			 C->data[C->nums].row = B->data[j].row;
			 C->data[C->nums].value = B->data[j].value;
			 j++;
	   }
   }
   else 
   {
	   while( i < A->nums )
	   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value;
             i++;
	   }
   }//if-else

   C->nums++;

   return C;
}//AddMatrix

  下面是可直接编译运行的代码:

/*************************************************************************
	> File Name: Matrix.c
	> Author: zh
	> Mail: 574932286@qq.com 
	> Created Time: 2014年10月16日 星期四 13时37分05秒
	
	一: 完成稀疏矩阵的建立i
    二: 15:33 稀疏矩阵的加法
         10,16 8:30 继续实现
		 10.19 15:07 继续
    三: 10.20 00:44 稀疏矩阵得乘法	
 ************************************************************************/
#include<stdlib.h>
#include<stdio.h>
#define MAXSIZE 100
typedef int ElementType; 
typedef struct 
{
	int row;
	int col;
	ElementType value;
}Triple;

typedef struct 
{
	Triple data[MAXSIZE];
	int rows,cols,nums;//非零起
}TSMatrix;

typedef TSMatrix * PtrTSMatrix;

PtrTSMatrix CreatMatrix( void );
void PrintMatrix( PtrTSMatrix Matrix );
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B );
PtrTSMatrix MinusMatrix( PtrTSMatrix A, PtrTSMatrix B );
PtrTSMatrix MultiMatrix( PtrTSMatrix A, PtrTSMatrix B );
/* Make a Matrix,use the triple array */
PtrTSMatrix CreatMatrix( void )
{

    int count = 0;
     PtrTSMatrix Matrix;
    Matrix  = ( PtrTSMatrix )malloc( sizeof( TSMatrix ) );
	 if( Matrix == NULL )
     {
		 printf("Not Space
 ");
		 exit( 0 );
     }

     printf("输入行与列
");
	 scanf("%d%d",&Matrix->rows,&Matrix->cols);

	 printf("输入矩阵的元素的行,列,值( -1 结束 ,行优先)
");
     scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
	 while( Matrix->data[count].row != -1 )
	 {
         count++;
         scanf("%d%d%d",&Matrix->data[count].row,&Matrix->data[count].col,&Matrix->data[count].value);
		 if( Matrix->data[count].row < Matrix->data[count-1].row && Matrix->data[count].row!=-1 )
        {
			printf("未按行输出:
");
			getchar();
			exit(0);
		}//if
	 }//while
    Matrix->nums = count;

	 return Matrix;

}/* CreatMatrix */

/* print the matrix Matrix by using matrix */
void PrintMatrix( PtrTSMatrix Matrix )
{
      int i,j;
	  int count = 0;
      
	  for( i=0; i<Matrix->rows; i++ )
	  {
		  for( j=0; j<Matrix->cols; j++ )
		  {
			  if( count<Matrix->nums && i==Matrix->data[count].row-1 && j==Matrix->data[count].col-1 )
			  {
  				  printf("%2d",Matrix->data[count].value);
				  count++;
			  }
			  else
			  {
				  printf("%2d",0);
			  }//if-else
		  }//for
		  printf("
");
	  }//for
}/* PrintMatrix */


/* Plus A and B ,return C */
PtrTSMatrix AddMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
	int i=0,j=0;//标记追逐 A  B 
	PtrTSMatrix C;//存放和

   if( A->rows!=B->rows || A->cols!=B->cols )
   {
	   return NULL;
   }
   
   C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
   C->rows = A->rows;
   C->cols = A->cols;
   C->nums = -1; //初始化
   
   while( i<A->nums && j<B->nums )
   {
	   if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
	   {
		   if( A->data[i].value+B->data[j].value != 0 )
		   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value+B->data[j].value;
		   }
		   i++;
		   j++;//标记后移
	   }
	   else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
	   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value;
             i++;
	   }
	   else
	   {
             C->nums++;
			 C->data[C->nums].col = B->data[j].col;
			 C->data[C->nums].row = B->data[j].row;
			 C->data[C->nums].value = B->data[j].value;
			 j++;
	   }//if-else

   }//while,

   if( i == A->nums )
   {
	   while( j < B->nums )
	   {
             C->nums++;
			 C->data[C->nums].col = B->data[j].col;
			 C->data[C->nums].row = B->data[j].row;
			 C->data[C->nums].value = B->data[j].value;
			 j++;
	   }
   }
   else 
   {
	   while( i < A->nums )
	   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value;
             i++;
	   }
   }//if-else

   C->nums++;

   return C;
}//AddMatrix
/* A mius B get C */
PtrTSMatrix MinusMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
	int i=0,j=0;//标记追逐 A  B 
	PtrTSMatrix C;//存放和

   if( A->rows!=B->rows || A->cols!=B->cols )
   {
	   return NULL;
   }
   
   C = ( PtrTSMatrix )malloc(sizeof( TSMatrix ));
   C->rows = A->rows;
   C->cols = A->cols;
   C->nums = -1; //初始化
   
   while( i<A->nums && j<B->nums )
   {
	   if( A->data[i].row*A->cols+A->data[i].col == B->data[j].row*B->cols+B->data[j].col )
	   {
		   if( A->data[i].value-B->data[j].value != 0 )
		   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value-B->data[j].value;
		   }
		   i++;
		   j++;//标记后移
	   }
	   else if( A->data[i].row*A->cols+A->data[i].col < B->data[j].row*B->cols+B->data[j].col )
	   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value;
             i++;
	   }
	   else
	   {
             C->nums++;
			 C->data[C->nums].col = B->data[j].col;
			 C->data[C->nums].row = B->data[j].row;
			 C->data[C->nums].value = B->data[j].value;
			 j++;
	   }//if-else

   }//while,

   if( i == A->nums )
   {
	   while( j < B->nums )
	   {
             C->nums++;
			 C->data[C->nums].col = B->data[j].col;
			 C->data[C->nums].row = B->data[j].row;
			 C->data[C->nums].value = B->data[j].value;
			 j++;
	   }
   }
   else 
   {
	   while( i < A->nums )
	   {
             C->nums++;
			 C->data[C->nums].col = A->data[i].col;
			 C->data[C->nums].row = A->data[i].row;
			 C->data[C->nums].value = A->data[i].value;
             i++;
	   }
   }//if-else

   C->nums++;

   return C;
}/* MiinusMatrix */


/* get the answer of A multiply B */
PtrTSMatrix MultiMatrix( PtrTSMatrix A, PtrTSMatrix B )
{
	PtrTSMatrix C;
    int num[MAXSIZE]={0};//第K行得非零元素得个数
	int cpot[MAXSIZE]={0};//k行得第一个非零元素在三元组得位置
	int i,j;
	int count = 0;
    int temp[MAXSIZE]={0};

	if( A->cols != B->cols )
	{
       return NULL;
	}//if ,输入检验

	C = (PtrTSMatrix)malloc( sizeof(TSMatrix) );
	C->rows = A->rows;
	C->cols = B->cols;

	for( i=0; i<B->nums; i++)
	{
        num[B->data[i].row-1]++;//m
		if( i!=0 && B->data[i-1].row!=B->data[i].row )
		{
            cpot[B->data[i-1].row-1] = i;
		}
	}

    for( i=0; i<A->nums; i++ )
	{
		if( i!=0 && A->data[i].row != A->data[i-1].row )
		{
               
			   for( j=0; j < B->cols; j++ )
			   {
				   if( temp[j] != 0 )
				   {
                      C->data[count].row = A->data[i-1].row;
					  C->data[count].col = j+1;
					  C->data[count].value = temp[j];
                     count++;
				   }
			   }//for,赋值
			   
			   for( j=0; j<B->cols; j++ )
			   {
				   temp[j] = 0;
			   }//for,初始化

		}//if

		for( j=0; j<num[A->data[i].col]; j++)
		{
			temp[ B->data[ cpot[A->data[i].col]+j ].col ]  = + A->data[i].value*B->data[ cpot[A->data[i].col]+j ];//高度注意,自己写一下
		}//for

	}//for
	
	return C;


}//MultiMatrix
int main(void)
{
   PtrTSMatrix A,B,C,D,E;
   A = CreatMatrix();
   B = CreatMatrix();
  
   C = AddMatrix( A, B );
   D = MinusMatrix( A , B );
   E = MultiMatrix( A, B );
   printf("
");
   PrintMatrix( C );
   printf("
");
   PrintMatrix( D );
   printf("
");
   PrintMatrix( E );
   return 0;
}

  

 

               

原文地址:https://www.cnblogs.com/dilidingzhi/p/4028665.html