稀疏矩阵的存储与获取(十字链表法 C++版)

此稀疏矩阵我们打算采用十字链表法进行存储。

 代码实现及结果测试:

#include<stdio.h>
#include<stdlib.h>
#define null NULL 
#define N 4    //矩阵的行数 
#define M 7    //矩阵的列数
 
/*
	稀疏矩阵的十字链表法实现方式 
*/

//十字链表的元素结点
typedef struct OLNode{
	int i,j,value; //i行标 j列标 value元素值
	struct OLNode *right,*down; //right是向右的指针   down是向下的指针 		
}OLNode; 

//十字链表行头指针数组,列头指针数组 
typedef struct{
	struct OLNode **rHead,**lHead;     //rHead指向行头指针数组     lHead指向列头指针数组 
}CrossList;

//使用十字链表法存储稀疏矩阵
void storage(CrossList *crossList,OLNode *node){
	//如果行头指针数组中的头指针为null,证明该行没有一个元素,如果有元素来,直接插入就行
	if(*(crossList->rHead+(node->i-1))== null){
		*(crossList->rHead+(node->i-1))=node;
	}else{
		//如果行头指针数组中的头指针不为null,证明该行有元素.我们就要逐一比较,把元素插在合适的位置
		OLNode *s = *(crossList->rHead+(node->i-1));
		OLNode *p = null;
	 	while(true){
	 		//s==null 表示s走到头了,要退出循环. 
	 		if(s==null){
		 		break;
		 	}
	 		if(node->j<s->j){//找到插入位置了,插入到s前面,p之后即可 
			 break;
		 	}
		 	p=s; 
		 	s= s->right;
	 	}
	 	//p==null 说明还得插入到该行的第一个位置 
	 	if(p == null){
	 		node->right=s;
		 	*(crossList->rHead+(node->i-1))=node;
	 	}else{
	 		//p!=null p指向的是s的前一个元素 
	 		node->right=s;
	 		p->right=node; 
	 	}
	} 
	//如果列头指针数组中的头指针为null,证明该列没有一个元素,如果有元素来,直接插入就行
	if(*(crossList->lHead+(node->j-1))==null){
		*(crossList->lHead+(node->j-1))=node;	
	}else{
		//如果列头指针数组中的头指针不为null,证明该列有元素,我们也要逐一比较,把元素插在合适的位置
		OLNode *s = *(crossList->lHead+(node->j-1));
		OLNode *p = null;
	 	while(true){ 
	 		if(s==null){
		 		break; 
		 	}
	 		if(node->i<s->i){//找到插入位置了,插入到s前面,p之后即可 
			 break;
		 	}
		 	p=s; 
		 	s= s->down;
	 	}
	 	//p==null 说明还得插入到该列的第一个位置 
	 	if(p == null){
	 		node->down=s;
		 	*(crossList->lHead+(node->j-1))=node;
	 	}else{
	 		//p!=null p指向的是s的前一个元素 
	 		node->down=s;
	 		p->down=node; 
	 	}
	}
	
}

void initrlHead(CrossList *crossList){
	//申请行头指针数组
	crossList->rHead = (OLNode **)malloc(sizeof(OLNode *)*N);
	//申请列头指针数组	
	crossList->lHead = (OLNode **)malloc(sizeof(OLNode *)*M);
	//行头指针数组元素初始化 
	for(int i = 0;i<N;i++){
		*(crossList->rHead+i)=null;
	}
	//列头指针数组元素初始化
	for(int i = 0;i<M;i++){
		*(crossList->lHead+i)=null;
	}
}
//打印行 
void printHang(CrossList *crossList,int i){
	OLNode *head = *(crossList->rHead+(i-1));
	while(head != null){
		printf("%d ",head->value);
		head=head->right;
	}
} 
//打印列
void printLie(CrossList *crossList , int j){
	OLNode * head = *(crossList->lHead+(j-1));
	while(head != null){
		printf("%d ",head->value);
		head=head->down;
	}
} 



int main(int argc, char *argv[])
{
	//用二维数组模拟一个稀疏矩阵
	int matrix[N][M]={
		{0,0,0,1,0,9,0},
		{0,2,0,0,7,0,0},
		{0,0,0,0,0,3,0},
		{4,0,0,5,0,0,0}
	};
	CrossList crossList;
	initrlHead(&crossList); 
	
	//找到二维数组中的非零元素。将非零元素加入到十字链表中。 
	for(int i = 0;i<N;i++){
		for(int j= 0;j<M;j++){
			if(matrix[i][j]!=0){
				OLNode *s = (OLNode *)malloc(sizeof(OLNode));
				s->i=(i+1);
				s->j=(j+1);
				s->value=matrix[i][j];
				s->right=null;
				s->down=null;
				storage(&crossList,s);  
			}	
		}
	}
	
	//打印每一行,打印每一列,看一下十字链表有没有成功 
	
	printf("第一行元素是 ");
	printHang(&crossList,1);
	printf("\n"); 
	printf("第二行元素是 ");
	printHang(&crossList,2);
	printf("\n");
	printf("第三行元素是 ");
	printHang(&crossList,3);
	printf("\n");
	printf("第四行元素是 "); 
	printHang(&crossList,4);
	printf("\n");
	printf("\n");
	printf("\n");
	printf("\n");
	printf("\n");
	
	
	printf("第一列元素是 ");
	printLie(&crossList,1);
	printf("\n"); 
	printf("第二列元素是 ");
	printLie(&crossList,2);
	printf("\n"); 
	printf("第三列元素是 ");
	printLie(&crossList,3);
	printf("\n"); 
	printf("第四列元素是 "); 
	printLie(&crossList,4);
	printf("\n"); 
	printf("第五列元素是 ");
	printLie(&crossList,5);
	printf("\n"); 
	printf("第六列元素是 ");
	printLie(&crossList,6);
	printf("\n"); 
	printf("第七列元素是 ");
	printLie(&crossList,7);
	printf("\n"); 
	
	
	
	
	return 0;
}

从结果图我们能看出,我们的十字链表法存储稀疏矩阵是成功的。

但是我那个storage确定新节点的插入位置代码不简洁。分支很多。

特此借鉴了一下别人的代码,改进了一版storage方法。

改进版storage方法如下:

//改进版的storage方法。 
void evolutionStorage(CrossList	*crossList,OLNode *node){
	//链接到行的指定位置  //以第一个结点为分界点, if是分界点之前找插入位置   else 是分界点之后找插入位置 
	if(*(crossList->rHead+(node->i-1))==null || node->j<(*(crossList->rHead+(node->i-1)))->j){
		node->right=*(crossList->rHead+(node->i-1));
		*(crossList->rHead+(node->i-1))= node;
	}else{
		OLNode *p =*(crossList->rHead+(node->i-1));
		//找到插入位置,p之后
		for(p;(p->right!=null)&&(p->right->j<node->j);p=p->right);
		node->right=p->right;
		p->right=node;
	}
	
	//链接到列的指定位置 
	if(*(crossList->lHead+(node->j-1)) == null || node->i<(*(crossList->lHead+(node->j-1)))->i){
		node->down = *(crossList->lHead+(node->j-1));
		*(crossList->lHead+(node->j-1)) = node;
	}else{
		OLNode *p =*(crossList->lHead+(node->j-1));
		//找到插入位置,p之后
		for(p;(p->down!=null)&&(p->down->i<node->i);p=p->down);
		node->down=p->down;
		p->down=node;
	}
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值