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---特殊矩阵的实现(对角矩阵三对角矩阵下三角矩阵上三角矩阵对称矩阵)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构(C++)笔记:04.字符串与多维数组

c++利用邻接矩阵存储方法实现图的存储与输出。

408数据结构与算法—数组和特殊矩阵的压缩存储(二十五)

408数据结构与算法—数组和特殊矩阵的压缩存储(二十五)

每周一书《数据结构算法与应用 C++语言描述》分享

考研数据结构与算法数组