稀疏矩阵及稀疏矩阵的压缩存储
2016-04-20 16:41
501 查看
没有经过处理的稀疏矩阵其实就是一个特殊的二维数组,数组中的大部分元素是0或者其他类型的非法值,只有少数几个非零元素。
为了实现压缩存储,可以只存储稀疏矩阵的非0元素。在存储稀疏矩阵中的非0元素时,必须要存储该元素的行列号以及元素值。
我们可以封装一个三元组类来存储这些元素。
创建稀疏矩阵。利用容器,可以非常方便的存储这些元素,相当于用一个动态数组来存储。要求按照行优先的顺序存储,方便打印稀疏矩阵时,按照行列顺序依次打印非0元素。
列序转置法:以矩阵的列序进行转置,这样经过转置后得到的三元组容器序列正好是以行优先存储的。时间复杂度为 O(_colMatrix*_array.size())
快速转置法:事先确定矩阵每一列第一个元素在容器中的位置,在对稀疏矩阵转置时,通过对原容器的遍历,依次直接将元素放在新容器的恰当位置。时间复杂度为O(_colMatrix+_array.size())
转置前,要先确定原矩阵每一列非零元素的个数,然后求出每一列非零元素在新容器中的正确位置。
设置两个整型数组RowCounts[_colMatrix]、RowStart[_colMatrix]分别用来存放三元组容器中每一列非零元素的个数以及每一列第一个非零元素在新容器中的正确位置。
RowStart[0] = 0; RowStart[col] = RowStart[col - 1] + RowCounts[col - 1];
为了实现压缩存储,可以只存储稀疏矩阵的非0元素。在存储稀疏矩阵中的非0元素时,必须要存储该元素的行列号以及元素值。
我们可以封装一个三元组类来存储这些元素。
//三元组 template<class T> struct Triple { size_t _row; //行 size_t _col; //列 T _value; //值 Triple<T>::Triple() //定义无参的构造函数 {} Triple(size_t row, size_t col,T value) :_row(row) , _col(col) , _value(value) {} };
创建稀疏矩阵。利用容器,可以非常方便的存储这些元素,相当于用一个动态数组来存储。要求按照行优先的顺序存储,方便打印稀疏矩阵时,按照行列顺序依次打印非0元素。
template<class T> //利用容器实现稀疏矩阵的压缩存储 SparseMatrix<T>::SparseMatrix(const T* array, size_t row, size_t col, const T& invalid) //初始化 :_rowMatrix(row) , _colMatrix(col) ,_invalid(invalid) { for (size_t i = 0; i < _rowMatrix; ++i) { for (size_t j = 0; j < _colMatrix; ++j) { if (array[i*col + j] != invalid) { Triple<T> cur(i, j, array[i*col + j]); _array.push_back(cur); } } } }
列序转置法:以矩阵的列序进行转置,这样经过转置后得到的三元组容器序列正好是以行优先存储的。时间复杂度为 O(_colMatrix*_array.size())
template<class T> //列序转置 SparseMatrix<T> SparseMatrix<T>::Transport() { assert(_array.size()!=0); SparseMatrix<T> ret; ret._rowMatrix = _colMatrix; ret._colMatrix = _rowMatrix; ret._invalid = _invalid; ret._array.reserve(this->_array.size()); for (size_t j = 0; j < _colMatrix; j++) { size_t index = 0; while (index < _array.size()) { if (_array[index]._col == j) { Triple<T> tp(_array[index]._col, _array[index]._row, _array[index]._value); ret._array.push_back(tp); } index++; } if (this->_array.size() == ret._array.size()) { break; } } return ret; }
快速转置法:事先确定矩阵每一列第一个元素在容器中的位置,在对稀疏矩阵转置时,通过对原容器的遍历,依次直接将元素放在新容器的恰当位置。时间复杂度为O(_colMatrix+_array.size())
转置前,要先确定原矩阵每一列非零元素的个数,然后求出每一列非零元素在新容器中的正确位置。
设置两个整型数组RowCounts[_colMatrix]、RowStart[_colMatrix]分别用来存放三元组容器中每一列非零元素的个数以及每一列第一个非零元素在新容器中的正确位置。
RowStart[0] = 0; RowStart[col] = RowStart[col - 1] + RowCounts[col - 1];
列号 | 0 | 1 | 2 | 3 | 4 |
RowCounts[col] | 2 | 0 | 2 | 0 | 2 |
RowStart[col] | 0 | 2 | 2 | 4 | 4 |
template<class T> SparseMatrix<T> SparseMatrix<T>::FastTranaport() //快速转置 { assert(_array.size() != 0); size_t index = 0; SparseMatrix<T> ret; ret._rowMatrix = _colMatrix; ret._colMatrix = _rowMatrix; ret._invalid = _invalid; ret._array.resize(_array.size()); int *RowCounts = new int[_colMatrix]; int *RowStart = new int[_colMatrix]; memset(RowCounts, 0, _colMatrix*sizeof(int)); memset(RowStart, 0, _colMatrix*sizeof(int)); for (size_t i = 0; i < _array.size(); i++) { RowCounts[_array[i]._col]++; } RowStart[0] = 0; for (size_t i = 1; i < _colMatrix; i++) { RowStart[i] = RowStart[i - 1] + RowCounts[i - 1]; } Triple<T> tp; for (size_t i = 0; i < _array.size(); i++) { tp._row = _array[i]._col; tp._col = _array[i]._row; tp._value = _array[i]._value; ret._array[RowStart[_array[i]._col]++] = tp; } delete [] RowCounts; delete [] RowStart; return ret; }
相关文章推荐
- 【小松教你手游开发】【unity实用技能】一键改变UI字体
- 作为项目经理的7个经验教训总结
- 华为与赛伯乐观点合璧,勾勒物联网商业模式
- 怎么实现div左右移动|animate animation hover的区别
- Redis支持5种数据类型之一Strings
- Contains Duplicate
- 设计模式(7)之装饰模式
- 腾讯2016实习生招聘后台研发面试经
- 清空cookie
- QT信号和槽以结构体为参数传递复杂数据
- jquery中的表单验证,,,,
- 我的屌丝giser成长记-研二篇
- 【好工具分享】如何进行屏幕录像记录操作步骤录制教程保存回放
- C++里的继承和多态(中)——分析单继承、多继承、菱形继承(不含虚函数)
- 添加RichEdit控件后对话框不显示
- Smali和逆向分析
- hdu 2049 不easy系列之(4)——考新郎
- ajax跨域解决方案2
- 【好工具分享】如何进行屏幕录像记录操作步骤录制教程保存回放
- linq之into子句