数据结构--稀疏矩阵的快速转置及快速相乘操作

来源:互联网 发布:单片机按键输入 编辑:程序博客网 时间:2024/06/04 18:06

      大家好!这一篇要写的是稀疏矩阵的快速转置和快速相乘的操作,我们都知道,在稀疏矩阵中对零元素进行存储和算术运算没什么必要,所以我们要减小这两个操作的复杂度,比如矩阵相乘的传统的经典算法中:

 for(i=1;i<=M.行;++i)
   for(j=1;j<=N.列;++j)
   {
    Q[i][j]=0;
    for(k=1;k<=M.列;++k)
    Q[i][j]+=M[i][k]*N[k][j];
   } 

光是Q[i][j]+=M[i][k]*N[k][j];这一句就要M的行数*N的列数再乘以M的列数这样一个复杂度,所以我们有了以下的算法,在快速相乘中我会写比较多的注释方便大家理解,具体详细的说明请各位参考严的数据结构,下面有三个文件,一个是Matrix.h,一个是Matrix.c,最后一个是main.c

 

//Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <stdio.h>
#include <stdlib.h>
//#include <windows.h>

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
#define OVERFLOW    -2

#define MAXSIZE 7
#define MAXRC  7
#define ROW 4
#define COL 5

#define FORMAT "%3d"
#define TURNLINE printf("/n/n")

typedef int ElemType;
typedef int status;

typedef struct
{
int i,j;//行,列
ElemType e;//非零元素
}Triple;

typedef struct
{
 Triple data[MAXSIZE+1];//非零元三元组表,data[0]不用
 int mu,nu,tu;//矩阵的行数,列数及非零元个数
 int rpos[MAXRC+1];//用于行逻辑链接的顺序表,即事先知道非零元在矩阵中每一行的位置,方便两个矩阵的快速相乘
}Matrix;

void test();
status createMatrix(Matrix *);//创建一个矩阵,这里留成空函数让大家自由发挥(因为这不是讨论的重点),下面自会有测试数据。
void printMatrix(Matrix M,int size);//打印矩阵
status findPostion(Matrix *);//查找矩阵中非零元的位置
status fastTransMatrix(Matrix ,Matrix *);//快速倒置矩阵
status multMatrix(Matrix ,Matrix ,Matrix *);//实现两个矩阵的快速相乘


void implement();//用于快速倒置矩阵的测试数据
void another_implement();//用于快速矩阵相乘的测试数据

#endif

 

//Matrix.c

#include "Matrix.h"


void test()
{
  printf("step here...");
  TURNLINE;
}

status createMatrix(Matrix *M)
{

 return OK;
}


void printMatrix(Matrix M,int size)
{
 int index;
 printf("该矩阵的行数:%3d",M.mu);
 printf("/t列数:%3d",M.nu);
 printf("/t非零元的个数: %d",M.tu);
 TURNLINE;
 
 for(index=1;index<=size;++index)
 {
  printf(FORMAT,M.data[index].i);
  printf(FORMAT,M.data[index].j);
  printf(FORMAT,M.data[index].e);
  TURNLINE;
 }

}

status fastTransMatrix(Matrix M,Matrix *T)
{
 
 int num[MAXSIZE+1];//每列非零元的个数
 int cpot[MAXSIZE+1];//每列第一个非零元将在T中出现的位置
    int col,t,p,q;

    T->mu=M.nu;
 T->nu=M.mu;
 T->tu=M.tu;

 if(T->tu)
 {
  for(col=1;col<=M.nu;++col)
  {
   num[col]=0;
  }

  for(t=1;t<=M.tu;++t)
  {
   ++num[M.data[t].j]; //统计M中每列的非零元的个数
  }
  
  cpot[1]=1;
  for(col=2;col<=M.nu;++col)
  {
   cpot[col]=cpot[col-1]+num[col-1];
  }

  for(p=1;p<=M.tu;++p)
  {
   col=M.data[p].j;
   q=cpot[col];

   T->data[q].i=M.data[p].j;
   T->data[q].j=M.data[p].i;
   T->data[q].e=M.data[p].e;

            ++cpot[col];
  }
 }

 

 return OK;
}

status findPostion(Matrix *M)
{
 int row,*num;
 if(!M->tu) return ERROR;

 num=(int *)malloc(sizeof(M->tu+1));
  if(!num) return ERROR;

    for(row=1;row<=M->mu;++row)  num[row]=0;
 for(row=1;row<=M->tu;++row)  ++num[M->data[row].i];
 M->rpos[1]=1;
    for(row=2;row<=M->mu;++row)  M->rpos[row]=M->rpos[row-1]+num[row-1];

 free(*num);

 

 return OK;
}

