【头歌】数组-稀疏矩阵的转置

news/2024/7/24 10:52:15 标签: 矩阵, 算法, 数据结构

数组-稀疏矩阵的转置

第1关:一般转置算法

任务描述

本关任务:实现稀疏矩阵的转置操作(采用一般转置算法,即按列序转置)。

相关知识

为了完成本关任务,你需要理解:1. 矩阵的压缩存储,2.稀疏矩阵的三元组顺序表存储表示,3.一般转置算法

矩阵的压缩存储

矩阵的压缩存储是指:为多个值相同的非零元素只分配一个存储空间,对零元素不分配空间,从而节省存储空间。

稀疏矩阵的三元组顺序表存储表示

稀疏矩阵是指非零元素的个数远远少于总的元素个数,且非零元素的分布没有规律。

稀疏矩阵的压缩存储就是只存储非零元素;且存储非零元素的值的同时,还需存储其所在的行和列。

于是,将非零元所在的行、列及其值构成一个三元组(i,j,v),且按行优先方式排列三元组,从而构成稀疏矩阵的三元组线性表,称为三元组表。

三元组表的存储方式有顺序存储和链式存储,从而可引出稀疏矩阵的两种压缩存储方式:三元组顺序表存储和十字链表存储。

//三元组顺序表存储表示
#define MAXSIZE 100
typedef int datatype;
typedef struct
{
    int i,j;
    datatype v;
}SPNode; //三元组类型
typedef struct
{
    int m,n,t; //矩阵的总行数、总列数及非零元个数
    SPNode data[MAXSIZE];
}SPMatrix;

如:下面图1所示的稀疏矩阵A的三元组顺序表的数据存储情况如图2所示。

img

img

一般转置算法

先在矩阵A的三元组表A.data中找到第0列的非零元素存入转置阵B的三元组表B.data中,再找到第1列存入B.data中,……,这样得到的转置矩阵B的三元组表B.data中的元素必定按行优先存放。

如何在A.data中找第k列?

需对A.data扫描一遍,即:先比较A.data[0].j是否等于k,若相等,则将A.data[0]存入B.data中,接着继续比较下一个A.data[1].j, …… 。

编程要求

在右侧编辑器中补充代码,完成TransSMatrix函数,以实现稀疏矩阵的转置操作。具体要求如下:

* TransSMatrix:求稀疏矩阵A的转置阵B,采用一般转置算法(即按列序转置),稀疏矩阵采用三元组顺序表存储。

测试说明

平台会对你编写的代码进行测试,测试文件为step1/Main.cpp,可在右侧文件夹中进行查看。

输入输出格式: 输入格式: 第一行输入矩阵A的总行数、总列数及非零元个数 第二行按行序输入矩阵A的各个非零元素的行号、列号及值 输出格式: 先输出矩阵A的三元组表,再输出A的转置阵的三元组表。末尾换行。

测试输入:

5 5 6 //输入矩阵A的总行数、总列数及非零元个数

0 2 -9 0 4 5 1 0 -7 1 2 7 3 1 8 4 2 9 //按行序输入矩阵A的各个非零元素的行号、列号及值

预期输出:

The Matrix A:
(0,2,-9)
(0,4,5)
(1,0,-7)
(1,2,7)
(3,1,8)
(4,2,9)
The Transport Matrix of A:
(0,1,-7)
(1,3,8)
(2,0,-9)
(2,1,7)
(2,4,9)
(4,0,5) //末尾换行

开始你的任务吧,祝你成功!

代码示例

/*************************************************************
    稀疏矩阵  实现文件
    更新于2020年10月28日
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SparseMatrix.h"

void input(SPMatrix &a)//输入采用三元组顺序表存储的矩阵
{
	int p;
	scanf("%d%d%d",&a.m,&a.n,&a.t); //输入矩阵总行数、总列数和非零元素的个数
	for(p=0;p<a.t;p++)
		scanf("%d%d%d",&a.data[p].i,&a.data[p].j,&a.data[p].v);
}
void output(SPMatrix a)//输出矩阵的三元组表
{
	int p;
	for(p=0;p<a.t;p++)
		printf("(%d,%d,%d)\n",a.data[p].i,a.data[p].j,a.data[p].v);
}
void TransSMatrix(SPMatrix a, SPMatrix &b)//一般转置,即:按列序转置
{
	// 请在这里补充代码,完成本关任务
    /********** Begin *********/
	b.m=a.n;
    b.n=a.m;
    b.t=a.t;
    if (b.t) {
        int q=0; //三元组表T的下标 
        int p; //三元组表M的下标
        for (int col=0;col<=a.m; col++) { //从最小列顺序开始找 
            for (p=0; p<a.t; p++) { //从三元组表M顺序查找 
                if (a.data[p].j==col) { //三元组表M中当前列是最小列,则进行转置 
                    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++;
                }
            }
        }
    }
  
    /********** End **********/
}

