稀疏矩阵存储

news2025/4/15 4:02:18
  • 实验内容

1、(1)题目要求:如图所示,任意输入一个稀疏矩阵M,用三元组顺序表压缩存储该稀疏矩阵M,然后求其转置矩阵T,并输出转置矩阵T。

三元组的表示和初始化,用线性表

typedef struct{
	int i,j;
	int val;
}Triplet;
typedef struct{
	Triplet *elem;
	int tu,mu,nu;//个数,行数,列数 
}SqTriplet;
bool InitTriplet(SqTriplet &T,int rowSize,int colSize)
{
	T.elem=new Triplet[rowSize*colSize/5];
	if(!T.elem) return false;
	T.tu=0;
	T.mu=rowSize;
	T.nu=colSize;
	return true;
}

矩阵压缩函数

void compress(int M[][10],SqTriplet &T,int rowSize,int colSize)
{//压缩函数 
	for(int row=0;row<rowSize;row++)
	{
		for(int col=0;col<colSize;col++)
		{
			if(M[row][col]!=0)
			{//非零项赋值,个数加一 
//				T.(elem+T.length)->row=i;
				T.elem[T.tu].i=row;
				T.elem[T.tu].j=col;
				T.elem[T.tu].val=M[row][col];
				T.tu++;
			}
		}
	}
}

转置函数(快速转置)

用一个nums数组记录某一列前前面的所有列一共有多少个数,随后再转置,只需对三元组扫描三次。

void reserve(SqTriplet T,SqTriplet &T1)
{//T转置==>T1 
    //记录每一列元素的个数 
	int nums[T.nu]={0}; 
	for(int k=0;k<T.tu;k++)
	{
		nums[T.elem[k].j]++;
	}
	//记录每一列之前的列一共有多少个数据[1,3,5,2,3,4,5]
	//    nums[i] =[0,i-1]列元素个数    [0,1,4,9,11,14,18]
	int pre=nums[0];
	nums[0]=0;
	for(int k=1;k<T.nu;k++)
	{
		int t=nums[k];
		nums[k]=pre+nums[k-1];
		pre=t;;
	}
	//开始转置 
	for(int k=0;k<T.tu;k++)
	{
		int index=nums[T.elem[k].j];//转置后的位置 
		T1.elem[index].i=T.elem[k].j;
		T1.elem[index].j=T.elem[k].i; 
		T1.elem[index].val=T.elem[k].val;
		nums[T.elem[k].j]++;//下一次同一列的位置要往后移 
	}
	T1.tu=T.tu;
}

输出

void ShowTriplet(SqTriplet T)
{//展示三元组 
	cout<<"行  列  值\n";
	for(int k=0;k<T.tu;k++)
	{
		cout<<T.elem[k].i<<"  "<<T.elem[k].j<<"  "<<T.elem[k].val<<endl;
	}
}
void ShowMat(SqTriplet T)
{
	int pos=0;
	for(int row=0;row<T.mu;row++)
	{
		for(int col=0;col<T.nu;col++)
		{
			if(T.elem[pos].i==row&&T.elem[pos].j==col)
			{ cout<<T.elem[pos].val<<" ";pos++;}
			else cout<<"0 ";
		}
		cout<<endl;
	}
}

程序完整代码:

#include<iostream>
using namespace std;
typedef struct{
	int i,j;
	int val;
}Triplet;
typedef struct{
	Triplet *elem;
	int tu,mu,nu;//个数,行数,列数 
}SqTriplet;
bool InitTriplet(SqTriplet &T,int rowSize,int colSize)
{
	T.elem=new Triplet[rowSize*colSize/5];
	if(!T.elem) return false;
	T.tu=0;
	T.mu=rowSize;
	T.nu=colSize;
	return true;
}
void compress(int M[][10],SqTriplet &T,int rowSize,int colSize)
{//压缩函数 
	for(int row=0;row<rowSize;row++)
	{
		for(int col=0;col<colSize;col++)
		{
			if(M[row][col]!=0)
			{//非零项赋值,个数加一 
//				T.(elem+T.length)->row=i;
				T.elem[T.tu].i=row;
				T.elem[T.tu].j=col;
				T.elem[T.tu].val=M[row][col];
				T.tu++;
			}
		}
	}
}
void reserve(SqTriplet T,SqTriplet &T1)
{//T转置==>T1 
    //记录每一列元素的个数 
	int nums[T.nu]={0}; 
	for(int k=0;k<T.tu;k++)
	{
		nums[T.elem[k].j]++;
	}
	//记录每一列之前的列一共有多少个数据[1,3,5,2,3,4,5]
	//    nums[i] =[0,i-1]列元素个数    [0,1,4,9,11,14,18]
	int pre=nums[0];
	nums[0]=0;
	for(int k=1;k<T.nu;k++)
	{
		int t=nums[k];
		nums[k]=pre+nums[k-1];
		pre=t;;
	}
	//开始转置 
	for(int k=0;k<T.tu;k++)
	{
		int index=nums[T.elem[k].j];//转置后的位置 
		T1.elem[index].i=T.elem[k].j;
		T1.elem[index].j=T.elem[k].i; 
		T1.elem[index].val=T.elem[k].val;
		nums[T.elem[k].j]++;//下一次同一列的位置要往后移 
	}
	T1.tu=T.tu;
}
void ShowTriplet(SqTriplet T)
{//展示三元组 
	cout<<"行  列  值\n";
	for(int k=0;k<T.tu;k++)
	{
		cout<<T.elem[k].i<<"  "<<T.elem[k].j<<"  "<<T.elem[k].val<<endl;
	}
}
void ShowMat(SqTriplet T)
{
	int pos=0;
	for(int row=0;row<T.mu;row++)
	{
		for(int col=0;col<T.nu;col++)
		{
			if(T.elem[pos].i==row&&T.elem[pos].j==col)
			{ cout<<T.elem[pos].val<<" ";pos++;}
			else cout<<"0 ";
		}
		cout<<endl;
	}
}
int main()
{
	int m,n;
	SqTriplet T,Ta;
	cout<<"输入矩阵的行数和列数:\n";
	cin>>m>>n;
	cout<<"请输入矩阵:\n";
	int M[10][10];
	for(int i=0;i<m;i++)
	    for(int j=0;j<n;j++)
	        cin>>M[i][j];
	//压缩 
	InitTriplet(T,m,n);
	compress(M,T,m,n);
	cout<<"压缩后的三元组:\n";
	ShowTriplet(T);
	//转置
	InitTriplet(Ta,m,n);
	reserve(T,Ta);
	ShowTriplet(Ta);
	//根据三元组来输出矩阵 
	cout<<"转置后的矩阵:\n";
	ShowMat(Ta);
}