status multMatrix(Matrix M,Matrix N,Matrix *Q)
{
  //传统的矩阵相乘算法
#if 0
 for(i=1;i<=M.行;++i)
  for(j=1;j<=N.列;++j)
  {
   Q[i][j]=0;
   for(k=1;k<=M.列;++k)
    Q[i][j]+=M[i][k]*N[k][j];
  }
#endif
  int Mrow,Nrow,pM,pN,*temp=NULL,t,tp,Qcol,i;
  int row;

  if(M.nu!=N.mu) return ERROR;

  Q->mu=M.mu;
  Q->nu=N.nu;
  Q->tu=0;

  if(M.tu*N.tu!=0)
  {
   temp=(int *)malloc(sizeof(N.nu+1));
    if(!temp) return ERROR;
            findPostion(&M);
   findPostion(&N);
           
   for(Mrow=1;Mrow<=M.mu;++Mrow)//通过处理M的每一行得到临时的Q的数据,因为相乘的结果不一定是非零元
   {
    for(i=1;i<=N.nu;++i) temp[i]=0;//用来临时存放Q的每一行里两列的累积和

             Q->rpos[Mrow]=Q->tu+1;//是不是似曾似???没错,它就是用来统计Q中每一行第一个非零元的位置

    if(Mrow<M.mu)  t=M.rpos[Mrow+1];//提取M中每一行里的每一个非零元
    else t=M.tu+1;

    for(pM=M.rpos[Mrow];pM<t;++pM)
             {
               Nrow=M.data[pM].j;//找到N中对应位置的非零元以便进行相乘
      if(Nrow<N.mu) tp=N.rpos[Nrow+1];//处理N中每一行中的每一个非零元
      else tp=N.tu+1;

      for(pN=N.rpos[Nrow];pN<tp;++pN)
      {
                 Qcol=N.data[pN].j;
     temp[Qcol]+=M.data[pM].e*N.data[pN].e ;
      }
    }
             for(Qcol=1;Qcol<=N.nu;++Qcol)
    {
     if(temp[Qcol])
     {
                   if(++Q->tu>MAXSIZE) return ERROR;
       Q->data[Q->tu].i=Mrow;
       Q->data[Q->tu].j=Qcol;
       Q->data[Q->tu].e=temp[Qcol];
     }

    }
   }
  }

  return OK;
}

void implement()//自己虚拟矩阵非零元素作测试
{
 Matrix M,N,T;

    M.mu=ROW;
    M.nu=COL;
    M.tu=7;

 M.data[1].i=1;
 M.data[1].j=2;
 M.data[1].e=3;

 M.data[2].i=1;
 M.data[2].j=5;
 M.data[2].e=-5;

 M.data[3].i=2;
 M.data[3].j=2;
 M.data[3].e=-1;

 M.data[4].i=3;
 M.data[4].j=1;
 M.data[4].e=6;

 M.data[5].i=3;
 M.data[5].j=4;
 M.data[5].e=8;

 M.data[6].i=4;
 M.data[6].j=1;
 M.data[6].e=-4;

 M.data[7].i=4;
 M.data[7].j=5;
 M.data[7].e=7;

 

    printMatrix(M,M.tu);

 fastTransMatrix(M,&T);
 printMatrix(T,T.tu);
}

void antother_implement()
{
    Matrix M,N,Q;


    M.mu=ROW;
    M.nu=COL;
    M.tu=7;

 M.data[1].i=1;
 M.data[1].j=2;
 M.data[1].e=3;

 M.data[2].i=1;
 M.data[2].j=5;
 M.data[2].e=-5;

 M.data[3].i=2;
 M.data[3].j=2;
 M.data[3].e=-1;

 M.data[4].i=3;
 M.data[4].j=1;
 M.data[4].e=6;

 M.data[5].i=3;
 M.data[5].j=4;
 M.data[5].e=8;

 M.data[6].i=4;
 M.data[6].j=1;
 M.data[6].e=-4;

 M.data[7].i=4;
 M.data[7].j=5;
 M.data[7].e=7;


 N.mu=5;
    N.nu=2;
    N.tu=5;

 N.data[1].i=1;
 N.data[1].j=2;
 N.data[1].e=3;

 N.data[2].i=2;
 N.data[2].j=1;
 N.data[2].e=2;

 N.data[3].i=2;
 N.data[3].j=2;
 N.data[3].e=4;

 N.data[4].i=3;
 N.data[4].j=1;
 N.data[4].e=1;

 N.data[5].i=5;
 N.data[5].j=2;
 N.data[5].e=-2;

    printMatrix(M,M.tu);
    printMatrix(N,N.tu);
 multMatrix(M,N,&Q);
 printMatrix(Q,Q.tu);

}

 


//main.c

//#include "Matrix.h"
//#include "Matrix.c"

int main()
{
 //implement();
 antother_implement();
     getchar();
 return 0;
}

 

原创粉丝点击