一、数组实现矩阵
- 我们不使用二维数组来实现矩阵,而是将矩阵映射到一个一位数组中
二、代码设计
异常类定义
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文件属性: