Bootstrap

西工大NOJ数据结构实验——实验2.3:稀疏矩阵加法,用十字链表实现C=A+B

关于这道题,需要注意一点,就是它的样例输入中的"?"是错误的,意思是说你完全可以不用去管这个问号,而如果你多此一举,把问号也给考虑进来了,那甭管你咋改,它永远都是WA。坑不坑??? 

这道题几乎和理论NOJ上的一道题一模一样,所以参考西工大NOJ数据结构理论——013.以十字链表为存储结构实现矩阵相加(严5.27)_没耳朵的Rabbit的博客-CSDN博客

即可,(直接复制粘贴这个,啥都不用改,直接就能AC

或者说,你把上一个实验的代码直接粘贴到这里也是可以的(哈哈好狡猾

西工大NOJ数据结构实验——2.2稀疏矩阵加法,实现C=A+B_没耳朵的Rabbit的博客-CSDN博客

好了,日常求赞啦,你们的支持是对我的最大鼓励!

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
typedef int ElemType;
typedef struct OLNode{
	int i,j;//行号和列号
	ElemType elem;
	struct OLNode *right;//右边元素 
	struct OLNode *down;//下边元素 
}OLNode,*OLink;

typedef struct CrossList{
	OLink* rHead;
	OLink* cHead;
	int mu,nu,tu;//行数、列数、非零元个数 
}CrossList;

CrossList* CreateOLSMatrix(int r,int c,int t){//创建目标十字链表的表头 
	CrossList* p=(CrossList*)malloc(sizeof(CrossList));
	if(p==NULL){
		printf("Out of space!");
	}
	p->mu=r;
	p->nu=c;
	p->tu=t;
	p->rHead=(OLink*)malloc((r+1)*sizeof(OLink));
	p->cHead=(OLink*)malloc((c+1)*sizeof(OLink));
	if(p->rHead==NULL||p->cHead==NULL) printf("Out of space!\n");
	for(int i=0;i<r+1;i++){
		p->rHead[i]=NULL;
	}//强迫症,初始化操作 
	for(int i=0;i<c+1;i++){
		p->cHead[i]=NULL;
	}//强迫症,初始化操作 
	return p;
}

void InsertMatrix(CrossList* p,int i,int j,int elem){//插入数据
	OLink p1=(OLink)malloc(sizeof(OLNode));
	if(p1==NULL) printf("Out of space!\n");
	p1->i=i;p1->j=j;p1->elem=elem;
	//创建并填充结点
	
	if(p->rHead[i]==NULL||p->rHead[i]->j>j){
		p1->right=p->rHead[i];
		p->rHead[i]=p1; 
	}else{
			OLink q=p->rHead[i];
			while(1){
				if(q->right==NULL||q->right->j>j) break;
				q=q->right;
			}//找到插入位置
			p1->right=q->right;
			q->right=p1;
		}//完成行插入
		
	if(p->cHead[j]==NULL||p->cHead[j]->i>i){
		p1->down=p->cHead[j];
		p->cHead[j]=p1;
	}else{
			OLink q=p->cHead[j];
			while(1){
				if(q->down==NULL||q->down->i>i) break;
				q=q->down;
			}//找到插入位置
			p1->down=q->down;
			q->down=p1; 
		}//完成列插入 
}

int BuildMatrix(CrossList* p){//完善表
	for(int k=1;k<=p->tu;k++){
		int i,j,elem;
		scanf("%d%d%d",&i,&j,&elem);
		InsertMatrix(p,i,j,elem);
	}
}

int OutputMatrix(CrossList* p){//输出表
	for(int i=1;i<=p->mu;i++){
		OLink q=p->rHead[i];
		for(int j=1;j<=p->nu;j++){
			if(q!=NULL&&j==q->j){
				printf("%d %d %d\n",q->i,q->j,q->elem);
				q=q->right;
			}
		}
	}//按照先行后列的顺序输出 
}

int AddMatrix(CrossList* p1,CrossList* p2,CrossList* p3){//矩阵相加得到新矩阵p3 
	for(int i=1;i<=p1->mu;i++){
		//先行后列,一点一点地来做 
		OLink temp1=p1->rHead[i];
		OLink temp2=p2->rHead[i];
		for(int j=1;j<=p1->nu;j++){
			int flag1=temp1!=NULL&&j==temp1->j;
			int flag2=temp2!=NULL&&j==temp2->j;
			//为什么我要用flag呢?因为都放在if后面的话,if会变的很长很长,超级麻烦 
			if(flag1==1&&flag2!=1){//如果这个位置上,p1有数据,p2没数据 
				InsertMatrix(p3,temp1->i,temp1->j,temp1->elem);
				temp1=temp1->right;
			}
			if(flag1!=1&&flag2==1){//如果这个位置上,p1没数据,p2有数据 
				InsertMatrix(p3,temp2->i,temp2->j,temp2->elem);
				temp2=temp2->right;
			}
			if(flag1==1&&flag2==1){//如果这个位置上,p1有数据,p2也有数据 
				int total=temp1->elem+temp2->elem;
				if(total==0){
					p3->tu=p3->tu-2;
					//如果p1的数据与p2的数据相加为0,那就不用插入
					//别忘了p3中非零元素要减2
				}else if(total!=0){
					InsertMatrix(p3,temp1->i,temp1->j,total);
					p3->tu--;
				}//如果相加和不为0,那么把和total插入。
				 //别忘了p3中非零元素要自减 
				temp1=temp1->right;
				temp2=temp2->right;
			}
		}
	}
}

int main(){
	//int r,c,t1;
	//scanf("%d%d%d",&r,&c,&t1);
	int r,c,t1,t2;
	scanf("%d%d%d%d",&r,&c,&t1,&t2);
	//输入行数、列数、两个矩阵的非零元个数 
	CrossList* p1=CreateOLSMatrix(r,c,t1);
	CrossList* p2=CreateOLSMatrix(r,c,t2);
	CrossList* p3=CreateOLSMatrix(r,c,t1+t2);
	//创建三个十字链表的表头
	//其中p3表示最终相加得到的十字链表 
	//p1+p2时,可能会有元素合并,或者合并之后结果为0之类的情况出现,导致p3中非零元素小于t1+t2
	//但是方便起见,还是记非零元素个数为t1+t2
	//要是真有元素合并,以及合并之后结果为0,那“非零元素-1”这一步到时候再做也不迟 
	BuildMatrix(p1);
	BuildMatrix(p2);
	AddMatrix(p1,p2,p3);
	OutputMatrix(p3);
	return 0;
}

;