矩阵的压缩存储以及转置
来源:互联网 发布:杨紫 否认整容 知乎 编辑:程序博客网 时间:2024/06/03 12:31
一.对称矩阵的压缩存储
1.什么是对称矩阵?
设一个N*N的方阵A,A中任意元素Aij,当且仅当Aij == Aji(0 <= i <= N-1&& 0 <= j <= N-1),
则矩阵A是对称矩阵。以矩阵的对角线为分隔,分为上三角和下三角。
2.对称矩阵的压缩存储
压缩存储称矩阵存储时只需要存储上三角/下三角的数据,所以最多存储n(n+1)/2个数据。对称矩阵
和压缩存储的对应关系:下三角存储i>=j, SymmetricMatrix[i][j] ==Array[i*(i+1)/2+j]
3.对称矩阵例子:
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
4.代码实现
//对称矩阵的压缩存储template<class T>class SymmetricMatrix{public:SymmetricMatrix(T* a, size_t N)//将矩阵存放到下三角中:_N(N){for (size_t i = 0; i < _N; ++i){for (size_t j = 0; j < _N; ++j){if (i >= j){_a.push_back(a[i*_N + j]);}elsebreak;}}}T& Access(size_t i, size_t j)//打印矩阵的任意位置{if (i < j)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){if (i >= j)cout << Access(i, j)<<" ";elsecout << Access(j, i)<<" ";}cout << endl;}}protected:vector<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> s((int*)a, 5);cout << s.Access(3, 1) << endl;cout << s.Access(1, 3) << endl;s.Display();}
二.稀疏矩阵的压缩存储
1.什么样的矩阵为稀疏矩阵?
一个M行N列(即M*N)的矩阵,矩阵中有效值得个数远小于无效值的个数,且这些数据的
分布没有规律。
2.稀疏矩阵的压缩存储?
压缩存储值存储极少数的有效数据。使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中
的位置,以行优先级先后顺序依次存放。
3.稀疏矩阵的例子:
一个六行五列的稀疏矩阵(M=6,N=5)
1 0 3 0 5 0
0 0 0 0 0 0
0 0 0 0 0 0
1 0 3 0 5 0
0 0 0 0 0 0
0 0 0 0 0 0
4.代码实现:
//稀疏矩阵的压缩存储template<class T>struct Triple //三元组存放有效数据的值以及行列值{T _value;size_t _row;size_t _col;};template<class T,size_t M,size_t N>class SparseMatrix{public:SparseMatrix(T a[M][N], const T& invalid) //将有效值压入三元组:_invalid(invalid){for (size_t i = 0; i < M; ++i){for (size_t j = 0; j < N; ++j){if (a[i][j] != _invalid){Triple<T> t;t._value = a[i][j];t._row = i;t._col = j;_a.push_back(t);}}}}T& Access(size_t i ,size_t j){size_t index = 0;while (index < _a.size()){if (_a[index]._row == i&&_a[index]._col == j){return _a[index]._value;}++index;}return _invalid;}void Display(){size_t index = 0;for (size_t i = 0; i < M; ++i){for (size_t j = 0; j < N; ++j){if ((index < _a.size()) && (_a[index]._row == i)&&(_a[index]._col == j)){cout << _a[index]._value << " ";++index;}else{cout << _invalid << " ";}}cout << endl;}cout << endl;}protected:vector<Triple<T>> _a;T _invalid;};void TestSparseMatrix(){int array[6][5] = { { 1, 0, 3, 0, 5 },{ 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0 },{ 1, 0, 3, 0, 5 },{ 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0 } };SparseMatrix<int,6,5> sm(array,0);cout << sm.Access(3, 0) << endl;cout << sm.Access(3, 1) << endl;sm.Display();}
三.稀疏矩阵的转置
1.普通转置:
矩阵的转置:将原矩阵的行、列互换,也就是将[i][j]和[j][i]的位置上的数据互换
例如:
算法思想:
三元组里边存放数据是按行优先存储的,矩阵的转置也就是将原矩阵的行、列互换,原矩阵是M行N列的,
那么转置后的矩阵是N行M列的,用一个for循环遍历原矩阵的每一列,然后和三元组里边的每一列相比较,如果
列相等就将原矩阵三元组里边的这个有效数据的值以及行列值,存放到转置后的三元组里边
代码实现:
//矩阵的转置template<class T>struct Triple //三元组存放有效数据的值以及行列值{T _value;size_t _row;size_t _col;};template<class T,size_t M,size_t N>class SparseMatrix{friend SparseMatrix<T, N, M>;public:SparseMatrix():_a(NULL), _invalid(T()){}SparseMatrix(T a[M][N], const T& invalid) //将有效值压入三元组:_invalid(invalid){for (size_t i = 0; i < M; ++i){for (size_t j = 0; j < N; ++j){if (a[i][j] != _invalid){Triple<T> t;t._value = a[i][j];t._row = i;t._col = j;_a.push_back(t);}}}}SparseMatrix<T, N, M> Transport() //矩阵的转置{SparseMatrix<T, N, M> tsm;tsm._a.reserve(_a.size());for (size_t i = 0; i < N; i++)//转置前的每一列是转置后的每一行{size_t index = 0;while (index < _a.size()){if (_a[index]._col == i){Triple<T> t;t._col = _a[index]._row;t._row = _a[index]._col;t._value = _a[index]._value;tsm._a.push_back(t);}++index;}}return tsm;}void Display(){size_t index = 0;for (size_t i = 0; i < M; ++i){for (size_t j = 0; j < N; ++j){if ((index < _a.size()) && (_a[index]._row == i)&&(_a[index]._col == j)){cout << _a[index]._value << " ";++index;}else{cout << _invalid << " ";}}cout << endl;}cout << endl;}protected:vector<Triple<T>> _a;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,6,5> sm(array,0);sm.Display();SparseMatrix<int, 5, 6> tsm;tsm = sm.Transport();tsm.Display();}
时间复杂度高所以引入了快速转置
2.矩阵的快速转置:
算法思想:
实现代码 :
//矩阵的快速转置template<class T>struct Triple //三元组存放有效数据的值以及行列值{T _value;size_t _row;size_t _col;};template<class T,size_t M,size_t N>class SparseMatrix{friend SparseMatrix<T, N, M>;public:SparseMatrix():_a(NULL), _invalid(T()){}SparseMatrix(T a[M][N], const T& invalid) //将有效值压入三元组:_invalid(invalid){for (size_t i = 0; i < M; ++i){for (size_t j = 0; j < N; ++j){if (a[i][j] != _invalid){Triple<T> t;t._value = a[i][j];t._row = i;t._col = j;_a.push_back(t);}}}}SparseMatrix<T, N, M> FastTransport()//矩阵的快速转置{SparseMatrix<T, N, M>tsm;int rows[N] = { 0 };size_t index = 0;//转置后每一行的数据个数while (index < _a.size()){rows[_a[index]._col]++;++index;}//转置后每一行的每一个数的起始位置int starts[N] = { 0 };starts[0] = 0;for (size_t i = 1; i < N; ++i){starts[i] = starts[i - 1] + rows[i - 1];}index = 0;tsm._a.resize(_a.size());//开辟有效数据个数的空间while (index < _a.size()){size_t row = _a[index]._col;Triple<T> t;t._value = _a[index]._value;t._col = _a[index]._row;t._row = _a[index]._col;tsm._a[starts[row]++] = t;++index;}return tsm;}void Display(){size_t index = 0;for (size_t i = 0; i < M; ++i){for (size_t j = 0; j < N; ++j){if ((index < _a.size()) && (_a[index]._row == i)&&(_a[index]._col == j)){cout << _a[index]._value << " ";++index;}else{cout << _invalid << " ";}}cout << endl;}cout << endl;}protected:vector<Triple<T>> _a;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,6,5> sm(array,0);sm.Display();SparseMatrix<int, 5, 6> tsm;tsm = sm.FastTransport();tsm.Display();}
- 矩阵的压缩存储以及转置
- 稀疏矩阵的压缩存储以及快速转置
- 对称矩阵和稀疏矩阵以及它们的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 矩阵的压缩存储
- 稀疏矩阵的压缩存储和逆置,以及快速逆置,以及稀疏矩阵的加法
- 稀疏矩阵的压缩存储及转置
- 稀疏矩阵的压缩存储及其转置算法
- 稀疏矩阵的压缩存储与转置
- 稀疏矩阵的压缩存储和转置
- 【代码】稀疏矩阵的压缩存储与转置算法
- 稀疏矩阵的压缩存储与转置
- 扩展欧几里得最小整数解
- TI DSP系列分类
- json
- Java 中extends与implements使用方法
- qt 之 国际化(中英文切换)
- 矩阵的压缩存储以及转置
- [ios/oc] UIWebView 首次非主线程调用导致crash
- Thread->sleep、wait、join使用
- 自定义EXCEL导出功能
- 每日一题 No.38 AI贪吃蛇(三)
- 《FreeSWITCH: VoIP实战》:PSTN 与 PBX 业务
- Discuz!开发之HTML转Discuz代码(bbcode)函数html2bbcode()
- 软件测试面试(一)
- 哈希表及处理冲突的方法