C++(数据结构与算法):15---矩阵的实现(数组形式)

一、数组实现矩阵

  • 我们不使用二维数组来实现矩阵,而是将矩阵映射到一个一位数组中

二、代码设计

异常类定义

class illegalParamterValue
{
private:
	string message;
public:
	illegalParamterValue() : message("Illegal Paramter Value") {}
	illegalParamterValue(const char* s) :message(s) {}
	const char* what() {
		return message.c_str();
	}
};
class matrixIndexOutOfBounds
{
public:
	matrixIndexOutOfBounds(string theMessage = "Matrix index out of bounds")
	{
		message = theMessage;
	}
	void outputMessage() { cout << message << endl; }
private:
	string message;
};

矩阵类定义 

template <typename T>
class matrix
{
	friend ostream& operator<< <>(ostream& out, matrix<T>& m);
public:
	matrix(int theRows=0,int theColumns=0);
	matrix(const matrix<T>& other);
	~matrix();

	int rows()const { return theRows; }
	int columns()const { return theColumns; }

	T& operator()(int i, int j)const;//数组用[]通过索引取值,我们设计的矩阵通过()通过索引取值
	matrix<T>& operator=(const matrix<T>&); //赋值运算符

	matrix<T> operator+()const; //一元+运算符
	matrix<T> operator+(const matrix<T>& other)const;//二元+运算符
	matrix<T> operator-()const; //一元-运算符
	matrix<T> operator-(const matrix<T>& other)const;//二元-运算符

	matrix<T> operator*(const matrix<T>& other)const; //矩阵相乘
	matrix<T>& operator+=(const T& m);//矩阵相加,返回自己
private:
	int theRows, theColumns;//行,列
	T *element;
};

构造函数、拷贝构造、析构函数

  • 时间复杂度:
    • 当T是一个内部数据类型时(整型、实型等),构造函数和析构函数复杂度为O(1)
    • 当T是一个自定义的数据类型时,构造函数和析构函数复杂度为O(theRows*theColumns),因为创建/释放数组,每个元素都需要调用构造/析构
template <typename T>
matrix<T>::matrix(int theRows, int theColumns)
{
	//如果输入的行和列都小于0
	if ((theRows < 0) || (theColumns < 0)) {
		throw illegalParameterValue("theRows or theColumns must be >=0");
	}

	//如果列或行有一个为0,那么另一个也必须为0
	if (((theRows == 0) || (theColumns == 0)) &&
		((theRows != 0) || (theColumns != 0))) {
		throw illegalParameterValue("Either both or neither rows and columns should be zero");
	}

	this->theRows = theRows;
	this->theColumns = theColumns;
	element = new T[theRows*theColumns];
}

template <typename T>
matrix<T>::matrix(const matrix<T>& other)
{
	this->theRows = other.theRows;
	this->theColumns = other.theColumns;
	this->element = new T[this->theRows*this->theColumns];

	copy(other.element, other.element+(other.theRows*other.theColumns),
		this->element);
}

template <typename T>
matrix<T>::~matrix()
{
	delete[] element;
	element = nullptr;
	theRows = 0;
	theColumns = 0;
}

运算符的重载

  • 复杂度:
    • 矩阵复制和两个矩阵相加所需的时间分别都是Θ(1)。那么矩阵复制构造函数和矩阵相加的渐近复杂度为O(theRows*theColumn)
    • 矩阵相乘的复杂度O(theRows*theColumn*other.theColumns)
template <typename T>
T& matrix<T>::operator()(int i, int j)const
{
	//备注:矩阵的索引从0开始
	if ((i<1) || (i>theRows) || (j<1) || (j>theColumns))
		throw matrixIndexOutOfBounds();

	return element[((i - 1)*theColumns)+(j - 1)];
}

template <typename T>
matrix<T>& matrix<T>::operator=(const matrix<T>& other)
{
	if (other != *this) {
		this->theColumns = other.theColumns;
		this->theRows = other.theRows;
		delete[] element;
		element = new T[theColumns*theRows];

		copy(other.element,other.element+(other.theRows*other.theColumns),this->element);
	}
	return *this;
}

