C++(数据结构与算法):16---特殊矩阵的实现(对角矩阵三对角矩阵下三角矩阵上三角矩阵对称矩阵)
Posted 董哥的黑板报
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++(数据结构与算法):16---特殊矩阵的实现(对角矩阵三对角矩阵下三角矩阵上三角矩阵对称矩阵)相关的知识,希望对你有一定的参考价值。
一、特殊矩阵(方阵)
- 方阵:是指行数与列数相同的矩阵
- 一些常用的特殊方阵如下:
- 对角矩阵: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的一维数组来表示。未存储的元素可以用存储的元素来计算
七、总结
以上是关于C++(数据结构与算法):16---特殊矩阵的实现(对角矩阵三对角矩阵下三角矩阵上三角矩阵对称矩阵)的主要内容,如果未能解决你的问题,请参考以下文章