特殊矩阵——对称矩阵(Symmetric Matrix)
注:压缩存储的矩阵可以分为特殊矩阵和稀疏矩阵。对于那些具有相同元素或零元素在矩阵中分布具有一定规律的矩阵,被称之为特殊矩阵。对于那些零元素数据远远多于非零元素数目,并且非零元素的分布没有规律的矩阵称之为稀疏矩阵。
1. 对称矩阵的概念
- 元素以主对角线为对称轴对应相等的矩阵。
2. 对称矩阵的特性
- 对角矩阵都是对称矩阵,对称矩阵必须是方形矩阵。
- 设一个n*n的方阵A,对于矩阵A中的任一元素aij,当且仅当aij=aji时(0≤i≤n-1,0≤j≤n-1)时,矩阵A为对称矩阵。
3. 对称矩阵的压缩存储
- 可以利用对称矩阵的上述特性,只存储对角线及对角线以下的元素,或者只存储对角线及对角线以上的元素,前者称之为下三角阵,后者称之为上三角阵。
- 对一个n*n的对称方阵A,元素总数有n2个,而上三角阵或下三角阵的元素共有n+(n-1)+(n-2)+……+2+1=n*(n+1)/2个元素。因此,存储对称方阵时最多只需存储n*(n+1)/2个元素。
- 利用对称矩阵的对称性,可以用一维数组B存储对称矩阵A(这主要要区分四种存储方式:行优先方式存储下三角阵、行优先方式存储上三角阵、列优先方式存储下三角阵和列优先方式存储上三角阵)。
(1)行优先方式存储下三角阵
(2)行优先方式存储上三角阵
(3)列优先方式存储下三角阵
(4)列优先方式存储上三角阵
4. 特殊矩阵的实现
文件:SymmetricMatrix.h
#include <iostream> using namespace std; //压缩存储后,存储对称方阵时最多只需存储n*(n+1)/2个元素 #define GetTotalLen(n) n * (n + 1) / 2 //按行优先方式存放下三角阵时,矩阵元素下标对应的一维数组的下标 #define GetIndexRowLower(i, j) ((i + 1) * i) / 2 + j //按行优先方式存放上三角阵时,矩阵元素下标对应的一维数组的下标 //n * i + j - ((i + 1) * i) / 2 =>((2 * n - i - 1) * i) / 2 + j #define GetIndexRowUpper(n, i, j) ((2 * n - i - 1) * i) / 2 + j //按列优先方式存放下三角阵时,矩阵元素下标对应的一维数组的下标 //n * j + i - ((j + 1) * j) / 2 =>((2 * n - j - 1) * j) / 2 + i #define GetIndexColLower(n, i, j) ((2 * n - j - 1) * j) / 2 + i //按列优先方式存放上三角阵时,矩阵元素下标对应的一维数组的下标 #define GetIndexColUpper(i, j) ((j + 1) * j) / 2 + i class SymmetricMatrix { public: SymmetricMatrix(int order); ~SymmetricMatrix(); public: void create(); //创建矩阵 void destroy(); //销毁矩阵 void transpos(); //矩阵转置 int get_order(); //获取矩阵阶数 int* compressed_storage_row_lower(); //压缩存储特殊矩阵——对称矩阵,按行优先方式存放下三角阵 int* compressed_storage_row_upper(); //压缩存储特殊矩阵——对称矩阵,按行优先方式存放上三角阵 int* compressed_storage_col_lower(); //压缩存储特殊矩阵——对称矩阵,按列优先方式存放下三角阵 int* compressed_storage_col_upper(); //压缩存储特殊矩阵——对称矩阵,按列优先方式存放上三角阵 bool is_symmetric(); //判断矩阵是否为对称矩阵 public: friend ostream& operator<<(ostream& os, SymmetricMatrix& m); //输出矩阵 private: int _order; int **_matrix; };
文件:SymmetricMatrix.cpp
#include "SymmetricMatrix.h" SymmetricMatrix::SymmetricMatrix(int order) : _order(order), _matrix(new int*[order]) { create(); } SymmetricMatrix::~SymmetricMatrix() { destroy(); } void SymmetricMatrix::create() { for (int i = 0; i < _order; i++) { _matrix[i] = new int[_order]; for (int j = 0; j < _order; j++) { _matrix[i][j] = i + j; } } } void SymmetricMatrix::destroy() { for (int i = 0; i < _order; i++) { delete[] _matrix[i]; } delete[] _matrix; _matrix = NULL; } void SymmetricMatrix::transpos() { int temp = 0; for (int i = 0; i < _order; i++) { for (int j = 0; j < _order; j++) { temp = _matrix[i][j]; _matrix[i][j] = _matrix[j][i]; _matrix[j][i] = temp; } } } int SymmetricMatrix::get_order() { return _order; } int* SymmetricMatrix::compressed_storage_row_lower() { int index = 0; int total_count = GetTotalLen(_order); int *a = new int[total_count]; for (int i = 0; i < _order; i++) { for (int j = 0; j <= i; j++) { index = GetIndexRowLower(i, j); a[index] = _matrix[i][j]; } } return a; } int* SymmetricMatrix::compressed_storage_row_upper() { int index = 0; int total_count = GetTotalLen(_order); int *a = new int[total_count]; for (int i = 0; i < _order; i++) { for (int j = i; j < _order; j++) { index = GetIndexRowUpper(_order, i, j); a[index] = _matrix[i][j]; } } return a; } int* SymmetricMatrix::compressed_storage_col_lower() { int index = 0; int total_count = GetTotalLen(_order); int *a = new int[total_count]; for (int j = 0; j < _order; j++) { for (int i = j; i < _order; i++) { index = GetIndexColLower(_order, i, j); a[index] = _matrix[i][j]; } } return a; } int* SymmetricMatrix::compressed_storage_col_upper() { int index = 0; int total_count = GetTotalLen(_order); int *a = new int[total_count]; for (int j = 0; j < _order; j++) { for (int i = 0; i <= j; i++) { index = GetIndexColUpper(i, j); a[index] = _matrix[i][j]; } } return a; } bool SymmetricMatrix::is_symmetric() { for (int i = 0; i < _order; i++) { for (int j = 0; j < _order; j++) { if (_matrix[i][j] != _matrix[j][i]) { return false; } } } return true; } ostream& operator<<(ostream& os, SymmetricMatrix& m) { for (int i = 0; i < m._order; i++) { for (int j = 0; j < m._order; j++) { os << m._matrix[i][j] << " "; } os << endl; } return os; }
文件:main.cpp
#include "SymmetricMatrix.h" int main() { int n = 0; cout << "请输入对称矩阵的阶数,n = "; cin >> n; SymmetricMatrix matrix(n); if (true == matrix.is_symmetric()) { cout << "$ 输出对称矩阵:" << endl; cout << matrix;//或operator<<(cout, matrix); } matrix.transpos(); if (true == matrix.is_symmetric()) { cout << "$ 输出转置后的对称矩阵:" << endl; cout << matrix;//或operator<<(cout, matrix); } cout << "\n$ 输出压缩存储后的一维数组(按行优先方式存放下三角阵):" << endl; int *arrayrl = matrix.compressed_storage_row_lower(); for (int i = 0; i < GetTotalLen(matrix.get_order()); i++) { cout << arrayrl[i] << " "; } cout << endl; delete[] arrayrl; cout << "\n$ 输出压缩存储后的一维数组(按行优先方式存放上三角阵):" << endl; int *arrayru = matrix.compressed_storage_row_upper(); for (int i = 0; i < GetTotalLen(matrix.get_order()); i++) { cout << arrayru[i] << " "; } cout << endl; delete[] arrayru; cout << "\n$ 输出压缩存储后的一维数组(按列优先方式存放下三角阵):" << endl; int *arraycl = matrix.compressed_storage_col_lower(); for (int i = 0; i < GetTotalLen(matrix.get_order()); i++) { cout << arraycl[i] << " "; } cout << endl; delete[] arraycl; cout << "\n$ 输出压缩存储后的一维数组(按列优先方式存放上三角阵):" << endl; int *arraycu = matrix.compressed_storage_col_upper(); for (int i = 0; i < GetTotalLen(matrix.get_order()); i++) { cout << arraycu[i] << " "; } cout << endl; delete[] arraycu; system("pause"); return 0; }
参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第四章
[2] 百度搜索关键字:对称矩阵