对称矩阵及稀疏矩阵浅谈
来源:互联网 发布:centos7安装mysql 编辑:程序博客网 时间:2024/06/09 23:12
1.对称矩阵
特点:
关于对角线对称,Aij == Aji。
下面实现:
①对称矩阵的压缩存储
②对称矩阵的访问
③对称矩阵的还原
实现代码如下:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;//对称矩阵的压缩存储template<class T>class SymmetricMatrix{public: SymmetricMatrix(T* array, size_t N) :_N(N) ,_a(NULL) { _a = new T[(N * (N + 1))>> 1]; for (size_t i = 0; i < N; ++i) { for (size_t j = 0; j < N; ++j) { if (i >= j)//表明是下三角数据时 { _a[(i * (i + 1))>>1 + j] = array[i * N + j]; } else { break; } } } } T& Access(size_t x, size_t y) { if (x < y)//如果访问上三角元素 { swap(x, y); } return _a[(x * (x + 1)) >> 1 + y]; } 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)<<" "; } else { cout << Access(j, i) << " "; } } cout << endl; } cout << endl; } ~SymmetricMatrix() { if (_a) { delete[] _a; _a = NULL; } }private: T* _a; size_t _N;};
测试代码如下:
void Test(){ 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> sm((int*)a, 5); cout << sm.Access(0, 3) << endl; cout << sm.Access(3, 0) << endl; sm.DisPlay();}int main(){ Test(); return 0;}
2.稀疏矩阵:
(1)稀疏矩阵的压缩存储:
所谓稀疏矩阵的压缩存储,其实就是将稀疏矩阵中的有效元素保存起来,但由于稀疏矩阵中有效元素的分布没有规律可寻,所以需要使用一个三元组来保存其位置(row、col)以及有效值。—>三元组最好使用结构体来存储。
因为不知道矩阵中究竟有多少个有效元素(即就是不知需要多少个结构体),那么就可以使用vector(动态增长型)来保存有效元素。
//三元组--->存储有效元素的位置及值 template<class T> struct Trituple { Trituple(size_t row, size_t col, const T& data) :_row(row) , _col(col) , _data(data) {} size_t _row; size_t _col; T _data; };
//稀疏矩阵的压缩存储 SparseMatrix(T* array, int row, int col,const T& invalid) :_row(row) , _col(col) ,_invalid(invalid) { for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { if (array[i * col + j] != invalid) { _sm.push_back(Trituple<T>(i, j, array[i * col + j])); } } } }
(2)稀疏矩阵的转置:
稀疏矩阵的转置过程如下:
实现代码如下:
// 稀疏矩阵的转置 //时间复杂度:(稀疏矩阵的列*稀疏矩阵中有效元素的个数) SparseMatrix<T> Transprot() { SparseMatrix<T> sm; sm._row = _col; sm._col = _row; for (size_t index = 0; index < _col; ++index) { vector<Trituple<T> >::iterator it = _sm.begin(); while (it != _sm.end()) { if ( it->_col == index) { sm._sm.push_back(Trituple<T>(it->_col, it->_row, it->_data)); } it++; } } return sm; }
3.稀疏矩阵的快速转置:
稀疏矩阵的转置的时间复杂度:(稀疏矩阵的列N*稀疏矩阵中有效元素的个数)—-》时间复杂度较大,所以引出了快速转置
稀疏矩阵的快速转置的时间复杂度(2*有效元素的个数 + 稀疏矩阵的列)
快速转置的思想如下:
代码实现:
//快速转置SparseMatrix<T,N,M> FastTransport(const size_t m,const size_t n) { SparseMatrix < T, N, M> sm;//转置后的压缩矩阵 sm._row = _col; sm._col = _row; sm._v.resize(_v.size());//为了保证后面可以直接访问vector中的数据(调用operator[]) //保存转置前的每列有效元素的个数,即就是转置后每行有效元素的个数 int rows[N] = {0}; size_t index = 0; while (index < _v.size()) { rows[_v[index]._col]++; index++; } //保存转置后的每行第一个有效元素在转置后的三元组数组中的下标 int starts[N] = { 0 }; for (size_t i = 1; i < _col; ++i) { starts[i] = starts[i - 1] + rows[i - 1]; } for (size_t i = 0; i < _v.size(); ++i) { int row = _v[i]._col;//转置前列的下标即是转置后行的下标 Triple<T> t; t._value = _v[i]._value; t._col = _v[i]._row; t._row = _v[i]._col; sm._v[starts[row]] = t; starts[row]++;//每次需要更新starts数组中的数据 } return sm; }
全部代码如下:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;#include<vector>//三元组template<class T>struct Triple{ Triple() {} Triple(T& data, size_t row, size_t col) :_value(data) , _row(row) , _col(col) {} T _value; size_t _row; size_t _col;};template<class T,size_t M,size_t N>class SparseMatrix{public: SparseMatrix() {} //稀疏矩阵的压缩存储 SparseMatrix(T* array, const T& invalid) :_invalid(invalid) , _row(M) , _col(N) { for (size_t i = 0; i < _row; ++i) { for (size_t j = 0; j < _col; ++j) { if (array[i * N + j] != invalid) { Triple<T> t; t._value = array[i * N + j]; t._row = i; t._col = j; _v.push_back(t); } } } } //稀疏矩阵的还原 void Display() { int index = 0; for (size_t i = 0; i < _row; ++i) { for (size_t j = 0; j < _col; ++j) { if (index < _v.size() && _v[index]._row == i && _v[index]._col == j) { cout << _v[index]._value << " "; index++; } else { cout << _invalid << " "; } } cout << endl; } cout << endl; } //稀疏矩阵的转置 SparseMatrix<T,N,M> Transport() { SparseMatrix<T,N,M> _sm;//转置后的 _sm._invalid = _invalid; _sm._row = _col; _sm._col = _row; //按列查找(转置前的列优先即就是转置后的行优先) for (size_t i = 0; i < _col; ++i) { size_t index = 0; while (index < _v.size()) { if (_v[index]._col == i) { Triple<T> t; t._value = _v[index]._value; t._row = _v[index]._col; t._col = _v[index]._row; _sm._v.push_back(t); } index++; } } return _sm; } template<class T, size_t N, size_t M> friend class SparseMatrix;//快速转置SparseMatrix<T,N,M> FastTransport(const size_t m,const size_t n) { SparseMatrix < T, N, M> _sm;//转置后的压缩矩阵 _sm._row = _col; _sm._col = _row; _sm._v.resize(_v.size());//为了保证后面可以直接访问vector中的数据(使用operator[]) //保存转置前的每列有效元素的个数,即就是转置后每行有效元素的个数 int rows[N] = {0}; size_t index = 0; while (index < _v.size()) { rows[_v[index]._col]++; index++; } //保存转置后的每行第一个有效元素在转置后的三元组数组中的下标 int starts[N] = { 0 }; for (size_t i = 1; i < _col; ++i) { starts[i] = starts[i - 1] + rows[i - 1]; } for (size_t i = 0; i < _v.size(); ++i) { int row = _v[i]._col;//转置前列的下标即是转置后行的下标 Triple<T> t; t._value = _v[i]._value; t._col = _v[i]._row; t._row = _v[i]._col; _sm._v[starts[row]] = t; starts[row]++;//每次需要更新starts数组中的数据 } return _sm; }private: vector<Triple<T> > _v; T _invalid; size_t _row; size_t _col;};
测试代码如下:
void Test(){ 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((int*)array, 0); sm.Display(); SparseMatrix<int,5,6> sm2 = sm.FastTransport(5,6); sm2.Display();}int main(){ Test(); return 0;}
由于能力有限,又是刚开始学习数据结构,难免会有思考的不正确或是不完善的地方,欢迎大家批评指正。。。
0 0
- 对称矩阵及稀疏矩阵浅谈
- 对称矩阵、稀疏矩阵
- 【矩阵】对称矩阵及稀疏矩阵的压缩存储
- 【数据结构】稀疏矩阵,对称矩阵
- 对称与稀疏矩阵
- 对称矩阵、稀疏矩阵的压缩存储
- 对称矩阵&稀疏矩阵的两种转置算法
- 对称矩阵与稀疏矩阵(转置)
- 对称矩阵、稀疏矩阵及矩阵的逆置与加法
- 矩阵-----对称矩阵及其压缩存储&&稀疏矩阵
- matlab 生成 稀疏 对称正定 矩阵
- 关于对称矩阵和稀疏矩阵问题的探究
- 稀疏矩阵的对称矩阵的转置
- 对称矩阵和稀疏矩阵的压缩和转置
- 对称矩阵和稀疏矩阵以及它们的压缩存储
- 【数据结构】对称矩阵和稀疏矩阵的压缩存储
- 对称矩阵和稀疏矩阵的相关问题
- ADT稀疏矩阵 及 转置
- 博客已迁移,本博客不再更新通知
- 阶段一:计数器的仿真实验
- 任给两个节点,如何判断这两个节点是否表示一条边
- PYTHON---DAY3
- 只有改变才能看见未来
- 对称矩阵及稀疏矩阵浅谈
- session统计在线人数
- 顺序栈的基本操作
- 从XML中学习HTML
- 全国C++职位需求统计20170507
- Unity3d搭建HTTP弱联网的服务器搭建及客户端编写(一)之java服务器
- [13]基本包装类型
- LeetCode : Reverse Integer
- 虚拟机可上外网,可ping通网关,但是ping不通主机,主机却可以ping通虚拟机