测试:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1147524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

七彩童年有“米小圈”陪伴!

长期以来&#xff0c;我对孩子看的电视和动画片都很谨慎&#xff0c;怕有不好的内容会对孩子产生误导&#xff0c;不利于小孩子健康成长。令我没想到的是在这个假期里&#xff0c;“米小圈”的出现&#xff0c;让我对动画片的看法有了很大的改变&#xff0c;也让我对孩子观看动…

关爱通分享丨三大步九小步—重构管理价值链,驱动福利进阶

企业人才素质不断提升&#xff0c;对生活品质和精神层面的追求越来越高&#xff0c;也倒推企业不断改善管理、健全福利制度&#xff0c;激发员工的积极性和创造力。企业成本激增&#xff0c;但预期价值未能完全实现&#xff0c;为此&#xff0c;笔者在价值驱动管理理念的基础上…

如何使用贝锐花生壳内网穿透实现远程打印?

打印机是现在办公必不可少的工具&#xff0c;我们常常需要使用打印机复印或打印各种文件资料&#xff0c;下面给大家介绍下如何通过花生壳发布内网打印机实现外网远程打印。 PS&#xff1a;本文使用花生壳8客户端映射发布Toshiba e-STUDIO3540C打印机&#xff1b;其它打印机型…

【文献分享】基于线特征的激光雷达和相机外参自动标定

论文题目&#xff1a;Line-based Automatic Extrinsic Calibration of LiDAR and Camera 中文题目&#xff1a;基于线特征的激光雷达和相机外参自动标定 作者&#xff1a;Xinyu Zhang, Shifan Zhu, Shichun Guo, Jun Li, and Huaping Liu 作者机构&#xff1a;清华大学汽车安…

微信小程序备案教你快速小程序备案

下面是小程序备案的步骤&#xff1a; 1. 在微信公众平台上登录小程序账号&#xff0c;进入“设置”页面。 2. 点击“账号信息”栏&#xff0c;进入账号信息页面。 3. 点击“备案”栏&#xff0c;进入备案页面。 4. 在备案页面中&#xff0c;选择需要备案的域名或网站&#…

Flash(Animate)和木疙瘩的元件学习和理解

元件就是讲一个图形或素材封装到一个容器里面&#xff01;可以被任何舞台、页面通过从仓库中拖拽的方式无限重复使用&#xff0c;类似unity中的预制体&#xff01; Flash(Animate)和木疙瘩中元件唯一区别&#xff1a;木疙瘩中一个元件A中不可以添加另一个元件B&#xff01; 一…

操作系统运行机制

文章目录 操作系统运行机制特权指令VS非特权指令内核态VS用户态中断和异常内中断(异常)外中断中断机制基本原理中断处理过程 系统调用系统调用和库函数的区别为什系统调用时必须的&#xff1f;什么功能需要用到系统调用系统调用的过程小结 操作系统内核 操作系统运行机制 特权…

防火墙的技术(NAT NAT-Server 策略路由 ) 第二十课

防火墙的技术(NAT NAT-Server 策略路由 ) 第二十课 环境的准备工作 1 配置如图所示的所有的IP地址 1 配置IIP地址 2 配置防火墙中的基本配置 防火墙的默认管理口的ip地址 <USG6000-ISP-LOCAL>display current-configuration 2023-10-28 02:54:08.620 !Software Ver…

YugaByteDB -- 全新的 “PostgreSQL“ 存储层

