数据结构预算法(六) 数组和矩阵(1)

数组:

抽象数据类型:

数组的操作:

1.存值    get(index)

2.取值    set(index, value)

这两个操作定义了抽象数据类型array

c++数组的索引,且数组时c++的标准数据结构

行主映射和列主映射 :

数组的应用需要将数组的元素序列化,按照一维排列,因为数组元素一次只能输出或者输入一个。因此必须确定一个输入输出的顺序(即映射关系)。

不规则的二维数组:

当数组的每行的元素个数不相等的 时候,数组称为不规则数组。不规则数组元素的访问方式与规则数组一样;

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
	// cout<<"Hello C-Free!"<<endl;
	int numberOfRows = 5;   // 数组的行数 
	// 定义每一行的长度
	int length[5] = {6, 3, 4, 2, 7};
	
	int** irregular_array = new int* [numberOfRows];   // 指向指针的指针
	for(int i=0; i<numberOfRows; i++)
	{
	   irregular_array[i] = new int[length[i]]; 
	} 
	// 初始化数组 
	for(int i=0; i<numberOfRows; i++)
	{
		for(int j=0; j<length[i]; j++)
		{
			irregular_array[i][j] = (i+j)*2;
		}
	}
	
	// 输出数组; 
	for(int i=0; i<numberOfRows; i++)
	{
		for(int j=0; j<length[i]; j++)
		{
			cout << irregular_array[i][j] << " ";
		}
		cout << endl;
	} 
	
	cout << "irregular_array[1][2] is " << irregular_array[1][2] << endl; 
	return 0;
}

矩阵

即数表,同城用来组织数据.定义matrix类,将二维矩阵映射到一维数组中。

注:c++中标准异常类是定义在标准命名空间中的,所以需要using  namespace  std.

将矩阵按照行主映射存储到一维数组中,注意矩阵的索引是从1开始,数组的是从0开始,需要转换;

matrix类的定义:matrix.h文件(模板类,定义和实现放在同一个文件中)

#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <stdexcept>  // 包含C++中标准异常类 
#include <string>

using namespace std;
// 定义matrix类
template<typename T>
class matrix
{
	private:
	int col;
	int row;
	T* element;     // 存储矩阵元素,将矩阵映射到一维数组中 //采用行主次序 
	
	public:
	matrix(int row=1, int col=1);   // 构造方法
	matrix(const matrix<T>& mat);      // copy constructor
	~matrix();    // 析构函数
	// 定义矩阵的一些操作 
	int rows() const;
	int cols() const;
	
	T& operator()(int i, int j) const;
	matrix<T>& operator=(const matrix<T>& mat);
	
	matrix<T> operator+();
	matrix<T> operator+(const matrix<T>& mat);  // 矩阵加法 
	matrix<T> operator-();
	matrix<T> operator-(const matrix<T>& mat);  // 矩阵减法 
	matrix<T> operator*(const matrix<T>& mat) const;   // 矩阵乘法 
	matrix<T> operator+=(const T num); 
	void print_matrix() const;     // 输出矩阵 
};

template<typename T>
matrix<T>::matrix(int row, int col)
{
	// 判断矩阵的合法性
	if(row<=0 || col<=0)
	{
		throw runtime_error("Rows and cols must > 0");
	} 
	// 创建矩阵
	this->row = row;
	this->col = col;
	element = new T[row*col];
}

template<typename T>
matrix<T>::matrix(const matrix<T>& mat)        
{
	row = mat.rows();
	col = mat.cols();
	this->element = new T[row*col];
	for(int i=0; i<row*col; i++)
	{
		element[i] = mat.element[i];
	}
}

template<typename T>
matrix<T>::~matrix()
{
	delete [] element;
}

template<typename T>
int matrix<T>::rows() const
{
	return row;
}

template<typename T>
int matrix<T>::cols() const
{
	return col;
} 

/*
template<typename T>
T& matrix<T>::operator()(int i, int j)  //矩阵下表的最最小值是1 
{
	int tmp = col*(i-1)+(j-1); 
	return element[tmp]; 
}*/


template<typename T>
matrix<T>& matrix<T>::operator=(const matrix<T>& mat)
{
	if(this!=&mat)   // 不能复制自己
	{
		delete [] element;   // 将原来的element删除
		row = mat.row;
		col = mat.col;
		element = new T [row*col];
		// 复制元素
		for(int i=0; i<(row*col); i++)
		{
			element[i] = mat.element[i];
		} 
	} 
	return *this;
}

