# 三元组十字链表下稀疏矩阵的加、转、乘实现

#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
#include<process.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int ElemType;

//------------------------------------------------------------------------------------------------

struct OLNode
{
int i,j;                                           //非零元所在行、列
ElemType e;                                        //非零元值
OLNode *right,*down;                               //定义向右域和向下域
};

struct CrossList
{
int mu,nu,tu;                                      //矩阵的行、列和非零元个数
};

//------------------------------------------------------------------------------------------------

void Create(CrossList &M)                             //矩阵的创建
{
int i,j,k,m,n,t;
ElemType e;                                       //用于存放非零元值
OLNode *p,*q;
printf("Please input the rows 、columns and the values of the matrix：");
scanf("%d%d%d",&m,&n,&t);                         //输入稀疏矩阵的行、列、非零元
M.mu=m;                                           //把矩阵的总行数存入M.mu
M.nu=n;                                           //把矩阵的总列数存入M.nu
M.tu=t;                                           //把矩阵的非零元个数存入M.tu
exit(OVERFLOW);                               //退出程序，程序返回给操作系统的返回码是OVERFLOW
exit(OVERFLOW);                               //退出程序，程序返回给操作系统的返回码是OVERFLOW
for(k=1;k<=m;k++)                                 //初始化行头指针
for(k=1;k<=n;k++)                                 //初始化列头指针
for(k=0;k<t;k++)
{
scanf("%d%d%d",&i,&j,&e);                     //输入t个非零元的信息
if(i>m||j>n)                                  //假如输入的元素不在矩阵中
{
exit(OVERFLOW);                           //退出程序，程序返回给操作系统的返回码是OVERFLOW
}
else                                          //假如输入的元素在矩阵中
{
p=(OLNode*)malloc(sizeof(OLNode));        //为p分配一个结点大小的空间
if(!p)                                    //假如p不存在
exit(OVERFLOW);                       //退出程序，程序返回给操作系统的返回码是OVERFLOW
p->i=i;                                   //把非零元的行值赋给p->i
p->j=j;                                   //把非零元的列值赋给p->j
p->e=e;                                   //把非零元的值赋给p->e
{
//p插入该行第一节点处
}
else
{
//否则寻找行表插入位置
p->right=q->right;                    //p的右向域指向q的右向域
q->right=p;                           //p指向q的右向域
}                                         //完成行插入
{
//p插入该列第一节点处
}                                         //完成列插入
else
{
//否则寻找列表插入位置
p->down=q->down;                      //p的向下域指向q的向下域
q->down=p;                            //p指向q的向下域
}                                         //完成列插入
}
}
}

//------------------------------------------------------------------------------------------------

void Print(CrossList M)                               //矩阵的输出
{
int i,j,k;
int array[100][100];                              //定义二元数组array[100][100]
for(i=1;i<=M.mu;i++)                              //行循环
{
for(j=1;j<=M.nu;j++)                          //列循环
{
array[i][j]=0;                            //初始化数组所需部分
}
}
for(k=1;k<=M.nu;k++)                              //将所有非零元的值存入对应的数组中
{
while(p)
{
//将第k行的非零元存入数组中
array[p->i][p->j]=p->e;                   //将这个结点的非零元存入数组中
p=p->right;                               //p指向下一个向右域
}
}
for(i=1;i<=M.mu;i++)                              //行循环
{
for(j=1;j<=M.nu;j++)                          //列循环
{
if(j==M.nu)
cout<<array[i][j]<<endl;              //如果是行的最后一个结点则换行
else
cout<<array[i][j]<<" ";               //以矩阵的显示方式显示稀疏矩阵
}
}
}

//------------------------------------------------------------------------------------------------

