矩阵的格式采用二维数组进行存储,接下来本文将介绍一些特殊矩阵的压缩存储方法。
1.对称矩阵
对称矩阵中的元素有一定的规律,就是行下标row与列下标col 互换后得到的新坐标的元素与换坐标前的元素相同。因此我们在存放对称矩阵的元素时只需将它的下三角或上三角的元素存储就可以了。特殊矩阵也称上三角矩阵或者下三角矩阵。
采用行优先进行存储:
对于下三角矩阵,原数组元素a[i][j]与压缩数组原则b[k]的对应关系如下:
- k = i * (i - 1) / 2 + j - 1
对于上三角矩阵,原数组元素a[i][j]与压缩数组原则b[k]的对应关系如下:
- k = (i - 1) * (2n - i + 2) / 2 + j - i
基于此设计的代码如下:
//
// Created by A on 2023/6/13.
//
#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;
template<class T>
class SymmetricMatrix {
public:
SymmetricMatrix(size_t row, size_t col, T *array)
: _row(row), _col(col) {
int index = 0;
_v.resize(((1 + row) * row) >> 1);
for (size_t i = 0; i < row; i++)
for (size_t j = 0; j <= i; j++)
_v[index++] = array[i * col + j];
}
T &Aescc(size_t row, size_t col) {
if (row < col)
swap(row, col);
return _v[(((row + 1) * row) >> 1) + col];
}
void BackSymmetricMatrix() {
for (size_t i = 0; i < _row; i++) {
for (size_t j = 0; j < _col; j++) {
cout << Aescc(i, j) << " ";
}
cout << endl;
}
}
private:
vector<T> _v;
size_t _row;
size_t _col;
};
int main() {
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(5, 5, (int *) a);
int ret = sm.Aescc(2, 1);
cout << ret << endl;
ret = sm.Aescc(0, 3);
cout << ret << endl;
sm.BackSymmetricMatrix();
system("pause");
return 0;
}
运行结果如下:
1
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
2.稀疏矩阵
稀疏矩阵是指矩阵中大多数元素为0的矩阵。从直观上来讲,当非零元素低于总元素的30%时,这样的矩阵称为稀疏矩阵。
本文对于稀疏矩阵采用三元组法进行存储。则我们要创建一个包含它的行坐标row 列坐标col 与元素 data 的结构体。
代码如下:
//
// Created by A on 2023/6/13.
//
#include<iostream>
#include<vector>
#include<assert.h>
#include<string.h>
using namespace std;
template<class T>
class SparseMatrix {
public:
template<class >
struct Trituple{
Trituple(size_t row = 0, size_t col = 0, const T &data = T())
: _row2(row), _col2(col), _data(data) {}
size_t _row2;
size_t _col2;
T _data;
};
SparseMatrix() {}
SparseMatrix(T *_array, size_t row, size_t col)
: _row(row), _col(col), invaild(0) {
for (size_t i = 0; i < row; i++) {
for (size_t j = 0; j < col; j++) {
if (_array[i * col + j] != invaild)
_vm.push_back(Trituple<T>(i, j, _array[i * col + j]));
}
}
}
T &Aescc(size_t row, size_t col) {
for (size_t i = 0; i < _vm.size(); i++) {
if (_vm[i]._row2 == row && _vm[i]._col2 == col)
return _vm[i]._data;
}
return invaild;
}
void displaySparseMatrix(){
size_t index = 0;
for (size_t i = 0; i < _row; i++) {
for (size_t j = 0; j < _col; j++) {
if (index < _vm.size() && _vm[index]._row2 == i && _vm[index]._col2 == j) {
cout << _vm[index]._data << " ";
index++;
} else
cout << invaild << " ";
}
cout << endl;
}
}
void ReverseMatrix(){
for (size_t i = 0; i < _col; i++) {
for (size_t j = 0; j < _row; j++) {
int flag = 0;
size_t index = _vm.size();
while (index--) {
if (_vm[index]._row2 == j && _vm[index]._col2 == i) {
flag = 1;
cout << _vm[index]._data << " ";
}
}
if (flag == 0)
cout << invaild << " ";
}
cout << endl;
}
}
friend ostream &operator<<(ostream &_cout, SparseMatrix<T> &m) {
size_t index = 0;
for (size_t i = 0; i < m._row; i++) {
for (size_t j = 0; j < m._col; j++) {
if (index < m._vm.size() && m._vm[index]._row2 == i && m._vm[index]._col2 == j) {
_cout << m._vm[index]._data << " ";
index++;
} else
_cout << m.invaild << " ";
}
cout << endl;
}
return _cout;
}
SparseMatrix<T> &operator+(SparseMatrix<T> &d){
assert(d._row == _row && d._col == _col);
SparseMatrix<T> *tmp = new SparseMatrix<T>;
(*tmp)._col = _col;
(*tmp)._row = _row;
(*tmp).invaild = invaild;
size_t leftMatrix = 0;
size_t rightMatrix = 0;
size_t Addrleft = 0;
size_t Addrright = 0;
while (leftMatrix < _vm.size() && rightMatrix < d._vm.size()) {
Addrleft = _vm[leftMatrix]._row2 * _col + _vm[leftMatrix]._col2;
Addrright = d._vm[rightMatrix]._row2 * _col + d._vm[rightMatrix]._col2;
if (Addrleft > Addrright) {
(*tmp)._vm.push_back(d._vm[rightMatrix]);
rightMatrix++;
} else if (Addrleft < Addrright) {
(*tmp)._vm.push_back(_vm[leftMatrix]);
leftMatrix++;
} else {
Trituple<T> ret;
ret._col2 = _vm[leftMatrix]._col2;
ret._row2 = _vm[leftMatrix]._row2;
ret._data = _vm[leftMatrix]._data + d._vm[rightMatrix]._data;
if (ret._data != invaild)
(*tmp)._vm.push_back(ret);
leftMatrix++;
rightMatrix++;
}
}
while (leftMatrix < _vm.size()) {
(*tmp)._vm.push_back(_vm[leftMatrix]);
leftMatrix++;
}
while (rightMatrix < d._vm.size()) {
(*tmp)._vm.push_back(d._vm[rightMatrix]);
rightMatrix++;
}
return (*tmp);
}
SparseMatrix<T> &FastReverseMatrix(){
SparseMatrix<T> *Newm = new SparseMatrix<T>;
(*Newm)._row = _col;
(*Newm)._col = _row;
(*Newm).invaild = invaild;
(*Newm)._vm.resize(_vm.size());
int *count = new int[_col];
memset(count, 0, _col * sizeof(int));
for (size_t i = 0; i < _vm.size(); i++)
count[_vm[i]._col2]++;
int *addr = new int[_col];
memset(addr, 0, _col * sizeof(int));
for (size_t i = 1; i < _col; i++)
addr[i] = addr[i - 1] + count[i - 1];
for (size_t i = 0; i < _vm.size(); i++) {
int &rowAddr = addr[_vm[i]._col2];
(*Newm)._vm[rowAddr] = _vm[i];
swap((*Newm)._vm[rowAddr]._row2, (*Newm)._vm[rowAddr]._col2);
rowAddr++;
}
return (*Newm);
}
private:
vector <Trituple<T>> _vm;
size_t _row;
size_t _col;
T invaild;
};
void test1(){
int array1[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> sn1((int *) array1, 6, 5); //存储一个稀疏矩阵
sn1.displaySparseMatrix(); //打印稀疏矩阵
cout << endl;
int array2[6][5] = {
{0, 0, 3, 0, 5},
{0, 2, 0, 0, 0},
{0, 0, 0, 0, 0},
{5, 0, -3, 0, 5},
{0, 4, 0, 0, 0},
{2, 0, 0, 0, 0}};
SparseMatrix<int> sn2((int *) array2, 6, 5); //存储一个稀疏矩阵
cout << sn2 << endl;
SparseMatrix<int> sn3 = sn1 + sn2;
cout << sn3;
}
void test2(){
int array1[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> sn1((int *) array1, 6, 5);
SparseMatrix<int> sn2 = sn1.FastReverseMatrix();
cout << sn2;
}
int main() {
test1();
test2();
system("pause");
return 0;
}
运行结果如下:
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
0 0 3 0 5
0 2 0 0 0
0 0 0 0 0
5 0 -3 0 5
0 4 0 0 0
2 0 0 0 0
1 0 6 0 10
0 2 0 0 0
0 0 0 0 0
6 0 0 0 10
0 4 0 0 0
2 0 0 0 0
1 0 0 1 0 0
0 0 0 0 0 0
3 0 0 3 0 0
0 0 0 0 0 0
5 0 0 5 0 0