第2关:快速转置算法

任务描述

本关任务:实现稀疏矩阵的转置操作(采用快速转置算法)。

相关知识

为了完成本关任务,你需要理解:1. 稀疏矩阵的三元组顺序表存储表示,2.快速转置算法

稀疏矩阵的三元组顺序表存储表示

//三元组顺序表存储表示
#define MAXSIZE 100
typedef int datatype;
typedef struct
{
    int i,j;
    datatype v;
}SPNode; //三元组类型
typedef struct
{
    int m,n,t; //矩阵的总行数、总列数及非零元个数
    SPNode data[MAXSIZE];
}SPMatrix;

快速转置算法

一般转置算法效率低的原因是通过对A.data扫描若干遍来找到第0列,第1列,……,共需扫描n遍。我们如果能直接确定A中每一个三元组在B中的位置,则对A.data扫描一遍即可。那么,如何确定A中每一个三元组在B.data中的位置?

设两个数组x[n]和y[n]。其中,x[i]表示A中第i列的非零元的个数,y[i]初始值表示A中第i列第一个非零元在B.data中的位置。

显然有:

y[0]=0
y[1]=y[0]+x[0]
……
y[i]=y[i-1]+x[i-1]

接下来依次扫描A.data,先判断A.data[0],取出A.data[0].j用变量k保存(k=A.data[0].j),表示该三元组是A中第k列第一个非零元,则其在B.data中的位置为q=y[k],接着将该三元组存入B.data[q]中,然后y[k]++,以便将第k列的下一个非零元存放到B.data下一个位置;接着再判断A.data[1],……。

编程要求

在右侧编辑器中补充代码,完成FastTransSMatrix函数,以实现稀疏矩阵的转置操作。具体要求如下:

* FastTransSMatrix:求稀疏矩阵A的转置阵B,采用快速转置算法,稀疏矩阵采用三元组顺序表存储。

测试说明

平台会对你编写的代码进行测试,测试文件为step2/Main.cpp,可在右侧文件夹中进行查看。

输入输出格式: 输入格式: 第一行输入矩阵A的总行数、总列数及非零元个数 第二行按行序输入矩阵A的各个非零元素的行号、列号及值 输出格式: 先输出矩阵A的三元组表,再输出A的转置阵的三元组表。末尾换行。

测试输入:

5 5 6 //输入矩阵A的总行数、总列数及非零元个数

0 2 -9 0 4 5 1 0 -7 1 2 7 3 1 8 4 2 9 //按行序输入矩阵A的各个非零元素的行号、列号及值

预期输出:

The Matrix A:

(0,2,-9)

(0,4,5)

(1,0,-7)

(1,2,7)

(3,1,8)

(4,2,9)

The Transport Matrix of A:

(0,1,-7)

(1,3,8)

(2,0,-9)

(2,1,7)

(2,4,9)

(4,0,5) //末尾换行

开始你的任务吧,祝你成功!