// 用()表示矩阵索引
template<typename T>
T& matrix<T>::operator()(int i, int j) const
{
	if(i>row || i<1 || j>col || j<1)
	{
		//throw invalid_argument("Matrix index out of bounds"); 
	}
	return element[col*(i-1)+(j-1)];
} 


template<typename T>
matrix<T> matrix<T>::operator+()
{
	return *this;
} 

//定义矩阵加法
template<typename T>
matrix<T> matrix<T>::operator+(const matrix<T>& mat)
{
	// 先判断矩阵的维度
	if(col!=mat.cols() || row!=mat.rows())
	{
		//throw runtime_error("The matrix size mismatch");
	} 
	matrix<T> w(row, col);   // 定义一个新的矩阵
	for(int i=0; i<row*col; i++)
	{
		w.element[i] = element[i] + mat.element[i];
	} 
	return w;
}

template<typename T>
matrix<T> matrix<T>::operator-()
{
	matrix<T> tmp(row, col);
	for(int i=0; i<row*col; i++)
	{
		tmp.element[i] = -element[i];
	}
	return tmp;
}

// 定义矩阵减法
template<typename T>
matrix<T> matrix<T>::operator-(const matrix<T>& mat)
{
	if(col!=mat.cols() || row!=mat.rows())
	{
		//throw runtime_error("The matrix size mismatch");
	} 
	matrix<T> w(row, col);   // 定义一个新的矩阵
	for(int i=0; i<row*col; i++)
	{
		w.element[i] = element[i] - mat.element[i];
	} 
	return w;
}
 
template<typename T>
matrix<T> matrix<T>::operator+=(const T num)
{
	matrix<T> w(row, col);
	for(int i=0; i<row*col; i++)
	{
		w.element[i] = element[i] +num;
	}
	return w;
} 

//定义矩阵乘法
template<typename T>
matrix<T> matrix<T>::operator*(const matrix<T>& mat) const
{
	// 先判断矩阵的维度
	if(col!=mat.rows())
	{
		throw runtime_error("Matrix size mismatch");
	} 
	matrix<T> w(row, mat.col);
	for(int i=1; i<=row; i++)
	{
		for(int j=1; j<=mat.col; j++)
		{
			T sum = element[col*(i-1)+(1-1)] * mat(1, j);   // 注意这里的处理方法 。先直接计算第一项,相当于给sum赋初值,因为这里的sum不能初始化为0 
			for(int k=2; k<=col; k++)    // k从2开始 
			{
				sum += element[col*(i-1)+(k-1)] * mat(k, j);
			}
			w(i, j) = sum;
		}
	}
	return w;
}
 
template<typename T>
void matrix<T>::print_matrix() const
{
	for(int i=1; i<=row; i++)
	{
		for(int j=1; j<=col; j++)
		{
			cout << element[col*(i-1)+(j-1)] << " ";
		}
		cout << endl;
	}
	cout << endl;
} 
#endif



测试代码1;

#include <iostream>
#include "E:\back_up\code\c_plus_code\matrix\external_file\matrix.h"
//#include <stdexcept>

using namespace std;


int main(int argc, char *argv[])
{
	cout<<"Hello C-Freesdf!"<<endl;
	matrix<int> m1(2,2);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=2; j++)
		{
			m1(i,j) = i+2*j;
		}
	}
	
	
	matrix<int> m2;
	m2 = -m1; 
	m1.print_matrix();
	
	cout << "---测试 operator-  ----" << endl;
	m2.print_matrix();
	
	matrix<int> m3;
	m3 = m2+m1;
	matrix<int> m4;
	m4 = m1-m2;
	
	cout << "---测试 operator+  ----" << endl;
	m3.print_matrix();
	cout << "---测试 operator-  ----" << endl;
	m4.print_matrix();
	
	matrix<int> m5;
	m5 = m3 += 4;
	cout << "---测试 operator+=  ----" << endl;
	m5.print_matrix();
	
	// 矩阵乘法;
	matrix<int> m6(2,3);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=3; j++)
		{
			m6(i,j)= (i-1)*3+j;
		}
	} 
	
	matrix<int> m7(3,2);
	for(int i=1; i<=3; i++)
	{
		for(int j=1; j<=2; j++)
		{
			m7(i,j) = (i-1)*2+j;
		}
	}
	
	m6.print_matrix();
	m7.print_matrix();
	matrix<int> m8;
	try    // 添加异常捕获代码; 
	{
		m8 = m6*m7;
		cout << "---测试 operator*  ----" << endl;
		m8.print_matrix();
	}
	catch(runtime_error& ex)
	{
		cout << "Exception: " << ex.what() << endl;
	}
	
	return 0;
}