void Add(CrossList M,CrossList N,CrossList &Q)  //矩阵M和矩阵N相加并存入矩阵Q
{
int i,k;
if(M.mu!=N.mu||M.nu!=N.nu)                 //如果两个矩阵不是同类型的
{
printf("The two matrixes is not of the same type!/n");
exit(OVERFLOW);                        //退出程序，程序返回给操作系统的返回码是OVERFLOW
}
//对Q进行初始化
Q.mu=M.mu;                                 //矩阵Q的总行数和矩阵M的总数相同
Q.nu=M.nu;                                 //矩阵Q的总列数和矩阵M的总数相同
Q.tu=0;                                    //将矩阵Q的非零元个数初始化为零
exit(OVERFLOW);                        //退出程序，程序返回给操作系统的返回码是OVERFLOW
exit(OVERFLOW);                        //退出程序，程序返回给操作系统的返回码是OVERFLOW
for(k=1;k<=Q.mu;k++)                       //初始化行
for(k=1;k<=Q.nu;k++)                       //初始化列
if(!col)                                   //如果分配空间成功
exit(OVERFLOW);                        //退出程序，程序返回给操作系统的返回码是OVERFLOW
for(k=1;k<=Q.nu;k++)                       //赋初始值
col[k]=NULL;
for(i=1;i<=M.mu;i++)                       //按行序相加
{
while(pm&&pn)                          //如果pm和pn都存在
{
if(pm->j<pn->j)                    //矩阵M当前结点的列小于矩阵N当前结点的列
{
//生成Q的结点
if(!p)                         //如果分配空间不成功
exit(OVERFLOW);            //退出程序，程序返回给操作系统的返回码是OVERFLOW
Q.tu++;                        //矩阵Q的非零元个数加1
p->i=i;                        //把非零元的行赋给p->i
p->j=pm->j;                    //把矩阵M中当前结点列的值赋给p->j
p->e=pm->e;                    //把矩阵M中当前结点的元素值赋给p->e
p->right=NULL;                 //p的向右域为空
pm=pm->right;                  //pm右移
}
else if(pm->j>pn->j)               //矩阵M当前结点的列大于矩阵N当前结点的列
{
if(!p)                          //如果分配空间不成功
exit(OVERFLOW);             //退出程序，程序返回给操作系统的返回码是OVERFLOW
Q.tu++;                         //矩阵Q的非零元个数加1
p->i=i;                         //把矩阵当前非零元的行赋给p->i
p->j=pn->j;                     //把矩阵N中当前结点列的值赋给p->j
p->e=pn->e;                     //把矩阵N中当前结点的元素值赋给p->e
p->right=NULL;                  //p的向右域为空
pn=pn->right;                   //pn右移
}
else if(pm->e+pn->e)                //M,N当前结点的列相同并且两元素之和非零
{
if(!p)                          //如果分配空间不成功
exit(OVERFLOW);             //退出程序，程序返回给操作系统的返回码是OVERFLOW
Q.tu++;                         //矩阵Q的非零元个数加1
p->i=i;                         //把矩阵当前非零元的行赋给p->i
p->j=pn->j;                     //把矩阵当前非零元的列赋给p->j
p->e=pm->e+pn->e;               //把矩阵M当前非零元的值和矩阵N当前非零元的值相加赋给p->e
p->right=NULL;                  //p的向右域为空
pm=pm->right;                   //pm右移
pn=pn->right;                   //pn右移
}
else                                //两元素相加为零
{
pm=pm->right;                   //pm右移
pn=pn->right;                   //pn右移
continue;                       //不执行下面的程序，回到循环
}
else                                //如果当前的头结点不为空
{
pq->right=p;                    //pq的向右域指向p
pq=pq->right;                   //pq指向pq的向右域
}                                   //完成行插入
else
{
//如果当前结点不为空，则插入p结点
col[p->j]->down=p;
col[p->j]=col[p->j]->down;
}
}
while(pm)                               //如果矩阵M中的结点还没有插完，将矩阵M该行的剩余元素插入矩阵Q
{
if(!p)
exit(OVERFLOW);
Q.tu++;                             //矩阵非零元个数加1
p->i=i;                             //把当前结点的行、列、和值插入p中
p->j=pm->j;
p->e=pm->e;
p->right=NULL;                      //p的向右域为空
pm=pm->right;                       //pm右移
else                                //如果当前行头结点不为空，插入p结点
{
pq->right=p;
pq=pq->right;
}
else                                //如果当前列头结点不为空，插入p结点
{
col[p->j]->down=p;
col[p->j]=col[p->j]->down;
}
}
while(pn)                               //如果矩阵N中的结点还没有插完，将矩阵N该行的剩余元素插入矩阵Q
{
if(!p)
exit(OVERFLOW);
Q.tu++;                             //矩阵非零元个数加1
p->i=i;                             //把当前结点的行、列、和值插入p中
p->j=pn->j;
p->e=pn->e;
p->right=NULL;                      //p的向右域为空
pn=pn->right;                       //pn右移
else                                //如果当前行头结点不为空，插入p结点
{
pq->right=p;
pq=pq->right;
}
else                                //如果当前列头结点不为空，插入p结点
{
col[p->j]->down=p;
col[p->j]=col[p->j]->down;
}
}
}
for(k=1;k<=Q.nu;k++)                        //使得每一列的最后一个结点的向下域为空
if(col[k])
col[k]->down=NULL;
free(col);                              //释放col的空间
}

//------------------------------------------------------------------------------------------------

