对称矩阵的压缩存储
什么是对称矩阵的压缩存储?
就是只存上三角或者只存下三角,以下代码以下三角存储为例;
怎么做到压缩存储呢? 只存下三角呢?
其实这很简单,采用的是一维数组存储,下标访问的形式! 这样做的目的肯定在于节省空间!
在实现代码之前,我们需要搞清楚的是对称矩阵的规律;
/*下面是一个对称矩阵:
0 1 2 3
1 0 1 2
2 1 0 1
3 2 1 0
显而易见的是对称轴上都是0; 而上三角和下三角对应的数据坐标刚好是行列相反的不是吗?
比如 上三角的3(0,3),下三角的3(3,0); 同时不知道你有没有想过,我们用一维数组存储下三角时应该开辟多大的空间呢? 同样仔细观察一下也是显而易见的,除对称轴外,从第1行起,以对称轴为分界线,分别是 1个, 2个, 3个,4个数据,这就是等差数列,那么我们开辟空间也就有了依据,n*(n+1)/2;
那么我们接下来还需要考虑什么呢?
其实接下来要考虑的就是下标访问遵循的规律的问题,我们现在这里提一下,实现代码的时候我会在注释提一遍;
再来看这个
0 1 2 3
1 0 1 2
2 1 0 1
3 2 1 0
重要:坐标规律
1. 上三角和下三角对称的数据坐标严格相反;
2. 在对称轴上的数据的下标是横纵相等的,而在上三角的数据的代码的纵坐标都比横坐标大,而下三角的数据的坐标是横坐标比竖坐标大, 仔细看一下是不是这样,记住这个规律;
下面就是代码的实现;
*/
具体实现请看代码!
#include<iostream>
#include<cassert>
#include<vector>
using namespace std;
template<class T>
class SymmetricMatrix
{
public:
SymmetricMatrix(T* arr, size_t n)
:_matrix (new T[n*(n+1)/2]) //注意开辟空间的大小
,_n(n)
,_size(n*(n+1)/2)
{
//接着就是对下三角的存储了,想想前面讲的坐标规律
int index = 0;
for(size_t i = 0; i < _n; i++)
{
for(size_t j = 0; j < _n; j++)
{
if(i>=j)//下三角的特点,只将下三角存储;
{
_matrix [index++] = arr[i*n + j ];
}
else
continue ; //小优化,节省时间;
}
}
}
//接下来就是打印了,但是在打印之前我们还需要一个函数Not(),这个函数的作用需要看了打印函数可能
// 才比较好理解,我们先看看这个函数是怎实现的;
T Not(size_t i, size_t j)
{
if(i < j)//i < j 的坐标规律代表是上三角的数据;
{
swap (i,j);
}
return _matrix [i*(i+1)/2 + j];//返回对称位置的数据;
}
//打印函数 --- 就是从压缩存储还原的过程;
void Display()
{
for(size_t i = 0; i < _n; i++)
{
for(size_t j = 0; j < _n; j++)
{
cout<<Not(i,j)<<" ";
}
cout<<endl;
}
cout<<endl;
}
private:
T* _matrix; //压缩存储需要的一维数组
size_t _n; //对称矩阵的行数
size_t _size; //一维数组中的元素个数;
};
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);//注意我们需要的参数是一维数组指针,所以这里需要强转;
s.Display ();
}
int main()
{
testSymmetricMatrix();
system("pause");
return 0;
}