草庐IT

矩阵压缩存储(对称,三角,对角,稀疏)

想写好代码的小猫头 2023-04-12 原文

1.对称矩阵

(1)下三角矩阵

利用一维数组进行储存(下面的图片参考懒猫老师《数据结构》相关课程的笔记~)

每个元素在一维数组中的存储序号=阴影部分的面积

第i行第j列的元素序号=1+2+3+4...+(i-1)+j(等差数列求和公式化,下标从0开始减1)

aij=i*(i-1)/2+j-1(i>=j)

 (2)上三角矩阵

因为上三角矩阵其实就是将下三角矩阵的i,j进行调换得到的,同理,上三角矩阵的元素在数组中的表示可以类比:

aij=j*(j-1)/2+i-1(i<j)

对于这两种矩阵,如果对角线的另一侧不是0,而是一个常数定值,则表达方式是,在这个一维数组的末尾添加这个常数的值:(如图)

(3)全矩阵

通过(1)+(2),找规律可以表示在矩阵中的任意一个元素为:

 2.对角矩阵

对角矩阵:所有非零元素都集中在以主对角线为中心的带状区域中,除了主对角线和它的上下方若干条对角线的元素外,所有其他元素都为零。

 元素aij在一维数组中的序号

=2+3(i-2)+(j-i+2)

=2i+j-2(以零下标开始减去1)

=2i+j-3

3.稀疏矩阵

 稀疏矩阵中的非零元素的分布没有规律,稀疏矩阵中包括0和非零元素,没有规律的分布

(1)顺序储存

定义三元组:(只储存非零元素的信息)

typedef struct Triple {
	int row, col; //行号,列号
	DataType item;//非零元素
} Triple;

 其顺序结构储存示意图如下:

 定义矩阵性质:

typedef struct Matrix {
	int num;//非零元素的个数
	int mu;//矩阵的行数
	int nm;//矩阵的列数
} Matrix;

(下面的代码实现了对一个三元组的增查,打印的等功能,后面有相应的测试用例)

完整代码:(分为功能实现包--稀疏矩阵(顺序).h和测试功能包--稀疏矩阵测试.c)

(1)稀疏矩阵(顺序).h

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
typedef int DataType;

typedef struct Triple {
	int row, col; //行号,列号
	DataType item;//非零元素
} Triple;

typedef struct Matrix {
	int num;//非零元素的个数
	int mu;//矩阵的行数
	int nm;//矩阵的列数
} Matrix;

void TripleMatrix(Triple *data) { //初始化
	for (int i = 0; i < MAX; i++) {
		data[i].row = -1;
		data[i].col = -1;
	}
}

void printTriple(Triple *data) { //打印三元组
	int i = 0;
	printf("生成的三元组为:(行,列,非零元素)\n");
	while (data[i].row != -1) {
		printf("(%d,%d,%d)\n", data[i].row, data[i].col, data[i].item);
		i++;
	}
}

void printfMatrix(Triple *data, Matrix *datasum) { //打印矩阵
	printf("矩阵为:\n");
	int matirx[datasum->mu][datasum->nm];
	for (int i = 0; i < datasum->mu; i++) { //先将矩阵初始化为全0阵
		for (int j = 0; j < datasum->nm; j++) {
			matirx[i][j] = 0;
		}
	}
	for (int k = 0; k < datasum->num; k++) { //将稀疏矩阵中的值赋进去
		matirx[data[k].row - 1][data[k].col  - 1] = data[k].item; //行列值记得减1
	}
	for (int i = 0; i < datasum->mu; i++) { //打印
		for (int j = 0; j < datasum->nm; j++) {
			if (j == datasum->nm - 1)
				printf("%-5d\n", matirx[i][j]);
			else
				printf("%-5d ", matirx[i][j]);
		}
	}
}

void setItem(Triple *data, int row, int col, DataType item) { //添加元素
	Triple *str = data;
	Triple temp, temp1;
	int flag = 1; //控制两种储存交替进行
	int type = 0; //控制最后一个插入的是新元素还是原来存在temp和temp1中的元素
	while (str->row != -1 || str->col != -1) {
		if (str->row > row || (str->row == row && str->col > col)) { //插在前面
			temp = *str;
			str->row = row;
			str->col = col;
			str->item = item;
			str++;
			while (str->row != -1) {
				if (flag == 1) {
					temp1 = *str;
					*str = temp; //temp准备存储下一个
					str++;
					flag = 2;
				} else if (flag == 2) {
					temp = *str;
					*str = temp1; //temp1准备存储下一个
					str++;
					flag = 1;
				}
			}
			if (flag == 1) //最后一个元素在temp中
				type = 1;
			else if (flag == 2) //最后一个元素在temp1中
				type = 2;
		} else if (str->row < row || str->row == row) {
			str++;
		}
	}
	//前面都没有添加进去,就添加到末尾
	//或者存入temp或temp1中的需要在最后添加进去
	if (type == 0) {
		str->col = col;
		str->row = row;
		str->item = item;
	} else if (type == 1) {
		*str = temp;
	} else if (type == 2) {
		*str = temp1;
	}
}

DataType getItem(Triple *data, int row, int col, Matrix *datasum) { //根据行号列号获取矩阵元素
	if (row > datasum->mu || col > datasum->nm)
		printf("该坐标不在矩阵内!\n");
	for (int i = 0; i < datasum->num; i++) {
		if (data[i].row == row && data[i].col == col)
			return data[i].item;
	}
	return 0;
}

(2)稀疏矩阵测试.c

#include "稀疏矩阵(顺序).h"

main() {
	Triple data[MAX];
	TripleMatrix(data);
	Matrix datasum;
	int row, col;
	DataType item;
	printf("请输入矩阵初始的行,列和非零元个数:");
	scanf("%d %d %d", &datasum.mu, &datasum.nm, &datasum.num);
	for (int i = 0; i < datasum.num; i++) { //乱序的,不用从大到小
		printf("请依次输入行,列和非零元:");
		scanf("%d %d %d", &row, &col, &item);
		setItem(data, row, col, item);
	}
	printTriple(data);
	printfMatrix(data, &datasum);
	printf("请输入想查询的矩阵元素坐标:");
	int a, b, index;
	scanf("%d %d", &a, &b);
	index = getItem(data, a, b, &datasum);
	printf("该元素的值为:%d", index);
}

(3)测试输出

(2)十字链表

定义三元组:(只储存非零元素的信息)

typedef struct LinkTriple{
	int row, col; //行号,列号
	DataType item;//非零元素
	struct LinkTriple* right;//指针域,指向同一行中的下一个三元组
	struct LinkTriple* down;//指针域,指向同一列中的下一个三元组
}LinkTriple;

  定义矩阵性质:

typedef struct Matrix {
	int num;//非零元素的个数
	int mu;//矩阵的行数
	int nm;//矩阵的列数
} Matrix;

 十字链表结构示意图:

初学小白,有错误欢迎指正喔!~

有关矩阵压缩存储(对称,三角,对角,稀疏)的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  4. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  5. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  6. ruby - Ruby 的压缩库? - 2

    是否有任何可用于Ruby的开源压缩/解压库?有没有人实现过LZW?或者,是否有任何使用压缩组件的开源库可以提取出来独立使用?编辑——感谢您的回答!我应该提到我必须压缩的是只驻留在数据库中的长字符串(我不会压缩文件)。此外,如果可以执行此操作的任何库都具有用于客户端压缩/分解的等效JavaScript实现,那将是理想的,因为这将用于Web应用程序。 最佳答案 您会在rubystdlib下找到所有已交付的ruby​​库的一个很好的列表.我会使用zlib库,它是开放的,无处不在,您会发现几乎所有语言的库!

  7. ruby-on-rails - 尝试设置 Amazon 的 S3 存储桶 : 403 Forbidden error & setting permissions - 2

    我正在关注Hartl的railstutorial.org并已到达11.4.4:Imageuploadinproduction.我做了什么:注册亚马逊网络服务在AmazonIdentityandAccessManagement中,我创建了一个用户。用户创建成功。在AmazonS3中,我创建了一个新存储桶。设置新存储桶的权限:权限:本教程指示“授予上一步创建的用户读写权限”。但是,在存储桶的“权限”下,未提及新用户名。我只能在每个人、经过身份验证的用户、日志传送、我和亚马逊似乎根据我的名字+数字创建的用户名之间进行选择。我已经通过选择经过身份验证的用户并选中了上传/删除和查看权限的框(而不

  8. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

  9. ruby-on-rails - 闪存消息存储在哪里? - 2

    我以为它们存储在cookie中-但不,检查cookie没有任何结果。session也不存储它们。那么,我在哪里可以找到它们?我需要这个来直接设置它们(而不是通过flashhash)。 最佳答案 它们存储在inyoursessionstore.自rails2.0以来的默认设置是cookie存储,但请检查config/initializers/session_store.rb以检查您是否使用默认设置以外的东西。 关于ruby-on-rails-闪存消息存储在哪里?,我们在StackOverf

  10. ruby-on-rails - 在 Rails 中存储(结构化)配置数据的位置 - 2

    对于我正在编写的Rails3应用程序,我正在考虑从本地文件系统上的XML、YAML或JSON文件中读取一些配置数据。重点是:我应该把这些文件放在哪里?Rails应用程序中是否有用于存储此类内容的默认位置?附带说明一下,我的应用程序部署在Heroku上。 最佳答案 我经常做的是:如果文件是通用配置文件:我在目录/config中创建一个YAML文件,每个环境有一个上层key如果我为每个环境(大项目)创建一个文件:我为每个环境创建一个YAML并将它们存储在/config/environments/然后我在加载YAML的地方创建了一个初始化

随机推荐