void Trans(CrossList M,CrossList &N)            //将矩阵M转置到矩阵N中
{
int i,j;
N.mu=M.mu;                                  //将矩阵M中的行、列和非零元值赋给矩阵N
N.nu=M.nu;
N.tu=M.tu;
for(i=1;i<=N.mu;i++)                        //对矩阵N的行进行初始化
for(j=1;j<=N.nu;j++)                        //对矩阵N的列进行初始化
for(i=1;i<=M.mu;i++)
{
{
p->i=s->j;                          //将扫描到的结点中的数据进行转置后存到结点p中
p->j=s->i;
p->e=s->e;
{
}
else
{
p->right=q->right;
q->right=p;
}
{
}
else
{
for(q=N.chead[p->j];q->down && q->down->i < p->i; q=q->down);//扫描当前列，直到扫描到的结点的行值大于要插入的结点的行值，则把p结点插入到这个结点的后面
p->down=q->down;
q->down=p;
}
}
}
}

//------------------------------------------------------------------------------------------------

void Mult(CrossList M,CrossList N,CrossList &Q)//把矩阵M和矩阵N相乘并存入到矩阵Q中
{
int i,j,e;
if(M.nu!=N.mu)                             //如果矩阵M的总列数不等于矩阵N的总行数，则不能矩阵相乘
{
printf("The matrix what you input is error!/n");
exit(OVERFLOW);
}
else                                       //如果矩阵M的总列数等于矩阵N的总行数
{
Q.mu=M.mu;                             //把矩阵M的总行数赋给Q.mu
Q.nu=N.nu;                             //把矩阵N的总列数赋给Q.nu
Q.tu=0;                                //矩阵Q的非零元个数置为零
exit(OVERFLOW);
exit(OVERFLOW);
for(i=1;i<=Q.mu;i++)                   //初始化行
for(i=1;i<=Q.nu;i++)                   //初始化列
for(i=1;i<=Q.mu;i++)
for(j=1;j<=Q.nu;j++)
{
e=0;                            //定义变量e的值为0
while(p0&&q0)                   //当矩阵M和矩阵N的当前结点都存在时
{
if(q0->i<p0->j)             //如果q0当前所在行小于p0当前所在列，q0下移
q0=q0->down;
else if(q0->i>p0->j)        //如果q0当前所在行大于p0当前所在列，p0右移
p0=p0->right;
else
{
e=e+p0->e*q0->e;        //乘积累加
q0=q0->down;            //行列后移
p0=p0->right;
}
}
if(e)                           //e不为零则插入Q
{
Q.tu++;                     //矩阵Q的非零元个数加1
if(!q)
exit(OVERFLOW);
q->i=i;                     //把当前元素的行、列和值赋给结点q
q->j=j;
q->e=e;
q->right=NULL;              //结点q的向右域为空
q->down=NULL;               //结点q的向下域为空
else                        //否则将q中的数据赋给q1的向右域，并将q1右移
q1=q1->right=q;
else
{
while(q2->down)         //如果q2的向下域存在
q2=q2->down;        //q2下移
q2->down=q;             //把当前要插入的结点q插入到结点q2的后面
}
}
}
}
}

//------------------------------------------------------------------------------------------------

void main()
{
CrossList A,B,C;                               //声明三个矩阵
int Select;                                    //用来表示所要选择的序号
cout<<"*****************************************************************************"<<endl;
cout<<"******************************"<<"请选择你需要的操作"<<"*****************************"<<endl;
printf("/t/t/t<1>.Press 1 to add the array;/n");
printf("/t/t/t<2>.Press 2 to trans the array;/n");
printf("/t/t/t<3>.Press 3 to multiply the array;/n");
cout<<"*****************************************************************************"<<endl;
{
switch(Select)
{
case 1 :                                    //稀疏矩阵相加
{
Create(A);                          //创建矩阵A
Create(B);                          //创建矩阵B
cout<<"The array A is:"<<endl;
Print(A);                           //输出矩阵A
Print(B);                           //输出矩阵B
cout<<"The result is:"<<endl;
Print(C);                           //输出矩阵C
break;
}
case 2 ://稀疏矩阵转置
{
Create(A);                          //创建矩阵A
Create(B);                          //创建矩阵B
cout<<"The array A is:"<<endl;
Print(A);                           //输出矩阵A
cout<<"Trans to B:"<<endl;
Trans(A,B);                         //将矩阵A转置到矩阵B中
cout<<"The result is:"<<endl;
Print(B);                           //输出矩阵B
break;
}
case 3 :                                     //稀疏矩阵相乘
{
Create(A);                           //创建矩阵A
Create(B);                           //创建矩阵B
cout<<"The array A is:"<<endl;
Print(A);                            //输出矩阵A
cout<<"To multiply array B:"<<endl;
Print(B);                            //输出矩阵B
Mult(A,B,C);                         //把矩阵A和矩阵B相乘所得的矩阵存入矩阵C中
cout<<"The result is:"<<endl;
Print(C);                            //输出矩阵C
break;
}
}
}
}
/*
2 2 3
1 1 1
1 2 4
2 2 3

2 2 2
1 1 2
2 2 33
*/

• 本文已收录于以下专栏：

举报原因： 您举报文章：三元组十字链表下稀疏矩阵的加、转、乘实现 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)