西北工业大学NOJ数据结构—013以十字链表为储存结构实现矩阵相加

这个题......一句话都不想说......万恶的十字链表......搞死我了.......直接上代码.......猝

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

typedef struct OL
{    //定义带有“右”“下”的结构体
	int i,j;
	int ele;
	struct OL *right,*down;
}OL,*olink;

typedef struct
{    //定义各行各列的头指针结构体
	olink *rhead,*chead;
	int mu,nu,tu;
}cross,*cr;

void init(cross *M)
{//初始化头指针
	M->rhead=M->chead=NULL;
	M->mu=M->nu=M->tu=0;
}

void creat(cross *M,int m,int n,int t)
{//输入各项数值创建一个十字链表
	int i,j,k,e;
	olink p,q;
	M->mu=m;
	M->nu=n;
	M->tu=t;
	M->rhead=(olink*)malloc(sizeof(olink)*(m+1));
	M->chead=(olink*)malloc(sizeof(olink)*(n+1));//申请行和列的头指针数组
	for(k=1;k<=m;k++)
		M->rhead[k]=NULL;
	for(k=1;k<=n;k++)
		M->chead[k]=NULL;//把各行各列的头指针都指向NULL
	for(k=0;k<t;k++){//输入t组元素作为十字链表储存的稀疏矩阵
		scanf("%d%d%d",&i,&j,&e);
		p=(olink)malloc(sizeof(OL));
		p->i=i;
		p->j=j;
		p->ele=e;
		if(M->rhead[i]==NULL||M->rhead[i]->j>j)
		{ //如果输入数据所在的这一行的头指针为NULL,或者头指针所在的列大于要输入的元素的列
			p->right=M->rhead[i];
			M->rhead[i]=p;//就直接把这一行的头指针改为输入的元素
		}
		else
		{ //不然就依此查找该把次元素插在此行的哪一个位置
			for(q=M->rhead[i];(q->right)&&q->right->j<j;q=q->right);
			p->right=q->right;
			q->right=p;
		}
		p->down=NULL;
		if(M->chead[j]==NULL||M->chead[j]->i>i)
		{ //列的插入与行类似,如果此列为空或者要插入的元素的行小于本来的头
			p->down=M->chead[j];
			M->chead[j]=p;
		}
		else
		{
			for(q=M->chead[j];(q->down)&&q->down->i<i;q=q->down);
			p->down=q->down;
			q->down=p;
		}
		p->right=NULL;
	}
}

void insert(cross &M,olink &p)//选择将B中的每个元素依此插入A
{
	int i=p->i,j=p->j;
	int de=0,pl=0;//定义两个变量作为指示
	if(M.rhead[i]==NULL)//先将此元素块插入A的行链表
	{
		M.rhead[i]=p;//如果A此行没有元素就直接插入
		M.tu++;
	}
	else
	{
		olink q=M.rhead[i];
		olink pre = q;
		while(q&&(q->j<p->j))//用两个指针找到该元素块应该插到那个位置
		{
			pre=q;
			q=q->right;
		}
		if(q!=NULL&&(q->j==p->j))//如果要插入的A中位置恰好有元素
		{
			q->ele+=p->ele;
			if(q->ele==0)//若果AB相应元素加在一起为0,就把A中的这个元素块从链表中删除
			{
				if(pre==q)
					M.rhead[i]=q->right;
				else
					pre->right=q->right;
				M.tu--;
				de=1;
			}
			else
				pl=1;
		}
		if(de==0&&pl==0)//如果在A中没找到与P元素位置相同的元素块
		{
			if(pre==q)
			{
				M.rhead[i]=p;//此种情况直接插在头
				p->right=q;
			}
			else
			{
				pre->right=p;//此种情况插在之前找到的合适位置
				p->right=q;
			}
			M.tu++;
		}
	}
	if(M.chead[j]==NULL)
		M.chead[j]=p;//列的插入与行类似
	else{
		olink q = M.chead[j];
		olink pre=q;			
		while(q&&(q->i<p->i))
		{
			pre=q;
			q=q->down;
		}
		if(de==1)
		{
			if(q!=NULL)
			{
				if(pre==q)
					M.chead[j]=q->down;
				else
					pre->down=q->down;
				free(q);
				free(p);//如果AB对应元素相加为0,将这个元素从链表中删除后再free掉
				return ;
			}
		}
		if(pl==0)
		{
			if(pre==q)
			{
				M.chead[j]=p;
				p->down=q;
			}
			else
			{
				pre->down=p;
				p->down=q;
			}
		}
	}
}

void add(cross &M,cross &N)
{//将N矩阵加到M上
	olink p,q;
	p=(olink)malloc(sizeof(OL));
	int k=1;
	for(;k<=N.mu;k++)
	{
		p=N.rhead[k];
		while(p)//依此找出N中的每个元素插入M中
		{
			q=(olink)malloc(sizeof(OL));
            q->down = p->down;  
            q->right = p->right;  
            q->ele = p->ele;  
            q->i = p->i;  
            q->j = p->j;//因为将P插入后N中原来的元素会变化,所以另设一个保存原有数据
			//printf("out");
			insert(M,q);
			p=p->right;
		}
	}
}

void show(cross &M)
{//按照先行后列的顺序额依此输出一个以十字链表为春村结构的稀疏矩阵
	int k=1,t=1;
	for(k=1;k<=M.mu;k++)
	{
		olink P=M.rhead[k];
		for(t=1;t<=M.nu;t++)
		{
			if(P!=NULL&&t==P->j){
				printf("%d %d %d\n",P->i,P->j,P->ele);
				P=P->right;
			}
		}
	}
}

int main()
{
	int m,n,t1,t2;
	scanf("%d%d%d%d",&m,&n,&t1,&t2);
	cross a,b;

	init(&a);
	init(&b);
	creat(&a,m,n,t1);//创建两个十字链表储存链两个稀疏矩阵
	creat(&b,m,n,t2);
	add(a,b);//加
	show(a);//输出
	return 0;
}
	

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值