特殊矩阵的压缩存储
2016-12-10 15:46
204 查看
矩阵的压缩存储
这两天我们学的一直是数据结构,今天我们来说说矩阵的这个数据结构 之前在大一的时候我们就学习线性代数是就了解了矩阵的使用 ,但是我们主要讲的是 矩阵的计算方法。。。。。但是我们现在学习了编程语言 ,之后就要学会将矩阵存储起来 ,但是 有一些特殊的矩阵,如果我们将他们全部都存储起来的话之后,就会浪费很多的空间。。。。。
就比如说
对称矩阵的压缩存储
所谓对称矩阵,就是上三角 与下三角的数据都是相等的 , ,, ,如果我们将上三角与下三角都存储起来的话就显得有点多余了。。》》》》下面用图来说明一下吧!!!!!
上图表示就是一个对称矩阵,其中上三角与下三角的数据值一模一样的,
所以我们可以将这个矩阵压缩存储一下,只需要保存下三角的数据就可以了。。。
我们可以将这数据保存在数组里,,,,
压缩存储称矩阵存储时只需要存储上三角/下三角的数据,所以最多存储n(n+1)/2个数据。
对称矩阵和压缩存储的对应关系:下三角存储i>=j, SymmetricMatrix[i][j] ==Array[i*(i+1)/2+j]
写出代码是
//对称矩阵的压缩存储 template<class T> class SymmetricMatrix { public: SymmetricMatrix(T * a,size_t n) :_a(new T[n*(n+1)/2]) ,_n(n) { for(size_t i = 0 ;i < n; ++i ) { for(size_t j = 0 ;j < n;++j) { if(i >= j) { _a[i*(i+1)/2 +j] = a[i*n + j];//将下三角的值都放到数组里去;; } else { break; } } } } T& Access(size_t i ,size_t j)//得到每个位置的值 { if(i < j) { std::swap(i,j); } return _a[i*(i+1)/2+j]; } void Display()//打印矩阵 { for(size_t i = 0;i < _n;++i) { for(size_t j = 0;j < _n;++j) { cout<<Access(i,j)<<" "; } cout<<endl; } } protected: T * _a;//存储的下三角的数组指针 size_t _n;//矩阵的大小 };
//测试代码 void TestSymmetricMatrix() { int a [5][5]= { {0,1,2,3,4}, {1,0,1,2,3}, {2,1,0,1,2}, {3,2,1,0,1}, {4,3,2,1,0}, }; SymmetricMatrix<int> s1((int*)a,5); s1.Display(); }矩阵中 的特殊矩阵除了对称矩阵之外还有的是稀疏矩阵 。。。。
稀疏矩阵的压缩存储
稀疏矩阵也是矩阵,只不过它里面保存的值大多数都是无效的的,只有少数是有效的, 所以对于这类的矩阵 ,, ,, ,压缩存储是十分有必要的,为什么呢????
如果有有一个文件大约有 32G ,如果存到硬盘上就会很费空间,但是它里面有效的数据仅仅只有 100M的话
在这种情况下,使用压缩存储是十分有必要的。。。
关于这类矩阵我们要怎么来压缩存储呢????
我们可以只保存有效数据的坐标与有效值 。。。。。
我们保存的数据叫做是一个三元组 (实际上就是个结构体)
压缩存储值存储极少数的有效数据。使用{row,col,value}三元组存储每一个有效
数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放。
另外除了这个 ,, , ,我们还需要实现一个矩阵转置 , ,, ,得到转置矩阵的压缩存储
实现转置的方法总有很多种:::
在这里我来说两种 ,,, 一个是普通的转置 ,,,, 还有就是快速转置。》》》》
就用下面这个矩阵来说说吧!!!!
通过上图我们可以看出来 ,,,上面的图中转置之后只是之前的列换成是的转置后的行
因此我们可以将按照列优先遍历一遍转置前的存储 !!!!
按照列的先后顺序 插入到新的压缩存储中!!!!
这就是所谓的普通转置法》》》》》
上面的转置法 ,,,将原来生成的压缩数组 ,遍历了不只一遍
所谓的快速转置法也就是说 只需要遍历一次, 就可以得到转置后的存储。。。。
但是要怎么做 呢????
我们知道所谓转置 ,就是将之前的行换成了现在的列 。。。。。
所以我们只需要记录下之前的每列有多少个有效值 ,,,,
再用 一个数组记录下每列的数的该插入的其实坐标。。。。
只要知道这俩个我们就可以直接 , ,, , ,,遍历一次数组 ,就可以将 全部完成转置。。。。
实现代码
//稀疏矩阵的存储的三元组 template<class T> struct Triple { size_t _row;//保存元素的行 size_t _col;//保存元素的列 T _value;//保存元素的有效值 Triple(size_t row = 0,size_t col = 0 ,const T& value = T()) :_row(row) ,_col(col) ,_value(value) {} }; template<class T> class SparseMatrix { public: SparseMatrix(T* a,size_t m, size_t n,const T& invalid) :_a(vector<Triple<T>>()) ,_countrow(m) ,_countcol(n) ,_invalid(invalid) { for(size_t i = 0;i < m;i++) { for(size_t j = 0;j < n;j++) { if(a[i*n+j] != _invalid) { _a.push_back(Triple<T>(i,j,a[i*n+j])); } } } } SparseMatrix() {} //转置 SparseMatrix Transport() { SparseMatrix<T> s; s._a = vector<Triple<T>>(); s._a.reserve(_a.size()); s._countrow =_countcol; s._countcol =_countrow; s._invalid =_invalid; for(size_t i = 0 ;i < s._countrow;++i)//从第0列开始,向后 { for(size_t j = 0 ;j <_a.size();++j) { if(_a[j]._col == i)//如果是存储的当前列的数就插入 { s._a.push_back(Triple<T>(_a[j]._col,_a[j]._row,_a[j]._value)); } } } return s; } //快速转置 SparseMatrix FastTransport() { SparseMatrix<T> s; s._a = vector<Triple<T>>(); s._a.resize(_a.size()); s._countrow =_countcol; s._countcol =_countrow; s._invalid =_invalid; int* count = new int[s._countrow];//创建数组 count保存每一列的有效值个数 for(size_t i = 0; i < s._countrow;++i) { int m= 0 ; for(size_t j = 0 ;j <_a.size();++j) { if(_a[j]._col == i) { m++; } } count[i] = m; } int * start = new int[s._countrow];//创建数组start 保存每一列位置的起始值 *start = 0;//第一列位置的起始值为0 for(size_t i = 1;i < s._countrow;++i) { start[i] =start[i-1] + count[i-1]; } for(size_t i = 0 ;i < _a.size();++i) { s._a[start[_a[i]._col]] =Triple<T>(_a[i]._col,_a[i]._row,_a[i]._value); start[_a[i]._col]++;//每一列插入一个元素之后 ,,,其实位置向后移一位 } delete[] count;//释放开辟的这两段空间 delete[] start; return s; } void Dsiplay() { size_t idex = 0; for(size_t i = 0;i <_countrow;++i) { for(size_t j = 0;j < _countcol;++j) { if( idex < _a.size() && _a[idex]._row == i && _a[idex]._col == j) { cout<<_a[idex]._value<<" "; idex++; } else { cout<<_invalid<<" "; } } cout<<endl; } cout<<endl; } protected: vector<Triple<T>> _a;//保存压缩后的数据 size_t _countrow;//矩阵的行 size_t _countcol;//矩阵的列 T _invalid;//保存的是无效值 }; void TestSparseMatrix() { int array [6][5] = {{1, 0, 3, 0, 5}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {2, 0, 4, 0, 6}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; SparseMatrix<int> s((int*)array,6,5,0); s.Dsiplay(); SparseMatrix<int> s1 =s.Transport(); s1.Dsiplay(); SparseMatrix<int> s2 =s.FastTransport(); s2.Dsiplay(); }
相关文章推荐
- C++数组应用之特殊矩阵的压缩存储
- 数据结构——c语言描述 第五章 (1) 特殊矩阵的压缩存储
- 第九周:特殊矩阵的压缩存储
- 【数据结构】特殊矩阵的压缩存储2——稀疏矩阵
- C++数组应用之特殊矩阵的压缩存储
- 多维数组与特殊矩阵的压缩存储
- 特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- 数据结构-二维数组-特殊矩阵压缩存储
- 数据结构——特殊矩阵的压缩存储
- 各种特殊矩阵的压缩存储
- C++数组 特殊矩阵压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- 特殊矩阵的压缩存储
- 特殊矩阵的压缩存储(转自chunlanse2014)
- 特殊矩阵的压缩存储
- 特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储