特殊矩阵的压缩存储
来源:互联网 发布:淘宝卖东西要交税吗 编辑:程序博客网 时间:2024/05/01 02:35
矩阵的压缩存储
这两天我们学的一直是数据结构,今天我们来说说矩阵的这个数据结构 之前在大一的时候我们就学习线性代数是就了解了矩阵的使用 ,但是我们主要讲的是 矩阵的计算方法。。。。。
但是我们现在学习了编程语言 ,之后就要学会将矩阵存储起来 ,但是 有一些特殊的矩阵,如果我们将他们全部都存储起来的话之后,就会浪费很多的空间。。。。。
就比如说
对称矩阵的压缩存储
所谓对称矩阵,就是上三角 与下三角的数据都是相等的 , ,, ,如果我们将上三角与下三角都存储起来的话就显得有点多余了。。》》》》
下面用图来说明一下吧!!!!!
上图表示就是一个对称矩阵,其中上三角与下三角的数据值一模一样的,
所以我们可以将这个矩阵压缩存储一下,只需要保存下三角的数据就可以了。。。
我们可以将这数据保存在数组里,,,,
压缩存储称矩阵存储时只需要存储上三角/下三角的数据,所以最多存储n(n+1)/2个数据。
对称矩阵和压缩存储的对应关系:下三角存储i>=j, SymmetricMatrix[i][j] ==Array[i*(i+1)/2+j]
对称矩阵和压缩存储的对应关系:下三角存储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
- 特殊矩阵的压缩存储
- 特殊矩阵的压缩存储
- 特殊矩阵的压缩存储
- 特殊矩阵的压缩存储
- 各种特殊矩阵的压缩存储
- 第九周:特殊矩阵的压缩存储
- 矩阵的压缩存储--特殊矩阵--三角矩阵
- 矩阵的压缩存储--特殊矩阵--带状矩阵
- 数据结构:矩阵的压缩存储(特殊矩阵)
- 特殊 矩阵 的 压缩
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- C++数组应用之特殊矩阵的压缩存储
- Android 判断程序是否是第一次启动
- Xposed Android hook框架入门 -开发步骤
- 接口java.util.Map.Entry的使用
- 倾斜图像
- vim 常用操作
- 特殊矩阵的压缩存储
- Windows环境下Spring Boot+Docker构建应用
- 古典加密
- 身份证的校验方法
- 验证码自动识别的价值与意义
- 将nginx+tomcat集成迁移到二代swarm
- 木马病毒隐身穿墙术解密之花指令和终止进程
- 【前端开发框架】面向UI编程框架:ui.js框架思路详细设计
- ubantu12.04中安装g++编译器