测试结果1:

测试代码2:main.cpp

#include <iostream>
#include "E:\back_up\code\c_plus_code\matrix\external_file\matrix.h"
//#include <stdexcept>

using namespace std;


int main(int argc, char *argv[])
{
	cout<<"Hello C-Freesdf!"<<endl;
	matrix<int> m1(2,2);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=2; j++)
		{
			m1(i,j) = i+2*j;
		}
	}
	
	
	matrix<int> m2;
	m2 = -m1; 
	m1.print_matrix();
	
	cout << "---测试 operator-  ----" << endl;
	m2.print_matrix();
	
	matrix<int> m3;
	m3 = m2+m1;
	matrix<int> m4;
	m4 = m1-m2;
	
	cout << "---测试 operator+  ----" << endl;
	m3.print_matrix();
	cout << "---测试 operator-  ----" << endl;
	m4.print_matrix();
	
	matrix<int> m5;
	m5 = m3 += 4;
	cout << "---测试 operator+=  ----" << endl;
	m5.print_matrix();
	
	// 矩阵乘法;
	matrix<int> m6(2,3);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=3; j++)
		{
			m6(i,j)= (i-1)*3+j;
		}
	} 
	
	matrix<int> m7(2,2);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=2; j++)
		{
			m7(i,j) = (i-1)*2+j;
		}
	}
	
	m6.print_matrix();
	m7.print_matrix();
	matrix<int> m8;
	try    // 添加异常捕获代码; 
	{
		m8 = m6*m7;
		cout << "---测试 operator*  ----" << endl;
		m8.print_matrix();
	}
	catch(runtime_error& ex)
	{
		cout << "Exception: " << ex.what() << endl;
	}
	
	return 0;
}

测试结果2:

复杂度分析

对matrix类的扩充:

1.添加tranpose()方法,实现矩阵转置

template<typename T>
matrix<T> matrix<T>::tranpose() const
{
	matrix<T> tmp(col, row);  // 存放转置后的矩阵
	for(int i=1; i<=row; i++)
	{
		for(int j=1; j<=col; j++)
		{
			tmp(j,i) = element[col*(i-1)+(j-1)];
		}
	} 
	return tmp;
}

测试代码:

cout << "---测试 transpose  ----" << endl;
matrix<int> m9;
m9 = m8.tranpose();
m9.print_matrix();

 结果:

2.添加自定义异常类到matrix类中:

需求:

1.当访问矩阵的索引值超过矩阵的实际大小的时候,应该抛出异常,这一功能由index_OutOf_Bound异常类实现

indexException.h文件:  基类是标准异常类out_of_range

// 自定义异常类
#ifndef INDEX_EXCEPTION_H
#define INDEX_EXCEPTION_H
#include <iostream>
#include <stdexcept>
using namespace std;
class index_OutOf_Bound: public out_of_range   // 矩阵索引超过范围 
{
	private:
	int matrix_row;
	int matrix_col;
	
	public:
	index_OutOf_Bound(int row, int col):out_of_range("The matrix index out of bound")  // 自定义异常类的构造方法调用基类的构造方法
	{
		this->matrix_row = row;
		this->matrix_col = col;
	} 
    void display_exception_info() const
    {
    	cout << "Error detail" << endl;
    	cout << "Matrix index (" << matrix_row << "," << matrix_col << ")" << " is out of bound" << endl;
    }
};

#endif 

 

2.当两个矩阵做加减乘的时候,如果维度不匹配,则抛出异常,这一功能由size_mismatch_exception类实现。

sizeMismatch文件:基类是标准异常类logic_error

// 自定义异常类
#ifndef SIZE_MISMATCH_EXCEPTION
#define SIZE_MISMATCH_EXCEPTION
#include <iostream>
#include <stdexcept>
using namespace std;

class size_mismatch_exception: public logic_error
{
	private:
	int a_row, a_col;
	int b_row, b_col;
	