template <typename T>
matrix<T> matrix<T>::operator+()const
{
	//一元+运算符,把矩阵中的所有元素都变正,负数变正用-
	matrix<T> tempMatrix(theRows, theColumns);

	for (int i = 0; i < theRows*theColumns; ++i) {
		if(element[i]<0)
			tempMatrix.element[i] = -element[i];
		else
			tempMatrix.element[i] = element[i];
	}

	return tempMatrix;
}

template <typename T>
matrix<T> matrix<T>::operator+(const matrix<T>& other)const
{
	if ((this->theRows != other.theRows) || (this->theColumns != other.theColumns))
		throw matrixIndexOutOfBounds();

	matrix<T> tempMatrix(this->theRows,this->theColumns);
	for (int i = 0; i < theRows*theColumns; i++)
		tempMatrix.element[i] = this->element[i] + other.element[i];

	return tempMatrix;
}

template <typename T>
matrix<T> matrix<T>::operator-()const
{
	//一元+运算符,把矩阵中的所有元素符号取反,负变正,正变负
	matrix<T> tempMatrix(this->theRows, this->theColumns);

	for (int i = 0; i < theRows*theColumns; ++i)
		tempMatrix.element[i] = -this->element[i];

	return tempMatrix;
}

template <typename T>
matrix<T> matrix<T>::operator-(const matrix<T>& other)const
{
	if ((this->theRows != other.theRows) || (this->theColumns != other.theColumns))
		throw matrixIndexOutOfBounds();

	matrix<T> tempMatrix(this->theRows, this->theColumns);
	for (int i = 0; i < theRows*theColumns; i++)
		tempMatrix.element[i] = this->element[i] - other.element[i];

	return tempMatrix;
}

template <typename T>
matrix<T> matrix<T>::operator*(const matrix<T>& other)const
{
	//如果矩阵的列数与other的行数不同,不能进行相乘
	if (this->theColumns!=other.theRows) {
		throw matrixIndexOutOfBounds();
	}

	matrix<T> tempMatrix(this->theRows,other.theColumns);

	int ct = 0,cm = 0, cw = 0;
	//对所有的i和j计算tempMatrix(i,j)
	for (int i = 1; i <= this->theRows; ++i)
	{
		//计算结果矩阵的第i行
		for (int j = 1; j <= other.theColumns; j++)
		{
			//计算tempMatrix(i,j)第一项
			T sum = element[ct] * other.element[cm];

			//累加其余所有项
			for (int k = 2; k <= this->theColumns; k++)
			{
				ct++; //*this中的第i行的下一项
				cm += other.theColumns;//m中的第j列的下一项
				sum += this->element[ct] * other.element[cm];
			}

			tempMatrix.element[cw++] = sum; //存储在tempMatrix(i,j)
			ct -= theColumns - 1;
			
			//从行的起点和下一列重新开始
			cm = j;
		}

		//从下一列的和第一列重新开始
		ct += theColumns;
		cm = 0;
	}

	return tempMatrix;
}

template <typename T>
matrix<T>& matrix<T>::operator+=(const T& x)
{
 	for (int i = 0; i < theRows*theColumns; i++)
		this->element[i] += x;

	return *this;
}

流运算符的重写

  • 备注:这个是全局函数,类的友元函数,重写时需要在<<后面添加“<>”,否则会出错
template<typename T>
ostream& operator<< <>(ostream& out, matrix<T>& m) 
{
	int index = 0;
	for (int i = 0; i < m.theRows; i++) {
		for (int j = 0; j < m.theColumns; j++) {
			out << m.element[index++]<<" ";
		}
		out << endl;
	}
	return out;
}

演示案例

int main()
{
	matrix<int> m(3, 3);

	for (int i = 1; i <= m.rows(); i++) {
		for (int j = 1; j <= m.columns(); j++) {
			m(i, j) = 1;
		}
	}
	cout << "m is:" << endl;
	cout << m<<endl;

	cout << "matrix + 1:"<< endl;
	m += 1;
	cout << m << endl;

	matrix<int> m2(m);
	cout << "m2 is:" << endl;
	cout << m2 << endl;


	cout <<"m+m2=:" << endl;
	cout << m+m2<< endl;

	cout << "m*m2=:" << endl;
	cout << m * m2 << endl;
	return 0;
}

三、遇到的问题

  • ①全局的<<运算符重载原先出错,后来在<<后面添加“<>”成功了
  • ②Visual Studio中使用copy函数出错了,解决办法右击.cpp文件属性:

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值