数据结构实验5----稀疏矩阵的应用

实验题目

实验题目:稀疏矩阵的应用:设计算法并编程实现用三元组顺序表解决稀疏矩阵的转置问题,用2种方法实现并分析比较2种算法的时间和空间复杂性。

实验说明:在m×n 的矩阵中,有t个非零元。令δ= t/(m*n),称δ矩阵的稀疏因子,常认为δ≤0.05时称为稀疏矩阵。稀疏矩阵在工程中有着大量的应用,不少工程问题都可以转化为对稀疏矩阵的计算问题。用三元组顺序表实现稀疏矩阵的转置通常有2种方法,顺序存和顺序取直接存。

        顺序取直接存方法:引入两个数组作为辅助数据结构:

                num[nu]:表示矩阵A中某列的非零元素的个数;

                cpot[nu]:初始值表示矩阵A中某列的第一个非零元素在B中的位置。 

        num与cpot递推关系:

三元组表实现稀疏矩阵的转置(顺序取直接存)算法伪代码如下:

        1. 设置转置后矩阵B的行数、列数和非零元素的个数;

        2. 计算A中每一列的非零元素个数;

        3. 计算A中每一列的第一个非零元素在B中的下标;

        4. 依次取A中的每一个非零元素对应的三元组;

                4.1 确定该元素在B中的下标pb;

                4.2 将该元素的行号列号交换后存入B中pb的位置;

                4.3 预置该元素所在列的下一个元素的存放位置;

实验内容

1.问题设计分析

        顺序存:首先建立a,b两个三元组通过函数InitSPNode用来建立一个稀疏矩阵的三元组表。输入行数、列数和非零元素的值,输入(-1,-1,-1)结束输入。然后通过TransposeSMatrix函数实现矩阵的转置,得到的转置矩阵的三元组表时要按一行一行存放且每行中的元素是按列号从小到大的规律顺序存放,因此在转换时,对a的每一列扫描三元组,找出相应的元素,若找到,则交换其行号与列号,并存储到b的三元组里。最后函数showMatrix用来输出稀疏矩阵。算法中按矩阵a的列进行循环处理,对a的每一列扫描三元组,找出相应的元素,若找到,则交换其行号和列号,并存储到矩阵b的三元组中。该算法的主要工作是在TransposeSMatrix函数p和col的两重循环中完成,时间复杂度为O(n*t)。如果非零元素个数t和m*n同数量级,则算法的时间复杂度变为O(m*n^2)。

        顺序取直接存方法:引入两个数组作为辅助数据结构,num[nu]表示矩阵A中某列的非零元素的个数;cpot[nu]:初始值表示矩阵A中某列的第一个非零元素在B中的位置。根据上图num与cpot递推关系以及三元组表实现稀疏矩阵的转置算法伪代码可得到最终结果。

2.程序编码

        方法一:

#include <stdio.h>
#include <string.h>
#define OK 1
#define Maxsize 10 
typedef struct 
{
	int i,j;
	int v;
}SPNode;
typedef struct
{ 
	SPNode data[Maxsize];
	int m,n,t;//矩阵行、列及三元表长度
}SPMatrix;
void InitSPNode(SPMatrix*a) 
{
	int i,j,k,val,maxrow,maxcol;
	maxrow=0;
	maxcol=0;
	i=j=0;
	k=0;
	while(i!=-1&&j!=-1)
	 { 
		printf(" 输入(行 列 值):  ");
		scanf(" %d %d %d",&i,&j,&val);
		a->data[k].i=i;
		a->data[k].j=j;
		a->data[k].v=val;
		if(maxrow<i) maxrow=i;
		if(maxcol<j) maxcol=j;
		k++;
	}
	a->m=maxrow;
	a->n=maxcol;
	a->t=k-1;
}
void showMatrix(SPMatrix *a) 
{
	int p,q;
	int t=0;
	for(p=0; p<=a->m; p++) {
		for(q=0; q<=a->n; q++) {
			if(a->data[t].i==p&&a->data[t].j==q) {
				printf(" %d  ",a->data[t].v);
				t++;
			} else printf(" 0  ");
		}
		printf("\n"  );
	}
}
void TransposeSMatrix(SPMatrix *a,SPMatrix *b) 
{
	int q,col,p;
	b->m=a->n;
	b->n=a->m;
	b->t=a->t;
	if(b->t) {
		q=0;
		for(col=0; col<=a->n; ++col) 
			for(p=0; p<a->t; ++p) 
				if(a->data[p].j==col) {
					b->data[q].i=a->data[p].j;
					b->data[q].j=a->data[p].i;
					b->data[q].v=a->data[p].v;
					++q;
				}
	}
}
int main() {
	SPMatrix a,b;
	printf("\n 结束请输入(-1 -1 -1)\n"  );
	InitSPNode(&a);
	printf(" 输入矩阵为:\n" );
	showMatrix(&a);
	TransposeSMatrix(&a,&b);
	printf(" 输出矩阵为: \n" );
	showMatrix(&b);
}

        方法二: 

#include<stdio.h>
#define M 5 
#define N 5 
#define MaxSize 10000 
typedef struct
{
	int r;
	int c;
	int d;
}TupNude;
typedef struct
{
	int rows;
	int cols;
	int nums;
	TupNude data[MaxSize];
}TSMatrix;
void change(TSMatrix t,TSMatrix& p)
{
	int k=0;
	p.rows = t.cols;
	p.cols = t.rows;
	p.nums = t.nums;
	int num[5] = { 0 };
	int copt[5] = { 0 };
	int w = t.nums;
	int co[MaxSize] = { 0 };
	if (t.nums)
	{
		for (int i = 0; i < t.nums; i++)
		{
			num[t.data[i].c]++;
		}
		for (int i = 1; i < t.cols; i++)
		{
			copt[i] = copt[i - 1] + num[i - 1];
		}
 		for (int i = 0; i < t.nums; i++)
		{
			int j;
			j = t.data[i].c;	
			p.data[copt[j]].r = t.data[i].c;
			p.data[copt[j]].c = t.data[i].r;
			p.data[copt[j]].d = t.data[i].d;
			copt[j]++;
		}
	}
}
void print(TSMatrix x)
{
	int k;
	printf("\t行\t列\t个数\n"); 
	printf("\t%d\t%d\t%d",x.rows,x.cols,x.nums);
	printf("\n");
	printf("具体为:\n");
	for (k=0;k<x.nums;k++)
	{
		printf("\t%d\t%d\t%d",x.data[k].r,x.data[k].c,x.data[k].d);
		printf("\n");
	}
}
int main()
{
	int i,j; 
	printf("请输入数组元素:\n");
	int a[M][N];
	for(i=0;i<M;i++)
	{
		for(j=0;j<N;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	printf("你的输入为:\n");
	for(i=0;i<M;i++)
	{
		for(j=0;j<N;j++)
		{
			printf("%d ",a[i][j]);
		}
		printf("\n");
	}
	TSMatrix l,p;
	l.rows=M;
	l.cols=N;
	int sum=0;
	for (i=0;i<M;i++)
	{
		for(j=0;j<N;j++)
		{
			if(a[i][j]!=0)
			{
				l.data[sum].r=i;
				l.data[sum].c=j;
				l.data[sum].d=a[i][j];
				sum++;
			}
		}
	}
	l.nums=sum;
	printf("转置前:\n");
	print(l);
	change(l,p);
	printf("转置后:\n");
	print(p);
	return 0;
}

3.运行结果和分析

        方法一结果如下:

        方法二结果如下: 

 

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值