稀疏矩阵 part 2
▶ 各种稀疏矩阵数据结构之间的转化
● MAT ←→ CSR
CSR * MATToCSR(const MAT *in) // MAT 转 CSR
{
checkNULL(in);
CSR * out = initializeCSR(in->row, in->col, in->count);
checkNULL(out); out->ptr[] = ;
for (int i = , j = , k = ; i < in->row * in->col; i++) // i 遍历 in->data
{
if (in->data[i] != ) // 找到非零元
{
if (j == in->count) // 在 out->data 已经填满了的基础上又发现了非零元,错误
return NULL;
out->data[j] = in->data[i]; // 填充非零元素
out->index[j] = i % in->col; // 填充列号
j++;
}
if ((i + ) % in->col == ) // 到了最后一列,写入行指针号
out->ptr[k++] = j;
}
return out;
} MAT * CSRToMAT(const CSR *in) // CSR转MAT
{
checkNULL(in);
MAT *out = initializeMAT(in->row, in->col, in->ptr[in->row]);
checkNULL(out); memset(out->data, , sizeof(format) * in->row * in->col);
for (int i = ; i < in->row; i++) // i 遍历行
{
for (int j = in->ptr[i]; j < in->ptr[i + ]; j++) // j 遍历列
out->data[i * in->col + in->index[j]] = in->data[j];
}
return out;
}
● MAT ←→ ELL
ELL * MATToELL(const MAT *in)// MAT转ELL
{
checkNULL(in); int i, j, maxElement;
for (i = j = maxElement = ; i < in->row * in->col; i++) // i 遍历 in->data,j 记录该行非零元素数,maxElement 记录一行非零元素最大值
{
if (in->data[i] != ) // 找到非零元
j++;
if ((i + ) % in->col == ) // 行末,更新 maxElement
{
maxElement = MAX(j, maxElement);
j = ; // 开始下一行之前清空 j
}
}
format* temp_data=(format *)malloc(sizeof(format) * in->row * maxElement); // 临时数组,将列数压缩到 maxElement
checkNULL(temp_data);
int* temp_index = (int *)malloc(sizeof(int) * in->row * maxElement);
checkNULL(temp_index);
memset(temp_data, , sizeof(format) * in->row * maxElement);
memset(temp_index, , sizeof(int) * in->row * maxElement);
for (i = j = ; i < in->row * in->col; i++) // i 遍历 in->data,j 记录该行非零元素数,把 in 中每行的元素往左边推
{
if (in->data[i] != ) // 找到非零元
{
temp_data[i / in->col * maxElement + j] = in->data[i]; // 存放元素
temp_index[i / in->col * maxElement + j] = i % in->col; // 记录所在的列号
j++;
}
if ((i + ) % in->col == ) // 行末,将剩余位置的下标记作 -1,即无效元素
{
for (j += i / in->col * in->col; j < maxElement * (i / in->col + ); j++) // 使得 j 指向本行最后一个非零元素之后的元素,再开始填充
temp_index[j] = -;
j = ; // 开始下一行之前清空 j
}
}
ELL *out = initializeELL(maxElement, in->row, in->col); // 最终输出,如果不转置的话不要这部分
checkNULL(out);
for (i = ; i < out->row * out->col; i++) // 将 temp_data 和 temp_index 转置以提高缓存利用
{
out->data[i] = temp_data[i % out->col * out->row + i / out->col];
out->index[i] = temp_index[i % out->col * out->row + i / out->col];
}
free(temp_data);
free(temp_index);
return out;
} MAT * ELLToMAT(const ELL *in) // ELL转MAT
{
checkNULL(in);
MAT *out = initializeMAT(in->col, in->colOrigin);
checkNULL(out); for (int i = ; i < in->row * in->col; i++) // i 遍历 out->data
{
if (in->index[i] < ) // 注意跳过无效元素
continue;
out->data[i % in->col * in->colOrigin + in->index[i]] = in->data[i];
}
COUNT_MAT(out);
return out;
}
● MAT ←→ COO
COO * MATToCOO(const MAT *in) // MAT转COO
{
checkNULL(in);
COO *out = initializeCOO(in->row, in->col, in->count); for (int i=, j = ; i < in->row * in->col; i++)
{
if (in->data[i] != )
{
out->data[j] = in->data[i];
out->rowIndex[j] = i / in->col;
out->colIndex[j] = i % in->col;
j++;
}
}
return out;
} MAT * COOToMAT(const COO *in) // COO转MAT
{
checkNULL(in);
MAT *out = initializeMAT(in->row, in->col, in->count);
checkNULL(out); for (int i = ; i < in->row * in->col; i++)
out->data[i] = ;
for (int i = ; i < in->count; i++)
out->data[in->rowIndex[i] * in->col + in->colIndex[i]] = in->data[i];
return out;
}
● MAT ←→ DIA
DIA * MATToDIA(const MAT *in) // MAT转DIA
{
checkNULL(in); int *index = (int *)malloc(sizeof(int)*(in->row + in->col - ));
for (int diff = in->row - ; diff > ; diff--) // 左侧零对角线情况
{
int flagNonZero = ;
for (int i = ; i < in->col && i + diff < in->row; i++) // i 沿着对角线方向遍历 in->data,flagNonZero 记录该对角线是否全部为零元
{
#ifdef INT
if (in->data[(i + diff) * in->col + i] != )
#else
if (fabs(in->data[(i + diff) * in->col + i]) > EPSILON)
#endif
flagNonZero = ;
}
index[in->row - - diff] = flagNonZero; // 标记该对角线上有非零元
}
for (int diff = in->col - ; diff >= ; diff--) // 右侧零对角线情况
{
int flagNonZero = ;
for (int j = ; j < in->row && j + diff < in->col; j++)
{
#ifdef INT
if (in->data[j * in->col + j + diff] != )
#else
if (fabs(in->data[j * in->col + j + diff]) > EPSILON)
#endif
flagNonZero = ;
}
index[in->row - + diff] = flagNonZero; // 标记该对角线上有非零元
}
int *prefixSumIndex = (int *)malloc(sizeof(int)*(in->row + in->col - ));
prefixSumIndex[] = index[];
for (int i = ; i < in->row + in->col - ; i++) // 闭前缀和,prefixSumIndex[i] 表示原矩阵第 0 ~ i 条对角线中共有多少条非零对角线(含)
prefixSumIndex[i] = prefixSumIndex[i-] + index[i]; // index[in->row + in->col -2] 表示原矩阵非零对角线条数,等于 DIA 矩阵列数
DIA *out = initializeDIA(in->row, prefixSumIndex[in->row + in->col - ], in->col);
checkNULL(out); memset(out->data, , sizeof(int)*out->row * out->col);
for (int i = ; i < in->row + in->col - ; i++)
out->index[i] = index[i]; // index 搬进 out
for (int i = ; i < in->row; i++) // i,j 遍历原矩阵,将元素搬进 out
{
for (int j = ; j < in->col; j++)
{
int temp = j - i + in->row - ;
if (index[temp] == )
continue;
out->data[i * out->col + (temp > ? prefixSumIndex[temp - ] : )] = in->data[i * in->col + j]; // 第 row - 1 行第 0 列元素 temp == 0,单独处理
}
}
free(index);
free(prefixSumIndex);
return out;
} MAT * DIAToMAT(const DIA *in) // DIA转MAT
{
checkNULL(in);
MAT *out = initializeMAT(in->row, in->colOrigin);
checkNULL(out); int * inverseIndex = (int *)malloc(sizeof(int) * in->col);
for (int i = , j = ; i < in->row + in->col - ; i++) // 求一个 index 的逆,即 DIA 中第 i 列对应原矩阵第 inverseIndex[i] 对角线
{ // 原矩阵对角线编号 (row-1, 0) 为第 0 条,(0, 0) 为第 row - 1 条,(col-1, 0) 为第 row + col - 2 条
if (in->index[i] == )
{
inverseIndex[j] = i;
j++;
}
}
for (int i = ; i < in->row; i++) // i 遍历 in->data 行,j 遍历 in->data 列
{
for (int j = ; j < in->col; j++)
{
if (i < in->row - - inverseIndex[j] || i > inverseIndex[in->col - ] - inverseIndex[j]) // 跳过两边呈三角形的无效元素
continue;
out->data[i * in->col + inverseIndex[j] - in->row + ] = in->data[i * in->col + j]; // 利用 inverseIndex 来找钙元素在原距震中的位置
}
}
free(inverseIndex);
return out;
}
稀疏矩阵 part 2的更多相关文章
- [LeetCode] Sparse Matrix Multiplication 稀疏矩阵相乘
Given two sparse matrices A and B, return the result of AB. You may assume that A's column number is ...
- 转载:稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB
http://www.cnblogs.com/xbinworld/p/4273506.html 稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,很多稀疏度在9 ...
- poj 3735 Training little cats 矩阵快速幂+稀疏矩阵乘法优化
题目链接 题意:有n个猫,开始的时候每个猫都没有坚果,进行k次操作,g x表示给第x个猫一个坚果,e x表示第x个猫吃掉所有坚果,s x y表示第x个猫和第y个猫交换所有坚果,将k次操作重复进行m轮, ...
- 稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB
稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,很多稀疏度在90%甚至99%以上.因此我们需要有高效的稀疏矩阵存储格式.本文总结几种典型的格式:COO,CSR ...
- C语言 稀疏矩阵 压缩 实现
稀疏矩阵压缩存储的C语言实现 (GCC编译). /** * @brief C语言 稀疏矩阵 压缩 实现 * @author wid * @date 2013-11-04 * * @note 若代码存在 ...
- 三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述)
三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述) 用经典矩阵转置算法和普通的三元组矩阵转置在时间复杂度上都是不乐观的.快速转置算法在增加适当存储空间后实现快速转置具体原理见代码注释部 ...
- 稀疏矩阵乘法加法等的java实现
原创声明:本文系作者原创,转载请写明出处. 一.前言 前几天由于科研需要,一直在搞矩阵的稀疏表示的乘法,不过最近虽然把程序写出来了,还是无法处理大规模的矩阵(虽然已经是稀疏了).原因可能是 ...
- Matlab稀疏矩阵
一.矩阵存储方式 MATLAB的矩阵有两种存储方式,完全存储方式和稀疏存储方式 1.完全存储方式 将矩阵的全部元素按列存储,矩阵中的全部零元素也存储到矩阵中. 2.稀疏存储方式 仅存储矩阵所有的非零元 ...
- matlab——sparse函数和full函数(稀疏矩阵和非稀疏矩阵转换)
函数功能:生成稀疏矩阵 使用方法 :S = sparse(A) 将矩阵A转化为稀疏矩阵形式,即矩阵A中任何0元素被去除,非零元素及其下标组成矩阵S.如果A本身是稀疏的,sparse(S)返回S. S ...
- 稀疏矩阵coo_matrix的乘法
稀疏矩阵的乘法在做基于n-gram的分类的时候还是相当有用的,但是由于网上资料太少,所以折腾了几天才算折腾出来. 首先scipy包里常见的稀疏矩阵有三种形式, coo_matrix, csr_matr ...
随机推荐
- Spring的由来以及发展
Spring简史: 第一阶段:XML配置在Spring1.x时代,都是使用XML配置Bean,随着项目扩大,我们把XML文件切分成多个配置文件,那时候需要频繁地在开发类和配置文件之间切换 第二阶 ...
- 旁路、去耦、Bulk以及耦合电容的作用与区别
在硬件设计中有很多种电容,各种电容的功能.种类和电容容值各不相同.按照功能划分的话,最重要的几种电容分别称为:去耦电容(De-coupling Capacitor),旁路电容(Bypass Capac ...
- cookie 就是一些字符串信息
什么是 Cookie “cookie 是存储于访问者的计算机中的变量.每当同一台计算机通过浏览器请求某个页面时,就会发送这个 cookie.你可以使用JavaScript 来创建和取回cookie 的 ...
- Python argparse用法
import argparse import sys parser = argparse.ArgumentParser(description='this is for test.') parser. ...
- salt+jenkins+gitlab+ecs构建公司部署平台
1.网络架构图如下 2.采用这种方案的原因 1.现网机器都在各个省机房内网,或者堡垒机内部.无法直接从公司总部ssh到各个现网机器 2.现网机器可以访问到公网.因此可以从公网下载制作的tar包 3.每 ...
- 18.23 inline函数功能
GUN的C关键字,在函数定义中函数返回类型前加上关键字inline,可以把函数指定为内联函数.关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用 ...
- Window服务项目脚手架
本人最近工作用到window服务程序,于是尝试分享下经验,开源了一个window服务脚手架项目,把window服务程序必不可少的组件集成进去,如日志组件log4net,window服务挂在后台,用日志 ...
- Asp.Net : Page.RegisterStartupScript及 不执行的原因
RegisterStartupScript 把script放置在ASP.NET page的底部,而RegisterClientScriptBlock把script放置在ASP.NET page的顶部 ...
- Ubuntu16.04安装Python3.6 和pip(python3 各版本切换)
安装: sudo add-apt-repository ppa:jonathonf/python-3.6 sudo apt-get update sudo apt-get install python ...
- css 实现 左右div 等高, 同时父级div就是最高的子div的高度
原文地址:https://www.cnblogs.com/cbza/p/7145384.html 方法一: 通过父级overflow:hidden, 自己设置padding-bottom 和 mar ...