_DataStructure_C_Impl:稀疏矩阵十字链表存储

#include<stdio.h>
#include<stdlib.h>
typedef int DataType;
typedef struct OLNode{
	int i,j;
	DataType e;
	struct OLNode *right,*down;
}OLNode,*OLink;
typedef struct{
	OLink *rowhead,*colhead;
	int m,n,len;
}CrossList;
//初始化稀疏矩阵
void InitMatrix(CrossList *M){
	M->rowhead=M->colhead=NULL;
	M->m=M->n=M->len=0;
}
//销毁稀疏矩阵
void DestroyMatrix(CrossList *M){
	int i;
	OLink p,q;
	for(i=0;i<M->m;i++){		//按行释放结点空间
		p=*(M->rowhead+i);
		while(p){
			q=p;
			p=p->right;
			free(q);
		}
	}
	free(M->rowhead);
	free(M->colhead);
	InitMatrix(M);
}
//使用十字链表的存储方式创建稀疏矩阵
void CreateMatrix(CrossList *M){
	int i,k;
	int m,n,num;
	OLNode *p,*q;
	if(M->rowhead)		//如果链表不空,则释放链表空间
		DestroyMatrix(M);
	printf("请输入稀疏矩阵的行数,列数,非零元素的个数: ");
	scanf("%d,%d,%d",&m,&n,&num);
	M->m=m;
	M->n=n;
	M->len=num;
	M->rowhead=(OLink*)malloc(m*sizeof(OLink));
	if(!M->rowhead)
		exit(-1);
	M->colhead=(OLink*)malloc(n*sizeof(OLink));
	if(!M->colhead)
		exit(-1);
	for(k=0;k<m;k++)		//初始化十字链表,将链表的行指针置为空
		M->rowhead[k]=NULL;
	for(k=0;k<n;k++)		//初始化十字链表,将链表的列指针置为空
		M->colhead[k]=NULL;
	printf("请按任意次序输入%d个非零元的行号、列号及元素值:\n",M->len);
	for(k=0;k<num;k++){
		p=(OLNode*)malloc(sizeof(OLNode));	 /*动态生成结点*/
		if(!p)
			exit(-1);
		printf("请输入第%d个非零元的行号(0~%d)、列号(0~%d)及元素值:",k+1,m,n);
		scanf("%d,%d,%d",&p->i,&p->j,&p->e); /*依次输入行号,列号和元素值*/
		/*-----------------------------行插入p结点-----------------------------------*/
		if(M->rowhead[p->i]==NULL||M->rowhead[p->i]->j>p->j)/*如果是第一个结点或当前元素的列号小于表头指向的一个的元素*/
		{
			p->right=M->rowhead[p->i];
			M->rowhead[p->i]=p;
		}
		else
		{
			q=M->rowhead[p->i];
			while(q->right&&q->right->j<p->j)	/*找到要插入结点的位置*/
				q=q->right;
			p->right=q->right;					/*将p插入到q结点之后*/
			q->right=p;
		}
		/*------------------------------列插入p结点-----------------------------------*/
		q=M->colhead[p->j];						/*将q指向待插入的链表*/
		if(!q||p->i<q->i)						/*如果p的行号小于表头指针的行号或为空表,则直接插入*/
		{
			p->down=M->colhead[p->j];
			M->colhead[p->j]=p;
		}
		else
		{
			while(q->down&&q->down->i<p->i)		/*如果q的行号小于p的行号,则在链表中查找插入位置*/
				q=q->down;
			p->down=q->down;					/*将p插入到q结点之下*/
			q->down=p;
		}
	}
}
//按矩阵形式输出十字链表
void PrintMatrix(CrossList M){
	int i,j;
	OLink p;
	for(i=0;i<M.m;i++)
	{
		p=M.rowhead[i];				/*p指向该行的第1个非零元素*/
		for(j=0;j<M.n;j++)			/*从第一列到最后一列进行输出*/
			if(!p||p->j!=j)			/*已到该行表尾或当前结点的列值不等于当前列值,则输出0*/
				printf("%-3d",0);
			else
			{
				printf("%-3d",p->e);
				p=p->right;
			}
			printf("\n");
	}
}
//按照行序将p插入到稀疏矩阵中
void InsertMatrix(CrossList *M,OLink p){
	OLink q=M->rowhead[p->i];		/*q指向待插行表*/
	if(!q||p->j<q->j)				/*待插的行表空或p所指结点的列值小于首结点的列值,则直接插入*/
	{
		p->right=M->rowhead[p->i];
		M->rowhead[p->i]=p;
	}
	else
	{
		while(q->right&&q->right->j<p->j)	/*q所指不是尾结点且q的下一结点的列值小于p所指结点的列值*/
			q=q->right;
		p->right=q->right;
		q->right=p;
	}
	q=M->colhead[p->j];					/*q指向待插列表*/
	if(!q||p->i<q->i)					/*待插的列表空或p所指结点的行值小于首结点的行值*/
	{
		p->down=M->colhead[p->j];
		M->colhead[p->j]=p;
	}
	else
	{
		while(q->down&&q->down->i<p->i)	/*q所指不是尾结点且q的下一结点的行值小于p所指结点的行值*/
			q=q->down;
		p->down=q->down;
		q->down=p;
	}
	M->len++;
}
//比较两个元素值的大小。如果a>b,返回1,a=b,则返回0,a<b,则返回-1
int CompareElement(int a,int b){
	if(a<b)
		return -1;
	if(a==b)
		return 0;
	return 1;
}
//十字链表表示的两个稀疏矩阵相加运算
void AddMatrix(CrossList A,CrossList B,CrossList *C){
	int i;
	OLink pa,pb,pc;
	if(A.m!=B.m||A.n!=B.n)
	{
		printf("两个矩阵不是同类型的,不能相加\n");
		exit(-1);
	}
	/*初始化矩阵Q*/
	C->m=A.m;
	C->n=A.n;
	C->len=0;				/*矩阵C的元素个数的初值为0*/
	/*初始化十字链表*/
	if(!(C->rowhead=(OLink*)malloc(C->m*sizeof(OLink))))	/*动态生成行表头数组*/
		exit(-1);
	if(!(C->colhead=(OLink*)malloc(C->n*sizeof(OLink))))	/*动态生成列表头数组*/
		exit(-1);
	for(i=0;i<C->m;i++)		/*初始化矩阵C的行表头指针数组,各行链表为空*/
		C->rowhead[i]=NULL;
	for(i=0;i<C->n;i++)		/*初始化矩阵C的列表头指针数组,各列链表为空*/
		C->colhead[i]=NULL;
	/*将稀疏矩阵按行的顺序相加*/
	for(i=0;i<A.m;i++)
	{
		pa=A.rowhead[i];	/*pa指向矩阵A的第i行的第1个结点*/
		pb=B.rowhead[i];	/*pb指向矩阵B的第i行的第1个结点*/
		while(pa&&pb)
		{
			pc=(OLink)malloc(sizeof(OLNode)); /*生成新结点*/
			switch(CompareElement(pa->j,pb->j))
			{
			case -1:				/*如果A的列号小于B的列号,将矩阵A的当前元素值插入C*/
				*pc=*pa;
				InsertMatrix(C,pc);
				pa=pa->right;
				break;
			case  0:				/*如果矩阵A和B的列号相等,元素值相加*/
				*pc=*pa;
				pc->e+=pb->e;
				if(pc->e!=0)		/*如果和为非零,则将结点插入到C中*/
					InsertMatrix(C,pc);
				else
					free(pc);
				pa=pa->right;
				pb=pb->right;
				break;
			case  1:				/*如果A的列号大于B的列号,将矩阵B的当前元素值插入C中*/
				*pc=*pb;
				InsertMatrix(C,pc);
				pb=pb->right;
			}
		}
		while(pa)					/*如果矩阵A还有未处理完的非零元素,则将剩余元素插入C中*/
		{
			pc=(OLink)malloc(sizeof(OLNode));
			*pc=*pa;
			InsertMatrix(C,pc);
			pa=pa->right;
		}
		while(pb)					/*如果矩阵B还有未处理完的非零元素,则将剩余元素插入C中*/
		{
			pc=(OLink)malloc(sizeof(OLNode));
			*pc=*pb;
			InsertMatrix(C,pc);
			pb=pb->right;
		}
	}
	if(C->len==0)					/*矩阵C的非零元素个数为零,则直接消耗C*/
		DestroyMatrix(C);
}
void main(){
	CrossList M,N,Q;
	int row,col;
	DataType value;
	OLink p;
	InitMatrix(&M);		/*初始化稀疏矩阵*/
	CreateMatrix(&M);	/*创建稀疏矩阵*/
	printf("矩阵M:\n");
	PrintMatrix(M);		/*以矩阵的形式输出稀疏矩阵*/

	InitMatrix(&N);		/*初始化稀疏矩阵*/
	CreateMatrix(&N);	/*创建稀疏矩阵*/
	printf("矩阵N:\n");
	PrintMatrix(N);	/*以矩阵的形式输出稀疏矩阵*/
	/*两个矩阵的相加*/
	AddMatrix(M,N,&Q);
	printf("两个稀疏矩阵相加结果:M+N=\n");
	PrintMatrix(Q);
	/*在矩阵M中插入一个元素*/
	printf("请输入要插入元素的行号、列号和元素值:");
	scanf("%d,%d,%d",&row,&col,&value);
	p=(OLNode*)malloc(sizeof(OLNode));
	p->i=row;
	p->j=col;
	p->e=value;
	InsertMatrix(&M,p);
	printf("插入元素后,矩阵M:\n");
	PrintMatrix(M);
	system("pause");
}