	public:
	size_mismatch_exception(int a_row, int a_col, int b_row, int b_col): logic_error("Matrix size mismatch")
	{
		this->a_row = a_row;
		this->a_col = a_col;
		this->b_row = b_row;
		this->b_col = b_col;
	}
	
	void diaplay_error_detail() const
	{
		cout << "Error detail" << endl;
		cout << "A matrix size (" << a_row <<"," << a_col << ")" << " dose not match a matrix size (" << b_row << "," << b_col << ")" << endl;
	} 
};
#endif 

matrix.h文件:

#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <stdexcept>  // 包含C++中标准异常类 
#include <string>
#include "E:\back_up\code\c_plus_code\matrix\external_file\indexException.h"   // 异常类文件
#include "E:\back_up\code\c_plus_code\matrix\external_file\sizeMismatch.h" 

using namespace std;
// 定义matrix类
template<typename T>
class matrix
{
	private:
	int col;
	int row;
	T* element;     // 存储矩阵元素,将矩阵映射到一维数组中 //采用行主次序 
	
	public:
	matrix(int row=1, int col=1);   // 构造方法
	matrix(const matrix<T>& mat);      // copy constructor
	~matrix();    // 析构函数
	// 定义矩阵的一些操作 
	int rows() const;
	int cols() const;
	
	T& operator()(int i, int j) const;
	matrix<T>& operator=(const matrix<T>& mat);
	
	matrix<T> operator+();
	matrix<T> operator+(const matrix<T>& mat);  // 矩阵加法 
	matrix<T> operator-();
	matrix<T> operator-(const matrix<T>& mat);  // 矩阵减法 
	matrix<T> operator*(const matrix<T>& mat) const;   // 矩阵乘法 
	matrix<T> operator+=(const T num); 
	matrix<T> tranpose() const;  
	void print_matrix() const;     // 输出矩阵 
};

template<typename T>
matrix<T>::matrix(int row, int col)
{
	// 判断矩阵的合法性
	if(row<=0 || col<=0)
	{
		throw runtime_error("Rows and cols must > 0");
	} 
	// 创建矩阵
	this->row = row;
	this->col = col;
	element = new T[row*col];
}

template<typename T>
matrix<T>::matrix(const matrix<T>& mat)        
{
	row = mat.rows();
	col = mat.cols();
	this->element = new T[row*col];
	for(int i=0; i<row*col; i++)
	{
		element[i] = mat.element[i];
	}
}

template<typename T>
matrix<T>::~matrix()
{
	delete [] element;
}

template<typename T>
int matrix<T>::rows() const
{
	return row;
}

template<typename T>
int matrix<T>::cols() const
{
	return col;
} 

/*
template<typename T>
T& matrix<T>::operator()(int i, int j)  //矩阵下表的最最小值是1 
{
	int tmp = col*(i-1)+(j-1); 
	return element[tmp]; 
}*/


template<typename T>
matrix<T>& matrix<T>::operator=(const matrix<T>& mat)
{
	if(this!=&mat)   // 不能复制自己
	{
		delete [] element;   // 将原来的element删除
		row = mat.row;
		col = mat.col;
		element = new T [row*col];
		// 复制元素
		for(int i=0; i<(row*col); i++)
		{
			element[i] = mat.element[i];
		} 
	} 
	return *this;
}

// 用()表示矩阵索引
template<typename T>
T& matrix<T>::operator()(int i, int j) const
{
	if(i>row || i<1 || j>col || j<1)
	{
		//throw invalid_argument("Matrix index out of bounds"); 
		throw index_OutOf_Bound(i, j);
	}
	return element[col*(i-1)+(j-1)];
} 


template<typename T>
matrix<T> matrix<T>::operator+()
{
	return *this;
} 

//定义矩阵加法
template<typename T>
matrix<T> matrix<T>::operator+(const matrix<T>& mat)
{
	// 先判断矩阵的维度
	if(col!=mat.cols() || row!=mat.rows())
	{
		//throw runtime_error("The matrix size mismatch");
		throw size_mismatch_exception(row, col, mat.row, mat.col);   // 矩阵维度不匹配 
	} 
	matrix<T> w(row, col);   // 定义一个新的矩阵
	for(int i=0; i<row*col; i++)
	{
		w.element[i] = element[i] + mat.element[i];
	} 
	return w;
}