文章目录 0 背景1 架构1.1 Master1.2 TServer1.3 Tablet 2 读写链路2.1 DDL2.2 DML2.3 事务 3 KEY 的设计4 Rocksdb 在 YB 中的一些实践总结 0 背景 YugaByteDB 的诞生也是抓住了 spanner 推行的NewSQL 浪潮的尾巴&#xff0c;以 PG 生态为基础 用C实现的 支持 SQL 以及 CQL 语…

Linux多核CPU启动内核调试(详细)总结

目录 一、综述二、调试流程简介2.1 大体流程2.2 spin-table简介 三、uboot和内核配置3.1 uboot配置3.2 timer配置3.3 GIC中断配置3.4 驱动确认3.5 SMP配置3.6 内核config配置 四、其他相关链接1、[交叉编译linux内核总结](https://blog.csdn.net/Luckiers/article/details/1245…

Apache服务的搭建与配置(超详细版)

前言 Apache是一种常见的Web服务器软件&#xff0c;广泛用于Linux和其他UNIX操作系统上。它是自由软件&#xff0c;可以通过开放源代码的方式进行自由分发和修改。Apache提供了处理静态和动态内容的能力&#xff0c;而且还支持多种编程语言和脚本&#xff0c;如PHP、Python和P…

Doremy‘s Connecting Plan(cf 906 div2)

Doremy生活在一个由编号从1到n的n个城市组成的国家&#xff0c;第二个城市居住着ai人。它可以被建模为具有n节点的无向图。最初&#xff0c;图形中没有边。现在Doremy想要使图连通。 要做到这一点&#xff0c;她可以在i和j之间添加一条边,并且满足以下条件 其中S是当前在i或j的…

分类预测 | Matlab实现KOA-CNN-BiGRU-selfAttention多特征分类预测(自注意力机制)

分类预测 | Matlab实现KOA-CNN-BiGRU-selfAttention多特征分类预测&#xff08;自注意力机制&#xff09; 目录 分类预测 | Matlab实现KOA-CNN-BiGRU-selfAttention多特征分类预测&#xff08;自注意力机制&#xff09;分类效果基本描述程序设计参考资料 分类效果 基本描述 1.M…

基于UDP/TCP的网络通信编程实现

小王学习录 今日鸡汤Socket套接字基于UDP来实现一个网络通信程序DatagramSocket类DatagramPacket类基于UDP的服务器端代码基于UDP的客户端代码基于TCP来实现一个网络通信程序ServerSocket类Socket类基于TCP的服务器端代码基于TCP的客户端代码优化之后的服务器端代码补充TCP长短…

RabbitMQ学习04

文章目录 发布确认1. 发布确认的原理2. 发布确认的策略2.1.开启发布确认的方法2.2.单个确认2.3.批量确认发布2.4.异步确认发布2.5.如何处理异步未确认消息2.6 总结&#xff1a; 发布确认 1. 发布确认的原理 生产者将信道设置成 confirm 模式&#xff0c;一旦信道进入 confirm …

Spring Cloud Alibaba 教程 Fegin 篇

Spring Cloud Alibaba 教程 | Feign 篇 写在前面的话&#xff1a; 本笔记在参考网上视频以及博客的基础上&#xff0c;只作为个人学习笔记&#xff0c;如有侵权联系删除&#xff0c;谢谢&#xff01; 1、Feign替代RestTemplate ​ 1.1 引入依赖 <!-- Feign 客户端依赖 --&…

StringBuffer类提供针对字符的操作方法

StringBuffer类是Java中用于操作字符串的一个类&#xff0c;提供了许多针对字符的操作方法&#xff0c;例如&#xff1a; append()&#xff1a;用于在字符串末尾添加字符或字符串。 insert()&#xff1a;用于在字符串的指定位置插入字符或字符串。 delete()&#xff1a;用于删…

Spring中简单的获取Bean对象(对象装配)

获取Bean对象也叫做对象装配&#xff0c;是把对象取出来放到某个类中&#xff0c;有时候也叫对象注入&#xff01; 对象装配&#xff08;对象注入&#xff09;更加简单的读取Bean&#xff08;是从Spring容器中读取某个对象放到当前类里面&#xff09;的实现方法有以下3种&…

06 MIT线性代数-线性无关,基和维数Independence, basis, and dimension

1. 线性无关 Independence Suppose A is m by n with m<n (more unknowns than equations) Then there are nonzero solutions to Ax0 Reason: there will be free variables! A中具有至少一个自由变量&#xff0c;那么Ax0一定具有非零解。A的列向量可以线性组合得到零向…

【AD9361 数字接口CMOS LVDSSPI】C 并行数据之LVDS

接上一部分&#xff0c;AD9361 数字接口CMOS &LVDS&SPI 目录 一、LVDS模式数据路径和时钟信号LVDS模式数据通路信号[1] DATA_CLK[2] FB_CLK[3] Rx_FRAME[4] Rx_D[5&#xff1a;0][5] Tx_FRAME[6]Tx_D[5&#xff1a;0][7] ENABLE[8] TXNRX系列 二、LVDS最大时钟速率和信…