版权声明:本文为博主原创文章,未经博主允许不得转载|Copyright ©2011-2015,Supernatural, All Rights Reserved.

时间: 2025-01-10 08:14:23

_DataStructure_C_Impl:稀疏矩阵十字链表存储的相关文章

稀疏矩阵的十字链表存储表示

/* Name: 稀疏矩阵的十字链表存储表示 Copyright: Author: 巧若拙 Date: 29-10-14 21:25 Description: //------------------------------------------------------------------------- 除了用三元组顺序表来存储压缩矩阵,我们还可以用链表结构来存储,实际上后者应用更广泛, 因为当非零元素的数目较大时,三元组的时间复杂度实在太高.链表结构中最常见的是十字链表, 在十字链表中,

javascript实现数据结构:稀疏矩阵的十字链表存储表示

当矩阵的非零个数和位置在操作过程中变化大时,就不宜采用顺序存储结构来表示三元组的线性表.例如,在作"将矩阵B加到矩阵A上"的操作时,由于非零元的插入或删除将会引起A.data中元素的移动.为此,对这种类型的矩阵,采用链式存储结构表示三元组的线性表更为恰当. 在链表中,每个非陵园可用一个含5个域的结点表示,其中i,j和e这3个域分别表示该非零元所在的行,列和非零元的值,向右域right用以链接同一行中下一个非零元,向下域down用以链接同一列中下一个非零元.同一行的非零元通过right域

数据结构之---C++语言实现图的十字链表存储表示

最近一直忙着考研复习,很久都没有更新博客了,今天写一篇数据结构的存储. //有向图的十字链表存储表示 //杨鑫 #include <iostream> #include <cstdio> #include <stdlib.h> #include <cstring> using namespace std; #define MAX_VERTEX_NUM 20 #define OVERFLOW -2 #define OK 1 typedef int Status

7-3-有向图的十字链表存储结构-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向图的十字链表存储结构 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c.LinkQueue.c        

有向图的十字链表存储形式

十字链表是有向图的另一种链式存储结构.可以看成是将有向图的邻接表和逆邻接表(只考虑入度)结合起来得到的一种链表.在十字链表中,对应于有向图中每一个顶点有一个节点,每一条弧也有一个结点. 顶点之间是数组顺序存储,而弧是链式存储. 弧结点结构: 顶点结点结构: 十字链表形态: 实现: /*********************************************** 有向图的存储形式--十字链表 by Rowandjj 2014/6/27 ***********************

图的十字链表存储(C语言)

时间一晃已经大二下了,学校也开了数据结构的课,想起了自己大一刚会C语言,自学数据结构的时候,那时候很无助啊,不懂就只有拼命看,改bug改很久. 老师一节课讲完了邻接表,十字链表,邻接多重表.然而感觉他好像在自己讲自己的,一点也不认真. 但是依托老师是不行的,只懂理论也不行,或许学生认为邻接矩阵,邻接表不就那种东西吗?很简单啊. 大一的时候我也觉得C语言很简单啊,然后一写不都是错? 不写代码的数据结构不叫数据结构. 不多说,开始吧. 邻接表固然优秀,但也有不足,例如对有向图的处理上,有时候需要再建

基于十字链表的两个稀疏矩阵相乘

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef int DataType;// 稀疏矩阵的十字链表存储表示 typedef struct LNode { int i,j; // 该非零元的行和列下标 DataType e; // 非零元素值 struct LNode *right,*down; // 该非零元所在行表和列表的后继链域 }LNode, *Link; typedef str

数据结构之---C/C++实现稀疏矩阵的十字链表

首先这里介绍什么是矩阵的十字链表,大家可以理解稀疏矩阵是顺序存储的,那么这个就是链式存储的. 如图: 存储该矩阵 那么应该是如下的格式: 我们知道稀疏矩阵的三元组存储方式的实现很简单,每个元素有三个域分别是col,row, e.代表了该非零元的行号.列号以及值.那么在十字链表的存储方式下,首先这三个域是肯定少不了的,不然在进行很多操作的时候都要自己使用计数器,很麻烦.而十字链表的形式大家可以理解成每一行是一个链表,而每一列又是一个链表 通过上面的图我们可以知道,每个结点不止要存放row, col

十字链表是有向图的另一种链式存储表示

十字链表是有向图的另一种链式存储表示.形式代码如下: //-------------------有向图的十字链表存储表示-------------------------- #definMA X_VERTEX_NUM20 typedefstructArcBox{ headvex;//该弧的尾和头顶点的位置 inttailvex. *tlink;//分别为弧头相同和弧尾相同的弧的链域 structArcBox*hlink. InfoTyp*info;//该弧相关信息的指针 }A rcBox typ