对称矩阵与稀疏矩阵(转置)
来源:互联网 发布:网络文字编辑兼职 编辑:程序博客网 时间:2024/04/29 22:44
对称矩阵:n*n的方阵,对于矩阵的任意元素,aij=aji时(i和j都大于等于0小于n)
因为该矩阵的上三角和下三角的数据相同,为了节省空间,我们可以只存储下三角或上三角的元素,这种存储方式称为矩阵的压缩
矩阵压缩后的结构就可以是一个一维数组。
存储的个数是n*(n+1)/2(等差数列),任意元素在一维数组中是array[i*(i+1)/2+j];
对称矩阵的压缩储存
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>#include<vector>using namespace std;template <class T> //对称矩阵的压缩class SymmetricMartic{public: SymmetricMartic(T* a, size_t N)//将二维数组当成一维数组在一维数组 :_N(N) { _Martix = new T[N*(N + 1) / 2];//先给压缩矩阵开辟空间 size_t index = 0; for (size_t i = 0; i < N; i++) { for (size_t j = 0; j < N; j++) { if (i >= j)//存储下三角 { _Martix[index++] = a[i*N + j];//把二维数组当成一维数组遍历a[i*N+j] } else { break; } } } } ~SymmetricMartic() { delete _Martix; _Martix = NULL; _N = 0; } void Display() { for (size_t i = 0; i<_N; i++) { for (size_t j = 0; j < _N; j++) { cout << Access(i, j) << " "; } cout << endl; } cout << endl; } const T& Access(size_t i,size_t j) const//实现一个接口,当还原上三角的元素是应在压缩矩阵存储的下三角寻找对应,将i,j交换,就可以找到对应元素 { if (j > i) { swap(i,j);//交换i,j } return _Martix[i * (i + 1) / 2 + j];//返回(i,j)位置在压缩矩阵中对应位置元素 } void fun() { for (size_t i = 0; i < _N*(_N+1)/2; i++) { cout << _Martix[i] << " "; } cout << endl; }protected: T* _Martix;//压缩存储的一维数组 size_t _N;//N*N矩阵};
void TestSymmetricMartic(){ 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 }, }; SymmetricMartic<int> sm((int*)a, 5); cout << "_Martix:"; sm.fun(); cout << endl; sm.Display();}
结果
稀疏矩阵
M*N的矩阵,矩阵中有效值的个数远小于无效值的个数,且这些数据分布没有规律。
我们要先定义一个三元组Triple来存储元素及行列。
template <class T>struct Triple{ T _value; size_t _row; size_t _col; Triple(size_t row=0, size_t col=0, const T& value=0) : _row(row) , _col(col) , _value(value) {}};
按行存储它的有效值,不知道需要开辟多大空间,这样就可以定义成一个vector,自己增容,将这些有效值push_back进去。
//稀疏矩阵template <class T>struct Triple{ T _value; size_t _row; size_t _col; Triple(size_t row=0, size_t col=0, const T& value=0) : _row(row) , _col(col) , _value(value) {}};template<class T>class SparseMartix{public: SparseMartix(T* a=0, size_t m=0, size_t n=0, const T& invalid=T()) :_rowsize(m) , _colsize(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)//判断是否是有效值 { Triple<T> temp(i, j, a[i * n + j]);//构造一个三元组 _a.push_back(temp);//插入到顺序表中 } } } } //遍历存储有效值三元组的vector如果有对应的i,j,将其直接打印,若没有打印invalid void Display() { size_t index = 0; for (size_t i = 0; i < _rowsize; i++) { for (size_t j = 0; j < _colsize; j++) { if (index<_a.size()&&_a[index]._row == i&&_a[index]._col == j)//遍历vector时它首先满足index<size() { cout << _a[index]._value << " "; index++; } else { cout << _invalid << " "; } } cout << endl; } cout << endl; }protected: vector<Triple<T>> _a; size_t _rowsize; size_t _colsize; T _invalid;};
接下来实现一下稀疏矩阵的转置:元素对应的i,j交换,aij–>aji
方法
第一种方法: 转置后的行对应转置前的列,用列(i)来遍历存储有效值的vector,在vector寻找第n列的元素,_a[index]._col==i,将push_back到一个新的vector sm,最后返回sm.
第二种方法:高效些,快速转置,快速定位。
代码实现:
//稀疏矩阵template <class T>struct Triple{ T _value; size_t _row; size_t _col; Triple(size_t row=0, size_t col=0, const T& value=0) : _row(row) , _col(col) , _value(value) {}};template<class T>class SparseMartix{public: SparseMartix(T* a=0, size_t m=0, size_t n=0, const T& invalid=T()) :_rowsize(m) , _colsize(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)//判断是否是有效值 { Triple<T> temp(i, j, a[i * n + j]);//构造一个三元组 _a.push_back(temp);//插入到顺序表中 } } } } //遍历存储有效值三元组的vector如果有对应的i,j,将其直接打印,若没有打印invalid void Display() { size_t index = 0; for (size_t i = 0; i < _rowsize; i++) { for (size_t j = 0; j < _colsize; j++) { if (index<_a.size()&&_a[index]._row == i&&_a[index]._col == j)//遍历vector时它首先满足index<size() { cout << _a[index]._value << " "; index++; } else { cout << _invalid << " "; } } cout << endl; } cout << endl; } SparseMartix<T> Transport()//稀疏矩阵的转置 { SparseMartix<T> sm;//转置后三元组内容 sm._colsize = _rowsize; sm._rowsize = _colsize; sm._invalid = _invalid; for (size_t i = 0; i < _colsize; i++)//以列来遍历存储 { size_t index = 0; while (index < _a.size()) { if (_a[index]._col == i) { Triple<T> temp(_a[index]);//构造新的三元组内容,并且交换行列,插入sm中 swap(temp._col, temp._row); sm._a.push_back(temp); } index++; } } return sm; } SparseMartix<T> FastTransport()//稀疏矩阵的快速转置 { SparseMartix<T> sm; sm._colsize = _rowsize; sm._rowsize = _colsize; sm._invalid = _invalid; sm._a.resize(_a.size());//定义数组count,start,开辟空间并初始化 int* count = new int[_colsize]; memset(count, 0, sizeof(int)*_colsize); int* start = new int[_colsize]; size_t index = 0; while (index < _a.size())//统计每一列的元素,以对应的列数作为count的下标 { count[_a[index]._col]++; index++; } start[0] = 0; for (size_t i = 1; i < _colsize; i++)//算出start的值 { start[i] = start[i - 1] + count[i - 1]; } //快速定位 index = 0; while (index < _a.size()) { int row = _a[index]._col;//取出_a元素对应的列数 Triple<T> temp(_a[index]); swap(temp._col, temp._row); sm._a[start[row]] = temp;//列数在start对应的值就是在_a中的位置 start[row]++; index++; } delete[] count; delete[] start; return sm; }protected: vector<Triple<T>> _a; size_t _rowsize; size_t _colsize; T _invalid;};
//测试函数void TestSparseMartix(){ int a[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 } }; SparseMartix<int> sm((int*)a, 6, 5, 0); sm.Display(); SparseMartix<int> ret1 = sm.Transport(); ret1.Display(); SparseMartix<int> ret2 = sm.FastTransport(); ret2.Display();}
0 0
- 对称矩阵与稀疏矩阵(转置)
- 对称与稀疏矩阵
- 对称矩阵、稀疏矩阵
- 【数据结构】稀疏矩阵,对称矩阵
- 对称矩阵、稀疏矩阵的压缩存储
- 对称矩阵&稀疏矩阵的两种转置算法
- 对称矩阵及稀疏矩阵浅谈
- 对称矩阵、稀疏矩阵及矩阵的逆置与加法
- 矩阵-----对称矩阵及其压缩存储&&稀疏矩阵
- 【矩阵】对称矩阵及稀疏矩阵的压缩存储
- 数据结构--稀疏矩阵(转置)
- 数据结构 对称矩阵的压缩存储与稀疏矩阵的转置
- matlab 生成 稀疏 对称正定 矩阵
- 稀疏特征(稀疏矩阵)
- 关于对称矩阵和稀疏矩阵问题的探究
- 稀疏矩阵的对称矩阵的转置
- 对称矩阵和稀疏矩阵的压缩和转置
- 对称矩阵和稀疏矩阵以及它们的压缩存储
- 当mybatis整合spring后出现org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
- umount: /var: device is busy
- CodeForces
- android studio NDK开发环境设置
- js 获取json对象的Key、value
- 对称矩阵与稀疏矩阵(转置)
- Apache 映射磁盘路径,启动静态资源以实现动静分离
- 数字签名是什么?
- 服务器安全配置
- 单例模式优缺点
- iOS 数组的去重(普通的无序的去重和排序好的去重)
- HttpClient
- 浅谈方正教务模拟登录实现
- 多线程编程