▶ 各种稀疏矩阵数据结构之间的转化

● 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的更多相关文章

  1. [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 ...

  2. 转载:稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

    http://www.cnblogs.com/xbinworld/p/4273506.html 稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,很多稀疏度在9 ...

  3. poj 3735 Training little cats 矩阵快速幂+稀疏矩阵乘法优化

    题目链接 题意:有n个猫,开始的时候每个猫都没有坚果,进行k次操作,g x表示给第x个猫一个坚果,e x表示第x个猫吃掉所有坚果,s x y表示第x个猫和第y个猫交换所有坚果,将k次操作重复进行m轮, ...

  4. 稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

    稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,很多稀疏度在90%甚至99%以上.因此我们需要有高效的稀疏矩阵存储格式.本文总结几种典型的格式:COO,CSR ...

  5. C语言 稀疏矩阵 压缩 实现

    稀疏矩阵压缩存储的C语言实现 (GCC编译). /** * @brief C语言 稀疏矩阵 压缩 实现 * @author wid * @date 2013-11-04 * * @note 若代码存在 ...

  6. 三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述)

    三元组表压缩存储稀疏矩阵实现稀疏矩阵的快速转置(Java语言描述) 用经典矩阵转置算法和普通的三元组矩阵转置在时间复杂度上都是不乐观的.快速转置算法在增加适当存储空间后实现快速转置具体原理见代码注释部 ...

  7. 稀疏矩阵乘法加法等的java实现

    原创声明:本文系作者原创,转载请写明出处. 一.前言       前几天由于科研需要,一直在搞矩阵的稀疏表示的乘法,不过最近虽然把程序写出来了,还是无法处理大规模的矩阵(虽然已经是稀疏了).原因可能是 ...

  8. Matlab稀疏矩阵

    一.矩阵存储方式 MATLAB的矩阵有两种存储方式,完全存储方式和稀疏存储方式 1.完全存储方式 将矩阵的全部元素按列存储,矩阵中的全部零元素也存储到矩阵中. 2.稀疏存储方式 仅存储矩阵所有的非零元 ...

  9. matlab——sparse函数和full函数(稀疏矩阵和非稀疏矩阵转换)

    函数功能:生成稀疏矩阵 使用方法 :S = sparse(A) 将矩阵A转化为稀疏矩阵形式,即矩阵A中任何0元素被去除,非零元素及其下标组成矩阵S.如果A本身是稀疏的,sparse(S)返回S. S ...

  10. 稀疏矩阵coo_matrix的乘法

    稀疏矩阵的乘法在做基于n-gram的分类的时候还是相当有用的,但是由于网上资料太少,所以折腾了几天才算折腾出来. 首先scipy包里常见的稀疏矩阵有三种形式, coo_matrix, csr_matr ...

随机推荐

  1. FFT算法详解

    啊…本来觉得这是个比较良心的算法没想到这么抽搐这个算法真是将一个人的自学能力锻炼到了极致qwqqwqqwq 好的,那我们就开始我们的飞飞兔FFTFFTFFT算法吧! 偷偷说一句,FFTFFTFFT的代 ...

  2. RabbitMQ全网资料收集

    RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有很多公开标准 ...

  3. React Native 开发环境搭建

    1.安装 Python 2,不知道是否已支持 Python 3 2.安装 node,npm... 修改 npm 镜像,不建议使用 cnpm,cnpm 安装模块的路径与 npm 有差别 npm conf ...

  4. 16. Antimalware (反病毒 3个)

    Malwarebytes反恶意软件是为Windows的恶意软件扫描程序. 作者声称使用各种技术来查找其他恶意软件扫描仪检测不到的恶意软件. 有一个有限选项的免费试用版和支持能够运行扫描计划的完整版本, ...

  5. EBS查询在线用户

    转自:https://www.cnblogs.com/benio/archive/2011/03/10/1979417.html SELECT u.user_name, app.application ...

  6. 芯灵思SinlinxA33开发板 Linux平台总线设备驱动

    1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...

  7. 解决解决httpd: Could not reliably determine the server's fully qualified domain name

    vi /etc/httpd/conf/httpd.conf   加入一句  ServerName  localhost:80 参考:https://www.cnblogs.com/52linux/ar ...

  8. OTB数据库上各tracker评测结果

    后面两张success plot分别是按照threshold和auc排序 各tracker说明: Year2015: [CF2] 实验结果比论文中的结果好,原因是我运行的是作者后期又更新过的代码,作者 ...

  9. C编程中printf不加'\n'不输出

    有时,使用printf("a=%d",a);并不一定会输出显示,只有当在格式化输出时加上'\n'才能输出,如printf("a=%d\n",a); 由于unix ...

  10. Python学习基本小练习

    对于python的10个小练习做下笔记 1.使用while循环输入1 2 3 4 5 6 8 9 10...自己写的代码如下: num1 = 0 while num1 < 10: num1 = ...