/*************************************************************
    稀疏矩阵  实现文件
    更新于2020年10月28日
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SparseMatrix.h"

void input(SPMatrix &a)//输入采用三元组顺序表存储的矩阵
{
	int p;
	scanf("%d%d%d",&a.m,&a.n,&a.t); //输入矩阵总行数、总列数和非零元素的个数
	for(p=0;p<a.t;p++)
		scanf("%d%d%d",&a.data[p].i,&a.data[p].j,&a.data[p].v);
}
void output(SPMatrix a)//输出矩阵的三元组表
{
	int p;
	for(p=0;p<a.t;p++)
		printf("(%d,%d,%d)\n",a.data[p].i,a.data[p].j,a.data[p].v);
}
void FastTransSMatrix(SPMatrix a, SPMatrix &b)//快速转置
{	
	int p,q,i,k;  int x[N],y[N];
	b.m=a.n; b.n=a.m; b.t=a.t;
	if(b.t==0)
	{
		printf("The matrix has no nonzero element!\n"); return;
	}
	for(i=0;i<a.n;i++) x[i]=0;
	for(p=0;p<a.t;p++) //求A中每一列非零元个数存放到x[ ]中
	{
		/********** Begin *********/
		int k=a.data[p].j;
        x[k]++;
		/********** End **********/
	}
	y[0]=0; 
    y[1]=y[0]+x[0];
	for(i=2;i<a.n;i++)//求A中每一列的第一个非零元在B.data中的位置存放到y[ ]中
	{
		/********** Begin *********/
		y[i]=y[i-1]+x[i-1];
	    /********** End **********/
	}
	for(p=0;p<a.t;p++) //扫描A.data,将A中每一三元组存放到B中恰当位置
	{
		/********** Begin *********/
		int i=a.data[p].j;
        int q=y[i];
        b.data[q].i=a.data[p].j;
        b.data[q].j=a.data[p].i;
        b.data[q].v=a.data[p].v;
        y[i]++;
		/********** End **********/
	}    	
}




http://www.niftyadmin.cn/n/310746.html

相关文章

Redis命令详解

Redis是一个高性能的内存键值数据库&#xff0c;它支持多种数据结构&#xff0c;包括字符串、哈希、列表、集合、有序集合等。Redis通过提供一组命令来实现对数据的操作&#xff0c;这些命令可以通过Redis客户端发送给Redis服务器&#xff0c;从而对数据库进行操作。 Redis的一…

Java 责任链模式详解

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它用于将请求的发送者和接收者解耦&#xff0c;使得多个对象都有机会处理这个请求。在责任链模式中&#xff0c;有一个请求处理链条&#xff0c;每个处理请求的对象都是一个…

jmeter如何测试一个get请求

目录 1.配置测试计划1.1.创建线程组1.2.创建GET的HTTP请求取样器&#xff08;模拟GET请求&#xff09;1.3.添加查看结果树和聚合报告 2.执行压测并查看结果2.1.验证接口2.2.执行压力测试 使用jmeter测试一个http的get请求示例. 1.配置测试计划 1.1.创建线程组 打开jmeter - 测…

前端小记——Vue3

目录 Vue介绍 Vue安装使用 Vue入门案列 插值表达式 Vue指令 v-test v-html v-bind v-on v-model v-cloak v-show v-if v-else v-else-if v-for 计算属性 计算属性完整写法 属性侦听 class属性的绑定 style属性的绑定 表单数据收集 事件绑定和修饰符 Vue…

什么是土壤水势传感器

水对任何植物的重要性不言而喻。在不同生理时期&#xff0c;水分的作用并不相同&#xff0c;每个阶段如何控制水分都会影响植物的生长发育和产量。根系具有向水向肥性&#xff0c;知道不同深度的水势&#xff0c;那么我们就可以使用特殊的灌溉策略来刺激根系向更深处发展。比如…

07 - 3系统容量规划

阿里系业务容量规划 Tair集群部署与水位调配 阿里系容量精调之单机压测场景 传统模拟请求 流量复制 流量转发 网关权重 线上测试注意点 阿里系混合部署技术 资源分时复用&#xff1a;提高资源利用率sigama框架做在线资源池调度&#xff0c;伏羲做离线资源池调度&#xff1b;…

什么是应用交付网络(ADN)

从CDN到ADN CDN&#xff08;内容分发网络&#xff09;在90年代末受到麻省理工学院的启发并完成发明&#xff0c;00年代初成立第一家成功的CDN商业企业Akamai。CDN的目标是相对于最终用户在空间上分配服务&#xff0c;以提供高可用性和高性能。随着互联网的发展&#xff0c;CDN…

makefile 条件判断语句

文章目录 前言一、条件判断语句的语法说明二、ifeq / ifneq三、ifdef / ifndef代码讲解&#xff1a; 四、经典示例总结 前言 一、条件判断语句的语法说明 makefile 中支持条件判断语句。 可以根据条件的值决定 make 的执行。可以 比较 两个不同变量或者变量和常量值。 条件判…