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

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

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

 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;
}

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 数数字油画你的颜料干了怎么办? 数字油画涂颜料涂错了怎么办 绝地求生模拟器注册已达上限怎么办 孕妇把番茄和虾一起吃了怎么办 4岁宝贝吃了玩具小电池怎么办 微信使用零钱需完善实名信息怎么办 两岁宝宝刷牙不会吐水怎么办 孩子牙龈上长了小牙怎么办 供暖公司未供暖却收取供暖费怎么办 两岁宝宝认知和语言能力低怎么办 蜡笔同步被对方发现删掉的怎么办 微信时间和手机时间不同步怎么办 孩子们家乡爱画美丽的也自己怎么办 娃把豆豆弄进鼻孔了怎么办 20岁了不知道自己该干什么怎么办 遇到一个新手买家恶意拍下怎么办 淘宝卖螃蟹有什么要求美工怎么办 淘宝衣服吊牌剪了想退货怎么办修 用图片在淘宝搜衣服搜不到怎么办 汽车黑塑料水砂纸磨的不平怎么办 sat报名要你填10位电话怎么办 手绘板连接电脑绘画有点迟钝怎么办 走路不小心滑了一下特尴尬怎么办 小孩子头撞了头发长不出来怎么办 小孩子头磕破了不长头发怎么办 晚上洗了冷水头早上头痛怎么办 头发洗了一天就油了怎么办 米诺地尔搽剂喷了头皮油怎么办 头发可以种植吗如果是秃顶怎么办 前额头发少怎么办如何使头发增多 头发又细又软又少怎么办 宝宝一岁了头发又少又黄怎么办 生完孩子头发掉的厉害怎么办 洗完头发后头发很蓬松怎么办 头发掉的厉害怎么办吃什么好得快 头发掉的很厉害怎么办吃什么好 我头发掉的厉害怎么办吃什么药 头发干枯毛躁掉发怎么办吃什么 最近洗头时头发掉的厉害怎么办 生完小孩头发掉的厉害怎么办 生完小孩后头发掉的厉害怎么办