/* 数据结构分析与学习专栏
* Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
* All rights reserved.
* 作 者: 高祥
* 完成日期: 2015 年 4 月 11 日
* 版 本 号:016
*任务描述:针对稀疏矩阵,实现6个基本操作
* 1:建立稀疏矩阵 ;
* 2:输出稀疏矩阵 ;
* 3:转置稀疏矩阵 ;
* 4:稀疏矩阵相加 ;
* 5:稀疏矩阵相减;
* 6:稀疏矩阵相乘 ;
*主要函数:
* 1.void InitMatrix(Matrix &M);//初始化矩阵
* 2.void InsertElem(Link &newnode,Matrix &M);//将已有的非零元素结点插入到矩阵中
* 3.void DeleteElem(Matrix &M,Link &deletenode,int row,int line);//删除在(row,line)处的结点
* 4.void CreateMatrix(Matrix &M);//创建矩阵
* 5.void Output(Matrix M);//输出矩阵
* 6.void TransposeMatrix(Matrix &M);//转置矩阵
* 7.void AddMatrix(Matrix &M,Matrix &N);//矩阵相加
* 8.void SubtractMatrix(Matrix &M,Matrix &N);//矩阵相减
* 9.void MultiplyMatrix(Matrix &M,Matrix &N);//矩阵相乘
*/
#include
#include
#include
using namespace std;
#define OK 1
#define FALSE 0
typedef int Status;
typedef int ElemType;
typedef struct node
{
int row;//非零元素的行数
int line;//非零元素的列数
ElemType elem;//非零元素的大小
struct node *right;//同一行的链接
struct node *down;//同一列的链接
} Node,*Link;
typedef struct
{
Link *rowhead;//所有行链表表头的指针数组
Link *linehead;//所有列链表表头的指针数组
int rownum;//矩阵的总行数
int linenum;//矩阵的总列数
int elemnum;//矩阵的非零元素总数
} Matrix;
void InitMatrix(Matrix &M);//初始化矩阵
void InsertElem(Link &newnode,Matrix &M);//将已有的非零元素结点插入到矩阵中
void DeleteElem(Matrix &M,Link &deletenode,int row,int line);//删除在(row,line)处的结点
void CreateMatrix(Matrix &M);//创建矩阵
void Output(Matrix M);//输出矩阵
void TransposeMatrix(Matrix &M);//转置矩阵
void AddMatrix(Matrix &M,Matrix &N);//矩阵相加
void SubtractMatrix(Matrix &M,Matrix &N);//矩阵相减
void MultiplyMatrix(Matrix &M,Matrix &N);//矩阵相乘
void Interaction();//输出操作
int main()
{
Interaction();
Matrix M,N;
int operate;
while(cin>>operate)
{
switch(operate)
{
case 0:
return 0;
case 1:
cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
cin>>M.rownum>>M.linenum>>M.elemnum;
CreateMatrix(M);
break;
case 2:
Output(M);
break;
case 3:
TransposeMatrix(M);
break;
case 4:
INPUT1:
cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
cin>>N.rownum>>N.linenum>>N.elemnum;
if(M.rownum!=N.rownum||M.linenum!=N.linenum)
{
cout<<"矩阵相加的前提是两个矩阵的行数列数分别相等。请创建合法的矩阵。\n";
goto INPUT1;
}
CreateMatrix(N);
AddMatrix(M,N);
break;
case 5:
INPUT2:
cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
cin>>N.rownum>>N.linenum>>N.elemnum;
if(M.rownum!=N.rownum||M.linenum!=N.linenum)
{
cout<<"矩阵相减的前提是两个矩阵的行数列数分别相等。请创建合法的矩阵。\n";
goto INPUT2;
}
CreateMatrix(N);
SubtractMatrix(M,N);
break;
case 6:
INPUT3:
cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
cin>>N.rownum>>N.linenum>>N.elemnum;
if(M.linenum!=N.rownum)
{
cout<<"矩阵相乘的前提是矩阵1的列数等于矩阵2的行数。请创建合法的矩阵。\n";
goto INPUT3;
}
CreateMatrix(N);
MultiplyMatrix(M,N);
break;
default:
cout<<"请输入正确的操作数字!\n";
}
}
return 0;
}
void InitMatrix(Matrix &M)//初始化矩阵
{
M.rowhead=(Link *)malloc((M.rownum+1)*sizeof(Link));//为每行的行链表分配一个指向该链表的指针
M.linehead=(Link *)malloc((M.linenum+1)*sizeof(Link));//为每列的列链表分配一个指向该链表的指针
//未填充元素,所有链表均为空,置空两个指针数组
for(int index=1; index<=M.rownum; index++)
{
M.rowhead[index]=NULL;
}
for(int index=1; index<=M.linenum; index++)
{
M.linehead[index]=NULL;
}
}
void InsertElem(Link &newnode,Matrix &M)//将已有的非零元素结点插入到矩阵中
{
//插入到对应的行链表中:讨论插在头结点还是后续的结点
Link rowcur=M.rowhead[newnode->row];
if(rowcur==NULL||rowcur->line>newnode->line)//若行链表为空或者已有的头结点的列数较大,插在头结点
{
newnode->right=rowcur;
M.rowhead[newnode->row]=newnode;
}
else//否则插在非头结点处
{
//找应该插的结点位置的前一个结点:
for(; !(rowcur->lineline&&(rowcur->right==NULL||rowcur->right->line>newnode->line)); rowcur=rowcur->right);
//找到并插入
newnode->right=rowcur->right;
rowcur->right=newnode;
}
//列链表的插入原理同上
Link linecur=M.linehead[newnode->line];
if(linecur==NULL||linecur->row>newnode->row)
{
newnode->down=linecur;
M.linehead[newnode->line]=newnode;
}
else
{
for(; !(linecur->rowrow&&(linecur->down==NULL||linecur->down->row>newnode->row)); linecur=linecur->down);
newnode->down=linecur->down;
linecur->down=newnode;
}
}
void DeleteElem(Matrix &M,Link &deletenode,int row,int line)
{
//首先更新行链表的链接:讨论该节点是否为该行链表的头结点
if(deletenode==M.rowhead[row])
{
M.rowhead[row]=deletenode->right;
}
else
{
Link prenode=M.rowhead[row];
while(prenode->right!=deletenode)
{
prenode=prenode->right;
}
prenode->right=deletenode->right;
}
//然后更新列链表的链接:讨论该节点是否为该列链表的头结点
if(deletenode==M.linehead[line])
{
M.linehead[line]=deletenode->down;
}
else
{
Link prenode=M.linehead[line];
while(prenode->down!=deletenode)
{
prenode=prenode->down;
}
prenode->down=deletenode->down;
}
Link temp=deletenode->right;//预存下一个结点
free(deletenode);//释放该结点的内存
deletenode=temp;
}
void CreateMatrix(Matrix &M)//创建矩阵
{
InitMatrix(M);//首先初始化矩阵
cout<<"请输入"<>newnode->row>>newnode->line>>newnode->elem;//生成新节点
InsertElem(newnode,M);//调用插入函数
}
cout<<"创建的稀疏矩阵为:\n";
Output(M);
}
void Output(Matrix M)//输出矩阵
{
for(int row=1; row<=M.rownum; row++)
{
Link cur=M.rowhead[row];
for(int line=1; line<=M.linenum; line++)
{
if(cur&&cur->line==line)
{
cout<elem;
cur=cur->right;
}
else
{
cout<right;//预存后一个结点
swap(cur1->row,cur1->line);
swap(cur1->right,cur1->down);
cur1=cur2;
}
}
swap(M.rownum,M.linenum);//交换矩阵的行列数
swap(M.rowhead,M.linehead);//交换矩阵的行列链表的指针数组
cout<<"转置后的矩阵是:\n";
Output(M);
}
void AddMatrix(Matrix &M,Matrix &N)//矩阵相加
{
for(int row=1; row<=M.rownum; row++)
{
Link cur1=M.rowhead[row];
Link cur2=N.rowhead[row];
for(int line=1; line<=M.linenum; line++)
{
//对应位置的非零元素存在情况共四种:
//当M有且N也有时:将运算结果赋给M,若结果为0,则删除M对应的结点,注意必须更新链接
if(cur1&&cur1->line==line&&cur2&&cur2->line==line)
{
cur1->elem=cur1->elem+cur2->elem;
if(cur1->elem!=0)
{
cur1=cur1->right;
}
else//删除M的结点
{
M.elemnum--;
DeleteElem(M,cur1,row,line);
}
Link temp=cur2->right;
free(cur2);//N的运算后的结点已没有存在的意义,释放其内存
cur2=temp;
}
//当M没有N有时:将N的结点插入到M中
if((cur1==NULL||cur1->line!=line)&&cur2&&cur2->line==line)
{
M.elemnum++;
Link temp=cur2->right;
InsertElem(cur2,M);//调用插入结点函数
cur2=temp;
}
//当M有N没有时:只需要右移M的指针
if(cur1&&cur1->line==line&&(cur2==NULL||cur2->line!=line))
{
cur1=cur1->right;
}
//当M、N都没有时,无需考虑。
}
}
cout<<"相加后的矩阵是:\n";
Output(M);
}
void SubtractMatrix(Matrix &M,Matrix &N)//矩阵相减
{
//基本同矩阵相加的算法
for(int row=1; row<=M.rownum; row++)
{
Link cur1=M.rowhead[row];
Link cur2=N.rowhead[row];
for(int line=1; line<=M.linenum; line++)
{
if(cur1&&cur1->line==line&&cur2&&cur2->line==line)
{
cur1->elem=cur1->elem-cur2->elem;
if(cur1->elem!=0)
{
cur1=cur1->right;
}
else
{
M.elemnum--;
DeleteElem(M,cur1,row,line);
}
Link temp=cur2->right;
free(cur2);
cur2=temp;
}
if((cur1==NULL||cur1->line!=line)&&cur2&&cur2->line==line)
{
M.elemnum++;
cur2->elem=-cur2->elem;
Link temp=cur2->right;
InsertElem(cur2,M);
cur2=temp;
}
if(cur1&&cur1->line==line&&(cur2==NULL||cur2->line!=line))
{
cur1=cur1->right;
}
}
}
cout<<"相减后的矩阵是:\n";
Output(M);
}
void MultiplyMatrix(Matrix &M,Matrix &N)
{
Matrix Q;//结果矩阵
Q.rownum=M.rownum;
Q.linenum=N.linenum;
Q.elemnum=0;
InitMatrix(Q);//初始化矩阵
int cnt=0;//计数矩阵中非零元素的个数
//遍历行数列数:
for(int row=1; row<=Q.rownum; row++)
{
for(int line=1; line<=Q.linenum; line++)
{
ElemType elem=0;
Link cur1=M.rowhead[row];
Link cur2=N.linehead[line];
//做到求每个元素时,M的一行元素和N的一列元素只遍历一遍
for(; cur1; cur1=cur1->right)
{
for(; cur2&&cur2->row<=cur1->line; cur2=cur2->down)
{
if(cur2->row==cur1->line)
{
elem=elem+cur1->elem*cur2->elem;
break;
}
}
}
if(elem)
{
cnt++;//计数器加1
Link newnode=(Link )malloc(sizeof(Node));
newnode->row=row;
newnode->line=line;
newnode->elem=elem;
InsertElem(newnode,Q);//插入新结点
}
}
}
Q.elemnum=cnt;
M=Q;
cout<<"相乘后的稀疏矩阵为:\n";
Output(M);
}
void Interaction()//输出操作
{
cout<<"请输入对应操作的序号:\n";
cout<<"0:退出程序 ;\n";
cout<<"1:建立稀疏矩阵 ;\n";
cout<<"2:输出稀疏矩阵 ;\n";
cout<<"3:转置稀疏矩阵 ;\n";
cout<<"4:稀疏矩阵相加 ;\n";
cout<<"5:稀疏矩阵相减;\n";
cout<<"6:稀疏矩阵相乘 ;\n";
}