特殊矩阵的压缩存储

来源:互联网 发布:淘宝卖东西要交税吗 编辑:程序博客网 时间:2024/05/01 02:35

矩阵的压缩存储

这两天我们学的一直是数据结构,今天我们来说说矩阵的这个数据结构  之前在大一的时候我们就学习线性代数是就了解了矩阵的使用 ,但是我们主要讲的是 矩阵的计算方法。。。。。
但是我们现在学习了编程语言 ,之后就要学会将矩阵存储起来  ,但是 有一些特殊的矩阵,如果我们将他们全部都存储起来的话之后,就会浪费很多的空间。。。。。
就比如说   

对称矩阵的压缩存储

  所谓对称矩阵,就是上三角 与下三角的数据都是相等的  , ,, ,如果我们将上三角与下三角都存储起来的话就显得有点多余了。。》》》》
下面用图来说明一下吧!!!!!


上图表示就是一个对称矩阵,其中上三角与下三角的数据值一模一样的,
所以我们可以将这个矩阵压缩存储一下,只需要保存下三角的数据就可以了。。。
我们可以将这数据保存在数组里,,,,
压缩存储称矩阵存储时只需要存储上三角/下三角的数据,所以最多存储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;//第一列位置的起始值为0for(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();}











0 0