假设在m*n的矩阵中,有t个元素不为0。令稀疏因子s=t/(m*n),通常认为s<0.05时称为稀疏矩阵。
目前创新互联公司已为上千家的企业提供了网站建设、域名、虚拟主机、网站改版维护、企业网站设计、东兰网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。有时为了节省存储空间,可以对这类矩阵进行压缩存储。所谓的压缩存储就是,为多个相同的值分配存储在一个空间,对零元不分配空间。而稀疏矩阵是只存储有效值,无效值只分配一个空间。
在这里我们用一个顺序表vector存储稀疏矩阵的有效值的行,列,值三个元素。
struct Triple { int _cow; int _col; T _value; Triple(int cow,int col,T value) :_cow(cow) , _col(col) , _value(value) {} Triple() :_cow(0) , _col(0) { } };
class SparseMatrix { public: SparseMatrix(T* a, int m, int n, const T& invalid) :_cow(m) , _col(n) , _invalue(invalid) { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (a[i*n + j] != invalid) { Tripletmp(i, j, a[i*n + j]); _a.push_back(tmp); } } } } protected: vector > _a; int _cow;//矩阵行数 int _col;//矩阵列数 T _invalue;//无效值 };
下面我们来讨论一下稀疏矩阵的转置,转置运算时最简单的一种矩阵运算。要得到转置矩阵,我们只要做到三点。
将矩阵的行列值相互交换
每个三元组的i和j相互交换
重排三元组之间的次序便可以实现转置
SparseMatrix
Transport() { SparseMatrix tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; for (size_t i = 0; i < _col; ++i)//遍历每一列,找到每一列有效值 { size_t index = 0; while (index < _a.size()) { if (_a[index]._col == i) { Triple tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a.push_back(tp); } index++; } } return tmp; }
对于矩阵的转置,我们首先得要了解转置后行列的变化。转置前的行变成了转置后的列。对于三元组顺序表中的元素是遵循行优先存储的。所以要得到转置后的每一行的有效值,只要循环遍历转置前的每一列即可。
矩阵的转置可以优化,使用快速转置。
SparseMatrixFastTransport() { SparseMatrix tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; tmp._a.resize(_a.size()); int* cowCount = new int[_col]; int* cowStart = new int[_col]; memset(cowCount, 0, sizeof(int)*_col); memset(cowStart, 0, sizeof(int)*_col); size_t index = 0; while (index < _a.size()) { cowCount[_a[index++]._col]++; cowStart[0]; for (size_t i = 1; i < _col; ++i) { cowStart[i] = cowStart[i - 1] + cowCount[i - 1]; } } index = 0; while (index < _a.size()) { int& cowBegin = cowStart[_a[index]._col]; Triple tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a[cowBegin] = tp; cowBegin++; index++; } return tmp; }
快速转置的思想是开辟两个数组用来存每一行有效值的个数,另一个用来存每个有效值在转置后顺序表vector中的起始位置。使用数组可以快速找到有效数据在转置后顺序表中的位置
以下是完整代码:
#pragma once #include#include using namespace std; template struct Triple { int _cow; int _col; T _value; Triple(int cow,int col,T value) :_cow(cow) , _col(col) , _value(value) {} Triple() :_cow(0) , _col(0) { } }; template class SparseMatrix { public: SparseMatrix(T* a, int m, int n, const T& invalid) :_cow(m) , _col(n) , _invalue(invalid) { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (a[i*n + j] != invalid) { Triple tmp(i, j, a[i*n + j]); _a.push_back(tmp); } } } } SparseMatrix() :_cow(0) , _col(0) {} SparseMatrix Transport() { SparseMatrix tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; for (size_t i = 0; i < _col; ++i) { size_t index = 0; while (index < _a.size()) { if (_a[index]._col == i) { Triple tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a.push_back(tp); } index++; } } return tmp; } SparseMatrix FastTransport() { SparseMatrix tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; tmp._a.resize(_a.size()); int* cowCount = new int[_col]; int* cowStart = new int[_col]; memset(cowCount, 0, sizeof(int)*_col); memset(cowStart, 0, sizeof(int)*_col); size_t index = 0; while (index < _a.size()) { cowCount[_a[index++]._col]++; cowStart[0]; for (size_t i = 1; i < _col; ++i) { cowStart[i] = cowStart[i - 1] + cowCount[i - 1]; } } index = 0; while (index < _a.size()) { int& cowBegin = cowStart[_a[index]._col]; Triple tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a[cowBegin] = tp; cowBegin++; index++; } return tmp; } void Display() { size_t index = 0; for (int i = 0; i < _cow; i++) { for (int j = 0; j < _col; j++) { if (index < _a.size()//此处必须加index<_a.size()这个条件, //并且在最前面访问到最后一个有效值后再_a[index]会访问越界 &&_a[index]._cow == i && _a[index]._col == j) { cout << _a[index]._value << " "; ++index; } else { cout << _invalue << " "; } } cout << endl; } cout << endl; } protected: vector > _a; int _cow;//矩阵行数 int _col;//矩阵列数 T _invalue; };
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
分享名称:稀疏矩阵的转置与快速转置-创新互联
文章URL:http://lswzjz.com/article/dddsod.html