一、特殊矩阵(方阵)
-
方阵:是指行数与列数相同的矩阵
-
一些常用的特殊方阵如下:
-
对角矩阵:M是一个对角矩阵,当且仅当i!=l时,M(i,j)=0
-
三对角矩阵:M是一个三对角矩阵,当且仅当|i-j|>1时,M(i,j)=0
-
下三角矩阵:M是一个下三角矩阵,当且仅当i<j时,M(i,j)=0
-
上三角矩阵:M是一个上三角矩阵,当且仅当i>j时,M(i,j)=0
-
对称矩阵:M是一个对称矩阵,当且仅当对于所有的j和j,M(i,j)=M(j,i)
二、特殊矩阵(方阵)在实际中的应用
应用①
- 佛罗里达州的6个城市Gainsville、Jacksonville、Miami、Orlando、Tallaha-ssee和Tampa
- 按照这个顺序,依次从1~6编号。任意两个城市之间的距离用一个6*6的矩阵distance表示。矩阵的第i行和第i列代表第i个城市。distance(i,j)代表城市i和城市j之间的距离
- 下图给出了相应的矩阵,因为对于所有的i和j有distance(i,j)=distance(j,i),所以这是一个对称矩阵
应用②
三、对角矩阵
-
对角矩阵:M是一个对角矩阵,当且仅当i!=l时,M(i,j)=0
编码实现:
- 一个rows*rows的对角矩阵D可以表示为一个二维数组element[rows][rows],其中element[i-1][j-1]=D(i,i)。这种表示法需要rows*rows个类型为T的数据空间
- 然后对角矩阵最多只有rows个非0元素,因此可以用一位数组element[rows]来表示,其中element[i-1]=D(i,i),所有未在一维数组中出现的矩阵元素均为0
异常类定义
class illegalParameterValue
{
string message;
public:
illegalParameterValue(const char *theMessage ="Illegal Parameter Value"):message(theMessage) {}
const char *what() {
return message.c_str();
}
};
class matrixIndexOutOfBounds
{
public:
matrixIndexOutOfBounds(string theMessage = "Matrix index out of bounds") :message(theMessage){}
const char *what() {
return message.c_str();
}
private:
string message;
};
类定义
template<typename T>
class diagonalMatrix
{
public:
diagonalMatrix(int theN = 10);
~diagonalMatrix();
void set(int i, int j, T value);
T get(int i, int j)const;
void output(ostream& out) const;
private:
T *element; //存放矩阵的数组
int n; //矩阵维度
};
类成员实现
- 构造函数时间复杂度:当T时内部数据类型时为O(1),当T为用户定义类型时为O(rows)
- get、set的时间复杂度:Θ(1)
template<typename T>
diagonalMatrix<T>::diagonalMatrix(int theN = 10)
{
if (theN < 1) {
throw illegalParameterValue("Parameter mu be >=1");
}
element = new T[theN];
n = theN;
}
template<typename T>
diagonalMatrix<T>::~diagonalMatrix()
{
if (element) {
delete[] element;
element = nullptr;
}
}
template<typename T>
void diagonalMatrix<T>::set(int i, int j, T value)
{
if ((i<1) || (j<1) || (i>n) || (j>n)) {
throw matrixIndexOutOfBounds();
}
if (i == j) {
element[i] = value;
}
else {
if (value != 0) {
throw illegalParameterValue("nondiagonal elements must be zero");
}
}
}
template<typename T>
T diagonalMatrix<T>::get(int i, int j)const
{
if ((i<1) || (j<1) || (i>n) || (j>n)) {
throw matrixIndexOutOfBounds();
}
if (i == j)
return element[i];
else
return 0;
}
template<typename T>
void diagonalMatrix<T>::output(ostream& out) const
{
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; j++) {
if (i == j) {
out << element[i]<<" ";
continue;
}
out << "0 ";
}
out << endl;
}
}
演示案例
int main()
{
diagonalMatrix<int> *matrix = new diagonalMatrix<int>(3);
matrix->set(1,1,1);
matrix->set(2, 2, 2);
matrix->set(3, 3, 3);
cout << "matrix[1,1]="<< matrix->get(1, 1) <<endl;
cout << "matrix[2,2]=" << matrix->get(2, 2) << endl;
cout << "matrix[3,3]=" << matrix->get(3, 3) << endl;
matrix->output(cout);
return 0;
}
四、三对角矩阵
-
三对角矩阵:M是一个三对角矩阵,当且仅当|i-j|>1时,M(i,j)=0
-
非0元素排列在如下三条对角线上:
- ①主对角线:i=j
- ②主对角线之下的对角线(称为低对角线):i=j+1
- ③主对角线之上的对角线(称为高对角线):i=j-1
编码实现:
- 三条对角线上的元素总数为3*rows-2。可以用一个容量3*rows-2的一维数组element来描述三对角矩阵
- 以下图这个三对角矩阵为例:
- 如果逐行映射:则element[0-9]={2,1,3,1,3,5,7,9,0}
- 如果逐列映射:则element[0-9]={2,3,1,1,5,3,2,9,7,0}
- 如果从低对角线开始逐条对角线映射:则element[0-9]={3,5,9,2,1,2,0,1,3,7}
- 每一种映射方式,get和set方法的代码都不同,下面我们假设为逐条对角线映射
异常类定义
class illegalParameterValue
{
string message;
public:
illegalParameterValue(const char *theMessage ="Illegal Parameter Value"):message(theMessage) {}
const char *what() {
return message.c_str();
}
};
class matrixIndexOutOfBounds
{
public:
matrixIndexOutOfBounds(string theMessage = "Matrix index out of bounds") :message(theMessage){}
const char *what() {
return message.c_str();
}
private:
string message;
};
类定义
template<typename T>
class tridiagonalMatrix
{
public:
tridiagonalMatrix(int theN = 10);
~tridiagonalMatrix();
T get(int i,int j)const;
void set(int i, int j, T value);
void output(ostream& out) const;
private:
T *element; //存放矩阵的数组
int n; //矩阵维数
};
类成员实现
template<typename T>
tridiagonalMatrix<T>::tridiagonalMatrix(int theN = 10)
{
if (theN < 1) {
throw illegalParameterValue("Parameter mu be >=1");
}
element = new T[3*theN-2];
n = theN;
}
template<typename T>
tridiagonalMatrix<T>::~tridiagonalMatrix()
{
if (element) {
delete[] element;
element = nullptr;
}
}
template<typename T>
T tridiagonalMatrix<T>::get(int i, int j)const
{
if ((i<1) || (j<1) || (i>n) || (j>n)) {
throw matrixIndexOutOfBounds();
}
switch (i-j)
{
case 1: //下对角线
return element[i - 2];
case 0: //主对角线
return element[n + i - 2];
case -1: //上对角线
return element[2 * n + i - 2];
default:
return 0;
}
}
template<typename T>
void tridiagonalMatrix<T>::set(int i, int j, T value)
{
if ((i<1) || (j<1) || (i>n) || (j>n)) {
throw matrixIndexOutOfBounds();
}
switch(i - j)
{
case 1: //下对角线
element[i - 2] = value;
break;
case 0: //主对角线
element[n + i - 2] = value;
break;
case -1: //上对角线
element[2 * n + i - 2] = value;
break;
default:
if (value != 0) {
throw illegalParameterValue("nondiagonal elements must be zero");
}
break;
}
}
template<typename T>
void tridiagonalMatrix<T>::output(ostream& out) const
{
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
switch (i - j)
{
case 1: //下对角线
out << element[i - 2] << " ";
continue;
case 0: //主对角线
out << element[n + i - 2] << " ";
continue;
case -1: //上对角线
out << element[2 * n + i - 2]<<" ";
continue;
default:
out << "0 ";
continue;
}
}
out << endl;
}
}
演示效果
int main()
{
tridiagonalMatrix<int> *matrix = new tridiagonalMatrix<int>(4);
matrix->set(1, 1, 2);
matrix->set(1, 2, 1);
matrix->set(2, 1, 3);
matrix->set(2, 2, 1);
matrix->set(2, 3, 3);
matrix->set(3, 2, 5);
matrix->set(3, 3, 2);
matrix->set(3, 4, 7);
matrix->set(4, 3, 9);
matrix->set(4, 4, 0);
matrix->output(cout);
return 0;
}
五、三角矩阵
-
下三角矩阵:M是一个下三角矩阵,当且仅当i<j时,M(i,j)=0
-
上三角矩阵:M是一个上三角矩阵,当且仅当i>j时,M(i,j)=0
编码实现:
- 在一个n行的下三角矩阵中(见下图),非0区域的第一行有1个元素,第二行有2个元素,......,第n行有n个元素
- 在一个n行的上三角矩阵中(见下图),非0区域的第一行有n个元素,第二行有n-1个元素,......,第n行有1个元素
-
总结:下三角矩阵或上三角矩阵中非0区域共有非0元素:n(n+1)/2。一个三角矩阵可以用一个大小为n(n+1)/2的一维数组来表示
-
以下面的下三角矩阵为例:
- 按行映射:element[0-9]={2,5,1,0,3,1,4,2,7,0}
- 按列映射:element[0-9]={2,5,0,4,1,3,2,1,7,0}
-
下三角矩阵的元素L(i,j):
- 如果i<j,则L(i,j)=0
- 如果i>=j,则L(i,j)位于非0区域。如果按行映射,在元素L(i,j)(i>=j)之前分别有个元素位于第1行至第i-1行的非0区域和j-1个元素位于第i行的非0区域拒,共有个
异常类定义
class illegalParameterValue
{
string message;
public:
illegalParameterValue(const char *theMessage ="Illegal Parameter Value"):message(theMessage) {}
const char *what() {
return message.c_str();
}
};
class matrixIndexOutOfBounds
{
public:
matrixIndexOutOfBounds(string theMessage = "Matrix index out of bounds") :message(theMessage){}
const char *what() {
return message.c_str();
}
private:
string message;
};
类定义
template<typename T>
class lowerTriangularMatrix
{
public:
lowerTriangularMatrix(int theN = 10);
~lowerTriangularMatrix();
void set(int i, int j, T value);
T get(int i, int j)const;
void output(ostream& out) const;
private:
T *element; //存放矩阵的数组
int n; //矩阵维度
};
类成员实现
template<typename T>
lowerTriangularMatrix<T>::lowerTriangularMatrix(int theN = 10)
{
if (theN < 1) {
throw illegalParameterValue("Parameter mu be >=1");
}
element = new T[theN*(theN + 1) / 2];
n = theN;
}
template<typename T>
lowerTriangularMatrix<T>::~lowerTriangularMatrix()
{
if (element) {
delete[] element;
element = nullptr;
}
}
template<typename T>
void lowerTriangularMatrix<T>::set(int i, int j, T value)
{
if ((i<1) || (j<1) || (i>n) || (j>n)) {
throw matrixIndexOutOfBounds();
}
if (i >= j) {
element[i*(i - 1) / 2 + j - 1] = value;
}
else {
if (value != 0) {
throw illegalParameterValue("nondiagonal elements must be zero");
}
}
}
template<typename T>
T lowerTriangularMatrix<T>::get(int i, int j)const
{
if ((i<1) || (j<1) || (i>n) || (j>n)) {
throw matrixIndexOutOfBounds();
}
if (i >= j)
return element[i*(i - 1) / 2 + j - 1];
else
return 0;
}
template<typename T>
void lowerTriangularMatrix<T>::output(ostream& out) const
{
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; j++) {
if (i >= j) {
out << element[i*(i - 1) / 2 + j - 1] << " ";
continue;
}
out << "0 ";
}
out << endl;
}
}
演示效果
int main()
{
lowerTriangularMatrix<int> *matrix = new lowerTriangularMatrix<int>(4);
matrix->set(1, 1, 2);
matrix->set(2, 1, 5);
matrix->set(2, 2, 1);
matrix->set(3, 1, 0);
matrix->set(3, 2, 3);
matrix->set(3, 3, 1);
matrix->set(4, 1, 4);
matrix->set(4, 2, 2);
matrix->set(4, 3, 7);
matrix->set(4, 4, 0);
matrix->output(cout);
return 0;
}
六、对称矩阵
-
对称矩阵:M是一个对称矩阵,当且仅当对于所有的j和j,M(i,j)=M(j,i)
-
编码实现:一个n*n的对称矩阵,可以视为下三角或上三角矩阵,用三角矩阵的表示方法,用一个大小为n(n+1)/2的一维数组来表示。未存储的元素可以用存储的元素来计算
七、总结