对称与稀疏矩阵

来源:互联网 发布:js 当前时间加1小时 编辑:程序博客网 时间:2024/05/17 07:00

一、对称矩阵:元素以主对角线为对称轴对应相等的矩阵

1.压缩存储:只需要存储上三角或下三角的数据即可,最多存储n*(n+1)/2个元素。

2.元素的访问:如果行下标小于列下标,是行列互换

3.矩阵的还原:根据矩阵的访问函数,一一还原

//对称矩阵的压缩存储template<class T,size_t N=5>class SymmetricMatrix{public:SymmetricMatrix(T(&arr)[N][N])  // 数组指针:_arr(NULL){int i = 0;int j = 0;int index = 0;_arr.resize((N*(N + 1)) / 2);  //已经放了15个默认值为0的数for (i = 0; i < N; i++){for (j = 0; j <= i; j++){_arr[index++]=(arr[i][j]);}}}//对称矩阵的访问T& Acess(int row, int col){if (row < col){swap(row, col);}return _arr[row*(row+1)/2+col];}//对称矩阵的还原并打印void Print(){int i = 0;int j = 0;int index = 0;vector<T> arr;arr.resize(N*N);  //新开辟空间,防止原空间被改变for (i = 0; i < N; i++){for (j = 0; j < N; j++){arr[index++] = Acess(i, j);}}index = 0;  //注意索引for (i = 0; i < N; i++){for (j = 0; j < N; j++){cout << arr[index++] <<" ";}cout << "\n";}}private:vector<int> _arr;};int main(){int arr[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(arr);cout<<s.Acess(1, 4);cout << "\n";s.Print();getchar();return 0;}
运行结果


二、稀疏矩阵:M*N的矩阵,其中有效值得个数远小于无效值的个数,且数据分布没有规律

1.压缩存储:存储极少数的有效数据,使用三元组{_row,_right,_data}结构体,存储每个有效元素,以行优先级顺序依次存放

2.打印稀疏矩阵

3.还原:如果是行列下标与稀疏矩阵的行列相同,输出三元组的值,否则输出无效值;如果稀疏矩阵已经遍历完,其他元素都为无效值

template<class T>struct Trituple{Trituple(){}Trituple(size_t row,size_t col,T data):_row(row), _col(col), _data(data){}size_t _row;size_t _col;T _data;};template<class T,int M,int N>  //类模板class SparseMatrix{public:SparseMatrix(int row,int col,T invalid):_arr(NULL), _row(row), _col(col), _invalid(invalid){}SparseMatrix(T arr[M][N],T invalid):_row(M), _col(N), _invalid(invalid){if (arr == NULL)return;size_t i = 0;size_t j = 0;for (i = 0; i < _row; i++){for (j = 0; j < _col; j++){if (arr[i][j] != invalid){Trituple<int> t(i,j,arr[i][j]);//先构造三元组对象_arr.push_back(t);  //尾插入三元组对象}}}}//打印稀疏矩阵void Display(){if (this == NULL)return;int i = 0;for (i = 0; i < _arr.size(); i++){cout << _arr[i]._data<<" ";}}//还原稀疏矩阵void Print(){int i = 0;int j = 0;int index = 0;for (i = 0; i < _row; i++){for (j = 0; j < _col; j++)  //当且仅当i和j相同,输出有效值{if(index < _arr.size())  // 防止下标越界{if ((_arr[index]._row == i) && (_arr[index]._col == j)){cout << _arr[index++]._data << " ";  //为了输出第一个值,应该访问0下标后,在让索引自增}else{cout << _invalid << " ";}}else{cout << _invalid << " ";}}cout << "\n";}}

三、矩阵的逆置

先将_arr[index]元素的行列互换,然后交换矩阵的行和列,由原来的四行五列变为五行四列;

int index = 0;for (index = 0; index < _arr.size(); index++){swap(_arr[index]._row, _arr[index]._col);}swap(_row, _col);
运行结果:

      
为什么没有得到我们所期望的呢?请看上图,因为原来的矩阵是按行优先进行存储的,现在是按列优先存储的,打印是按行,_row<5,所以打印data5后,后面的元素不在打印。我们应该冒泡排序元素的行,才能得到正确的结果

void ReverseMatrix(){size_t i = 0;size_t j = 0;int index = 0;for (index = 0; index < _arr.size(); index++){swap(_arr[index]._row, _arr[index]._col);}swap(_row, _col);for (i = 0; i < _arr.size(); i++)//冒泡排序,行优先在前先排{for (j = 0;j<_arr.size()-i-1;j++){if (_arr[j]._row>_arr[j + 1]._row){swap(_arr[j], _arr[j + 1]);}}}}
结果运行图



四、矩阵的加法

只用行和列都相同的两个矩阵才能相加,我们以偏移量来计算两个值,当偏移量相同时,相加,存入新矩阵;不相同时,偏移量小的存入新矩阵

SparseMatrix& operator+(SparseMatrix& Matrix)//传构造的矩阵对象{if ((Matrix._row != _row)||(Matrix._col != _col)){printf("两个矩阵的行列不同,无法相加\n");return *this;}size_t LeftIndex = 0;//左的索引size_t RightIndex = 0;//右的索引size_t addL= 0;//左偏移量size_t addR = 0;//右偏移量//当左右矩阵的三元组都没有遍历完,循环执行SparseMatrix* ret = new SparseMatrix(_row,_col,_invalid);while (LeftIndex < _arr.size() && RightIndex < Matrix._arr.size()){addL = _arr[LeftIndex]._row*_col + _arr[LeftIndex]._col;addR = Matrix._arr[RightIndex]._row*_col + Matrix._arr[RightIndex]._col;if (addL<addR){ret->_arr.push_back(_arr[LeftIndex]);//将左的三元组放入顺序表中LeftIndex++;}else if (addL>addR){ret->_arr.push_back(Matrix._arr[RightIndex]);//将右的的三元组放入顺序表中RightIndex++;}else  // 偏移量相同,有可能相加为0{Trituple<T> t(_arr[LeftIndex]._row, _arr[LeftIndex]._col, _arr[LeftIndex]._data + Matrix._arr[RightIndex]._data);ret->_arr.push_back(t);LeftIndex++;RightIndex++;}}while(LeftIndex < _arr.size()) //右遍历完,然后直接将左矩阵存入新矩阵{ret->_arr.push_back(_arr[LeftIndex]);LeftIndex++;}while (RightIndex < Matrix._arr.size())  //右遍历完,然后直接存入新矩阵{ret->_arr.push_back(Matrix._arr[RightIndex]);RightIndex++;}return *ret;}

测试函数

void Test(){int array[4][5] = {{ 1, 0, 2, 0, 5 },{ 0, 0, 0, 0, 0 },{ 0, 1, 0, 0, 0 },{ 3, 0, 0, 0, 0 },};int array1[4][5] = {{ 1, 0, 0, 0, 5 },{ 0, 0, 0, 1, 0 },{ 0, -1, 0, 0, 0 },{ 3, 0, 0, 0, 1 }, };SparseMatrix<int, 4, 5> s1(array, 0);SparseMatrix<int, 4, 5> s2(array1, 0);s1.Display();cout << "\n";cout << "\n";s2.Display();cout << "\n";cout << "\n";s1.Print();cout << "\n";s2.Print();cout << "\n";(s1+s2).Print();}int main(){Test();getchar();return 0;}

运行结果图








原创粉丝点击