template<typename T>
matrix<T> matrix<T>::operator-()
{
	matrix<T> tmp(row, col);
	for(int i=0; i<row*col; i++)
	{
		tmp.element[i] = -element[i];
	}
	return tmp;
}

// 定义矩阵减法
template<typename T>
matrix<T> matrix<T>::operator-(const matrix<T>& mat)
{
	if(col!=mat.cols() || row!=mat.rows())
	{
		//throw runtime_error("The matrix size mismatch");
		throw size_mismatch_exception(row, col, mat.row, mat.col);   // 矩阵维度不匹配
	} 
	matrix<T> w(row, col);   // 定义一个新的矩阵
	for(int i=0; i<row*col; i++)
	{
		w.element[i] = element[i] - mat.element[i];
	} 
	return w;
}
 
template<typename T>
matrix<T> matrix<T>::operator+=(const T num)
{
	matrix<T> w(row, col);
	for(int i=0; i<row*col; i++)
	{
		w.element[i] = element[i] +num;
	}
	return w;
} 

//定义矩阵乘法
template<typename T>
matrix<T> matrix<T>::operator*(const matrix<T>& mat) const
{
	// 先判断矩阵的维度
	if(col!=mat.rows())
	{
		// throw runtime_error("Matrix size mismatch");
		throw size_mismatch_exception(row, col, mat.row, mat.col);
	} 
	matrix<T> w(row, mat.col);
	for(int i=1; i<=row; i++)
	{
		for(int j=1; j<=mat.col; j++)
		{
			T sum = element[col*(i-1)+(1-1)] * mat(1, j);   // 注意这里的处理方法 。先直接计算第一项,相当于给sum赋初值,因为这里的sum不能初始化为0 
			for(int k=2; k<=col; k++)    // k从2开始 
			{
				sum += element[col*(i-1)+(k-1)] * mat(k, j);
			}
			w(i, j) = sum;
		}
	}
	return w;
}
 
template<typename T>
void matrix<T>::print_matrix() const
{
	for(int i=1; i<=row; i++)
	{
		for(int j=1; j<=col; j++)
		{
			cout << element[col*(i-1)+(j-1)] << " ";
		}
		cout << endl;
	}
	cout << endl;
} 

template<typename T>
matrix<T> matrix<T>::tranpose() const
{
	matrix<T> tmp(col, row);  // 存放转置后的矩阵
	for(int i=1; i<=row; i++)
	{
		for(int j=1; j<=col; j++)
		{
			tmp(j,i) = element[col*(i-1)+(j-1)];
		}
	} 
	return tmp;
}
#endif

测试函数:

main.cpp

#include <iostream>
#include "E:\back_up\code\c_plus_code\matrix\external_file\matrix.h"
//#include <stdexcept>

using namespace std;


int main(int argc, char *argv[])
{
	
	// 矩阵乘法;
	matrix<int> m6(2,3);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=3; j++)
		{
			m6(i,j)= (i-1)*3+j;
		}
	} 
	
	matrix<int> m7(2,2);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=2; j++)
		{
			m7(i,j) = (i-1)*2+j;
		}
	}
	
	m6.print_matrix();
	m7.print_matrix();
	matrix<int> m8;
	try    // 添加异常捕获代码; 
	{
		m8 = m6*m7;
		cout << "---测试 operator*  ----" << endl;
		m8.print_matrix();
		
		cout << "---测试 transpose  ----" << endl;
		matrix<int> m9;
		m9 = m8.tranpose();
		m9.print_matrix();
		
	}
    catch(size_mismatch_exception& ex)
	{
		cout << "Exception: " << ex.what() << endl;
		ex.diaplay_error_detail();
	}
	 
	
	/*********测试indexException*************/
	matrix<int> m1(2,3);
	for(int i=1; i<=2; i++)
	{
		for(int j=1; j<=3; j++)
		{
			m1(i,j)= (i-1)*3+j;
		}
	} 
	m1.print_matrix();
	try
	{
		int a = m1(1,2);
		int b = m1(2,4);
		cout << "result is " << (a+b) << endl; 
	}
	catch(index_OutOf_Bound& ex)
	{
		cout << ex.what() << endl;
		ex.display_exception_info();
	}
	return 0;
	
}

测试结果:

------------------------------------------------------分割线----------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

posted @ 2019-02-26 15:08  Alpha205  阅读(141)  评论(0编辑  收藏  举报