传统二维数组是个标准的矩阵,每行的元素数量相同
int a[3][5];
使用指针数组可以创建一个不规则二维数组
#include <iostream>
using namespace std;
#include <iostream>
using namespace std;
int main()
{
int numberOfRows = 5;//行数
int length[] = { 5,3,4,5,7 };//每一行的长度
int** irregularArray = new int* [numberOfRows];//定义一个指针数组,数组中的指针还没分配
//int* irregularArray[] = new int* [numberOfRows];也是一样的
for (int i = 0; i < numberOfRows; i++) {//给数组里的指针分配指定长度的数组
irregularArray[i] = new int[length[i]];
}
irregularArray[1][2] = 2;
//记得delete所有new出来的东西
for (int i = 0; i < numberOfRows; i++) {
delete []irregularArray[i];
}
delete []irregularArray;
}
下面定义一个矩阵类matrix
#pragma once
#include <iostream>;
using namespace std;
template<class T>
class matrix
{
friend ostream& operator<<(ostream& out, const matrix<T>& x) {x.output(out); return out;}//重载<<
public:
matrix(int theRows = 0, int theColumns = 0);//构造函数
matrix(T **a,int theRows = 0, int theColumns = 0);//构造函数(使用数组赋值)
matrix(const matrix<T>&);//构造函数(复制)
~matrix() { delete []element; };//析构函数,删除存放元素的数组
int rows() const { return theRows; }//返回行数
int columns() const { return theColumns; }//返回列数
matrix<T> transposition();//转置
T& operator()(int i, int j)const;//重载(),通过此函数使用二维索引访问矩阵元素
matrix<T>& operator=(const matrix<T>&);//重载=,复制每个元素
matrix<T> operator+(const matrix<T>&) const;//重载+
matrix<T> operator-(const matrix<T>&) const;//重载-
matrix<T> operator*(const matrix<T>&) const;//重载*
void output(ostream& out) const;//逐个输出元素值,提供给<<重载用
private:
int theRows, theColumns;//行数和列数
T* element;//用来存储数据的数组
};
三种重载函数,注意动态二维数组的创建与调用方法
//matrix.cpp
#include <iostream>;
#include "matrix.h";
/*-------------构造函数--------------------------*/
template<class T>
matrix<T>::matrix(int theRows, int theColumns) {
this->theRows = theRows;
this->theColumns = theColumns;
element = new T[theRows * theColumns];//一维数组,用行主映射转换
}
/*-------------构造函数(复制)-----------------*/
template<class T>
matrix<T>::matrix(const matrix<T>& m) {
theRows = m.theRows;
theColumns = m.theColumns;
element=new T[theRows * theColumns];
copy(m.element, m.element + theRows * theColumns, element);//使用copy函数获得被复制矩阵数组的值
}
/*-------------构造函数(并赋值)---------------*/
template<class T>
matrix<T>::matrix(T **a, int theRows, int theColumns) {
this->theRows = theRows;
this->theColumns = theColumns;
element = new T[theRows * theColumns];
for (int i = 0; i < theRows; i++)
for (int j = 0; j < theColumns; j++)
element[i * theColumns + j] = a[i][j];
}
//main.cpp
int main()
{
int **a = new int*[5];//创建二维动态数组
//分配每一行的数组
a[0] = new int[5]{ 1,2,3,4,5 };
a[1] = new int[5]{ 1,2,3,4,5 };
a[2] = new int[5]{ 1,2,3,4,5 };
matrix<int>* m = new matrix<int>(a,3,5);//创建matrix并通过数组赋值
delete []a[0];
delete []a[1];
delete []a[2];
delete []a;//记得删除动态数组
delete m;
return 0;
}
之后是各种运算符重载,要特别注意哪些函数返回的是引用
以重载()为例, 重载后()返回矩阵二维索引的值,这里我们设置矩阵的索引从1开始而不是数组的0开始,符合日常生活习惯。函数很简单,换算一下二维索引和一维数组的映射关系就行
template<class T>
T& matrix<T>::operator()(int i, int j) const{
return element[(i - 1) * theColumns + j - 1];//矩阵的索引从1开始
}
重点是函数返回的是引用,这就代表我们不仅可以通过这个函数访问对应的元素值,还可以直接改变这个值,请看下面的示例 注:调用()函数时记得给前面 *m 打上括号,要不然会报错
int main()
{
int **a = new int*[3];
a[0] = new int[5]{ 1,2,3,4,5 };
a[1] = new int[5]{ 1,2,3,4,5 };
a[2] = new int[5]{ 1,2,3,4,5 };
matrix<int>* m = new matrix<int>(a,3,5);
cout << (*m)(1, 1) << endl;//获得矩阵(1,1)处的值
(*m)(1, 1) = 0;
cout << (*m)(1, 1) << endl;//改写矩阵(1,1)处的值
delete []a[0];
delete []a[1];
delete []a[2];
delete[]a;
delete m;
return 0;
}
加法和减法符号的重载
/*-------------加法(+)重载--------------------------*/
template<class T>
matrix<T> matrix<T>::operator+(const matrix<T>& m) const {//函数调用时使用引用符&避免复制浪费效率,使用const防止更改
matrix<T> w(theRows, theColumns);
for (int i = 0; i < theRows * theColumns; i++)
w.element[i] = element[i] + m.element[i];//对应位置的值相加
return w;
}
/*-------------劵大小是否匹配
matrix<T> w(theRows, m.theColumns);//定义结果矩阵
int ct = 0, cm = 0, cw = 0;//定义游标
for (int i = 1; i <= theRows; i++) {
for (int j = 1; j <= m.theColumns; j++) {
T sum = element[ct] * m.element[cm];
//根据矩阵形状加上其他相乘的项
for (int k = 2; k <= theColumns; k++) {
ct++;
cm += m.theColumns;//向下一行在一维数组映射就是加一行的元素个数
sum += element[ct] * m.element[cm];
}
w.element[cw++] = sum;//先把结果存入数组指定位置,cw游标再加1
ct -= theColumns - 1;//第一个矩阵游标向下一行
cm = j;//第二个矩阵的游标回到第一行并向右移动一位
}
ct += theColumns;//第一个矩阵游标向下一行
cm = 0;//第二个矩阵游标归零
}
return w;
}
#include <iostream>;
#include "matrix.h";
#include "matrix.cpp";
using namespace std;
int main()
{
int **a = new int*[5];
a[0] = new int[5]{ 1,2,3,4,5 };
a[1] = new int[5]{ 1,2,3,4,5 };
a[2] = new int& class="wp-block-code">friend ostream& operator<<(ostream& out, const matrix<T>& x) {x.output(out); return out;}//重载<<
这样使用c<<输出就可以逐个打印矩阵中元素的值
之后是矩阵的转置,新建一个矩阵,形状从(rows,columns)变成 (columns,rows),相应的元素映射也很明显
template<class T>
matrix<T> matrix<T>::transposition() {
matrix<T> w(theColumns, theRows);//形状变换
for (int i = 0; i < w.theRows; i++)
for (int j = 0; j < w.theColumns; j++) {
w.element[i * w.theColumns + j] = element[i+j*theColumns];
}
return w;
}
剩下还有一个矩阵的乘法,二维矩阵的乘法规则还是相对简单的
template<class T>
matrix<T> matrix<T>::operator*(const matrix<T>& m)const {
if (theColumns != m.theRows) { abort(); };//检查矩阵大小是否匹配
matrix<T> w(theRows, m.theColumns);//定义结果矩阵
int ct = 0, cm = 0, cw = 0;//定义游标
for (int i = 1; i <= theRows; i++) {
for (int j = 1; j <= m.theColumns; j++) {
T sum = element[ct] * m.element[cm];
//根据矩阵形状加上其他相乘的项
for (int k = 2; k <= theColumns; k++) {
ct++;
cm += m.theColumns;//向下一行在一维数组映射就是加一行的元素个数
sum += element[ct] * m.element[cm];
}
w.element[cw++] = sum;//先把结果存入数组指定位置,cw游标再加1
ct -= theColumns - 1;//第一个矩阵游标向下一行
cm = j;//第二个矩阵的游标回到第一行并向右移动一位
}
ct += theColumns;//第一个矩阵游标向下一行
cm = 0;//第二个矩阵游标归零
}
return w;
}
#include <iostream>;
#include "matrix.h";
#include "matrix.cpp";
using namespace std;
int main()
{
int **a = new int*[5];
a[0] = new int[5]{ 1,2,3,4,5 };
a[1] = new int[5]{ 1,2,3,4,5 };
a[2] = new int[5]{ 1,2,3,4,5 };
matrix<int>* m1 = new matrix<int>(a,3,5);
matrix<int> m2 = *m1;
m2 = m2.transposition();//转置
cout<<m2 * (*m1)<<endl;//输出相乘结果
delete []a[0];
delete []a[1];
delete []a[2];
delete[]a;
delete m1;
return 0;
}
Comments 1 条评论
博主 W
上班来你这里摸小鳄鱼啦