对称矩阵的存储方式

对于N*N的矩阵A,对于任意i和j(N-1>i>=0 && N-1>j>=0),如果Aij=Aji那么,就称矩阵A是对称矩阵。以矩阵对角线为分界线,矩阵A分为上三角和下三角。

如下图:

由对称矩阵的性质,存储对称矩阵时,只需要存储对称矩阵的上三角或下三角就可以了(压缩存储),最多存储N*(N+1)/2个数据。

对称矩阵和压缩存储的对应关系:下三角存储i>=j,  SymmetricMatrix[i][j] == Array[i*(i+1)/2+j]


步骤分析:

(1)存储

定义一个一维数组_a,开辟N*(N+1)/2个空间,遍历矩阵,若i>=j,说明元素在矩阵的下三角位置,按顺序存入_a;  若i<j,则不存储,继续遍历矩阵的下一个元素。

(2)访问矩阵元素

要访问压缩存储的矩阵元素,我们可以根据对称矩阵和压缩存储的对应关系: SymmetricMatrix[i][j] == Array[i*(i+1)/2+j]

来访问矩阵元素。


实现方法:

#pragma once

#include<iostream>
using namespace std;

template<class T>
class SymmetricMatrix
{
public:
	SymmetricMatrix(const T* a, size_t size, size_t n)//构造函数,压缩存储矩阵元素
	:_a(new T[n*(n + 1) / 2])//开辟空间,下三角元素一共有(n*(n + 1) / 2)个
	, _size(n*(n + 1) / 2)//设置一维数组大小
	, _n(n)//矩阵大小(维数)
	{
		int index = 0;
		for (size_t i = 0; i < n; i++)
		{
			for (size_t j = 0; j < n; j++)//遍历
			{
				if (i >= j)   //若为下三角元素
					_a[index++] = a[i*n + j];//存储
				else;         //若不是下三角元素
					break      //直接跳出循环(此步骤优化,若不是下三角元素,则该行剩余元素一定也不是下三角元素)
			}
		}
	}
	~SymmetricMatrix()//析构函数
	{
		if (_a)
			delete[] _a;
	}
	T& Access(int i,int j)//访问元素
	{
		if (i < j)
			swap(i, j);
		return _a[i*(i + 1) / 2 + j];//根据对称矩阵和压缩存储的对应关系访问元素
	}
	void display()//还原打印矩阵
	{
		for (size_t i = 0; i < _n; i++)
		{
			for (size_t j = 0; j < _n; j++)
			{
				if (i >= j)//若要打印下三角元素,则直接根据对称矩阵和压缩存储的对应关系访问元素,打印
					cout << _a[i*(i + 1) / 2 + j] << " ";
				else      //若打印上三角元素,则交换元素行列(根据对称矩阵性质),就可以看做该元素是下三角元素并打印
					cout << _a[j*(j + 1) / 2 + i] << " ";
			}
			cout << endl;
		}
	}
protected:
	T* _a;
	size_t _size;
	size_t _n;
};

测试代码:

#include "SymmetricMatrix.hpp"
void TestSymmetricMatrix()
{
	int a[4][4] = {
		{0,1,2,3},
		{1,0,3,4},
		{ 2, 3, 0, 5 },
		{ 3, 4, 5, 0 }
	};
	size_t size = sizeof(a) / sizeof(a[0][0]);
	SymmetricMatrix<int> matrix((int *)a, size, 4);
	matrix.display();
	cout << matrix.Access(2,3) << endl;
}
int main()
{
	TestSymmetricMatrix();
	getchar();
	return 0;
}



  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值