动态二维数组类(C++ Vector)

目录

🌟1【问题描述】

💓2【问题分析】

2.1类的定义

2.2关于vector

2.3如何输入

2.4矩阵相加与相乘

🌵3【完整代码】

🌟1【问题描述】

编写一个程序,定义一个安全、动态二维double型的数组类Matrix。

  • 实现Matrix table(row,col)定义row行col列的二维数组, row和col为正整数;

  • 实现table(i,j)访问table的第i行第j列的元素,行号和列号从0开始;

  • 实现Matrix的输入输出(>>、<<);

  • 实现矩阵加等、乘等运算(+=、*=),例:Matrix& operator+=(const Matrix&); Matrix& operator*=(const Matrix&);

  • 实现矩阵的赋值运算(=),例:Matrix& operator=(const Matrix&)。

【输入形式】

  • 第一行table1的行列值row1和col1,空格分隔;

  • 第二行table1的初始化值,共row1*col1个数据,空格分隔;

  • 第三行table2的行列值row2和col2,空格分隔;

  • 第四行table2的初始化值,共row2*col2个数据,空格分隔;

【输出形式】

  • Matrix的输出格式为row行col列, 数据空格分隔;

  • 若table1和table2不满足矩阵的加法和乘法运算规则,输出ERROR!;

  • 依次输出以下表达式的值,每个输出间隔一行;

  • table1(row1/2,col1/2);

  • table1 *= table2;

  • table1 += table2;

  • table1 = table2。

💓2【问题分析】

解决这个问题需要问自己几个问题:

  1. 类实现数组的输入、输出及运算,需用到运算符重载?
  2. 动态数组用什么办法赋值呐?每次new,还是用顺序容器vector?
  3. 矩阵的加法、乘法、赋值实现的条件与逻辑?

2.1类的定义

先别着急,先来看看我定义了类里的哪些内容吧!

class Matrix
{
public:

	//row:数组行数;col:数组列数;
	//flag=1:可以输出;flag=0:出错,输出Error
	int row, col, flag = 1;

	//用vector嵌套来存放动态二维数组
	vector<vector<double>> v;

	//输出对应行列的元素
	void table(const int i, const int j)
	{
		cout << v[i][j] << endl;
	}
	
	//我认为,由于采用嵌套vector,所以输入是难点
	friend ostream& operator<<(ostream& os, Matrix &m);
	friend istream& operator>>(istream& is, Matrix &m);
	Matrix& operator+=(const Matrix&); 
	Matrix& operator*=(const Matrix&);
	Matrix& operator=(const Matrix&);
};
  1. 成员属性:行数(row)、列数(col)、状态(flag,给输出服务,即判断经过矩阵运算后能不能输出,也就是矩阵的运算能否执行)。
  2. 成员函数:访问矩阵的某个元素(table)、输入输出重载、累加累乘重载、赋值重载。

2.2关于vector

这里,我选用了vector来实现动态数组。下图是C++的部分顺序容器,(源《C++ Primer》)实质就是把我们数据结构中自己写的顺序表、单链表、队列等封装好,直接供我们使用。在以下容器中,我们最常使用的就是vector,除非我们有其他更好的理由选择其他容器。

 顺序容器几乎可以保存各种类型的元素,以vector为例

vector<int> v;    v里面存放着int的数据类型,类比int v[N];

vector<double> v;    v里面存放着double的数据类型,类比double v[N];

vector<string> v;     v里面存放着string的数据类型,类比char[M][N];

以上其实就定义了三个动态数组,前者数组大小可变,后者类比C语言,数组大小需提前固定好。

那二维动态数组,也就是类似于矩阵呢?

vector<vector<double>> v;    本题所用数据类型,类比double v[M][N];

定义好了数据类型,那vector是怎么样进行操作的呢?它不能使用我们的直接给数组赋值的操作,比如v[i][j]=n;(把n赋值给v[i][j]),但却支持v[n]这种访问方法,(string、array、deque、string都支持),而包括四者在内的顺序容器,更应该使用迭代器(现在不明白也没关系)。

下图是顺序容器的一些插入操作(源《C++ Primer》),对于vector,我们最常用的就是第一个。

v.push_back(t);    v是容器,t是添加的元素

vector其他的一些的操作:

v.pop_back();    删除v中最后一个元素

v.clear();    删除v中所有元素

2.3如何输入

有了以上储备,我们就可以开始输入数组啦!先看代码。

istream& operator>>(istream& is, Matrix& m)
{
	//先输入行列数
	cin >> m.row >> m.col;

	//x为即将输入的数组元素
	double x=0.0;

	//v是二维数组:把一行里的元素作为整体存储,如:v[i][N]是数组的第i行
	//vv是一维数组:存某一行里的不同列的元素,如:在存第一行元素时,vv[j]是第一行第j个元素
	//vector作为顺序容器,长度可变,输入操作为v.push_back(x),不能用赋值的方法输入
	vector<double> vv;
	m.v.clear();
	for (int i = 0; i < m.row; i++)
	{
		//清除vv里上一次存过的元素,方便多次使用
		vv.clear();
		for (int j = 0; j < m.col; j++)
		{
			cin >> x;
			//用vv来存某一行的不同列的元素
			vv.push_back(x) ;
		}
		//一行输入完后就整体存入v,即将此时的vv存入v
		m.v.push_back(vv);
	}
	return is;
}

注意理解那两层循环的意义:vector支持一维数组的直接输入,那二维数组怎么输入呢?

vector创建一个一维数组并将其反复插入到二维数组中,如下图:

 

注意:为方便,我展示时看似数组大小固定了的,实际上是一边添加一个元素,一边分配一个空间。

2.4矩阵相加与相乘

矩阵加法:两矩阵行数列数相等,对应元素相加。

矩阵乘法:(m*n)第一个矩阵的列数n=(n*k)第二个矩阵的行数n,结果为(m*k)的矩阵,举个例子。

\begin{bmatrix} 1 & 2&3\\ 4 & 5&6 \end{bmatrix}\cdot \begin{bmatrix} 7 &8 \\ 9&10 \\ 11& 12 \end{bmatrix}

第一行第一列:1\times 7\dotplus 2\times9 \dotplus3\times 11= 58

第一行第二列:1\times 8\dotplus 2\times10 \dotplus3\times 12= 64

第二行第一列:4\times 7\dotplus 5\times9 \dotplus6\times 11= 139

第二行第二列:4\times 8\dotplus 5\times10 \dotplus6\times12= 154

结果:

\begin{bmatrix} 58&64& \\139&154\end{bmatrix}


我们的算法也就应该模拟上述的过程。(上面的加号有点不对劲)

Matrix& Matrix:: operator+=(const Matrix& m)
{
	//相加的条件:行列数均相等
	//相加:即对应元素相加
	if (row == m.row && col == m.col)
	{
		for (int i = 0; i < row; i++)
		{
			for (int j = 0; j < col; j++)
			{
				v[i][j] += m.v[i][j];
			}
		}
	}
	else
	{
		flag = 0;
	}
	return *this;
}
Matrix& Matrix:: operator*=(const Matrix& m)
{
	//相乘条件:前一个的列数=后一个的行数
	//注意两矩阵相乘的过程
	if (col == m.row )
	{
		for (int i = 0; i < row; i++)
		{
			double sum = 0;
			for (int j = 0; j < m.col; j++)
			{
				for (int k = 0; k < col; k++)
				{
					sum += v[i][k] * m.v[k][j];
				}
				v[i][j] = sum;
			}
			
		}
	}
	else
	{
		flag = 0;
	}
	return *this;
}

🌵3【完整代码】

#include<iostream>
#include<vector>
using namespace std;
class Matrix
{
public:

	//row:数组行数;col:数组列数;
	//flag=1:可以输出;flag=0:出错,输出Error
	int row, col, flag = 1;

	//用vector嵌套来存放动态二维数组
	vector<vector<double>> v;

	//输出对应行列的元素
	void table(const int i, const int j)
	{
		cout << v[i][j] << endl;
	}
	
	//我认为,由于采用嵌套vector,所以输入是难点
	friend ostream& operator<<(ostream& os, Matrix &m);
	friend istream& operator>>(istream& is, Matrix &m);
	Matrix& operator+=(const Matrix&); 
	Matrix& operator*=(const Matrix&);
	Matrix& operator=(const Matrix&);
};

istream& operator>>(istream& is, Matrix& m)
{
	//先输入行列数
	cin >> m.row >> m.col;

	//x为即将输入的数组元素
	double x=0.0;

	//v是二维数组:把一行里的元素作为整体存储,如:v[i][N]是数组的第i行
	//vv是一维数组:存某一行里的不同列的元素,如:在存第一行元素时,vv[j]是第一行第j个元素
	//vector作为顺序容器,长度可变,输入操作为v.push_back(x),不能用赋值的方法输入
	vector<double> vv;
	m.v.clear();
	for (int i = 0; i < m.row; i++)
	{
		//清除vv里上一次存过的元素,方便多次使用
		vv.clear();
		for (int j = 0; j < m.col; j++)
		{
			cin >> x;
			//用vv来存某一行的不同列的元素
			vv.push_back(x) ;
		}
		//一行输入完后就整体存入v,即将此时的vv存入v
		m.v.push_back(vv);
	}
	return is;
}
ostream& operator<<(ostream& os, Matrix& m)
{
	if (m.flag != 0)
	{
		for (int i = 0; i < m.row - 1; i++)
		{
			for (int j = 0; j < m.col - 1; j++)
			{
				cout << m.v[i][j] << " ";
			}
			cout << m.v[i][m.col - 1] << endl;
		}
		//主要是考虑每一行最后一个元素后接endl,而不是" "
		//最后一行的最后一个元素无endl
		for (int j = 0; j < m.col - 1; j++)
		{
			cout << m.v[m.row - 1][j] << " ";
		}
		cout << m.v[m.row - 1][m.col - 1];
	}
	//如果被标志过,即两数组不能相加、相乘,就输出错误
	else
	{
		cout << "ERROR!";
	}
		return os;
}
Matrix& Matrix:: operator+=(const Matrix& m)
{
	//相加的条件:行列数均相等
	//相加:即对应元素相加
	if (row == m.row && col == m.col)
	{
		for (int i = 0; i < row; i++)
		{
			for (int j = 0; j < col; j++)
			{
				v[i][j] += m.v[i][j];
			}
		}
	}
	else
	{
		flag = 0;
	}
	return *this;
}
Matrix& Matrix:: operator*=(const Matrix& m)
{
	//相乘条件:前一个的列数=后一个的行数
	//注意两矩阵相乘的过程
	if (col == m.row )
	{
		for (int i = 0; i < row; i++)
		{
			double sum = 0;
			for (int j = 0; j < m.col; j++)
			{
				for (int k = 0; k < col; k++)
				{
					sum += v[i][k] * m.v[k][j];
				}
				v[i][j] = sum;
			}
			
		}
	}
	else
	{
		flag = 0;
	}
	return *this;
}
Matrix& Matrix::operator=(const Matrix& m)
{
	//赋值类似于输入,需要修改row、col
	flag = 1;
	row = m.row;
	col = m.col;
	vector<double> vv;
	v.clear();
	for (int i = 0; i < m.row; i++)
	{
		vv.clear();
		for (int j = 0; j < m.col; j++)
		{
			vv.push_back(m.v[i][j]);
		}
		v.push_back(vv);
	}
	return *this;
}
int main()
{
	Matrix m1, m2;
	cin >> m1 >> m2;

	m1.table(m1.row / 2, m1.col / 2);

	m1 *= m2;
	cout << m1 << endl;

	m1 += m2;
	cout << m1 << endl;

	m1 = m2;
	cout << m1;
	return 0;
}


 补充:输入输出运算符重载可以格式化,感谢大家的建议!

头文件#include<iomanip>

std::ostream& operator<<(std::ostream& os, const Matrix &m);

std::istream& operator>>(std::istream& is, const Matrix &m);

  • 16
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
在C++中,可以使用vector来实现动态二维数组。创建一个二维数组可以使用以下方法: vector<vector<int>> asd1(row, vector<int>(column, 0)); 这行代码创建了一个row行column列的二维动态数组,初始化值为0。其中,row和column是你想要的行数和列数,可以根据实际需求进行更改。 此外,在C++中,vector是一种常用的动态数组,它是C++标准模板库(STL)中的一部分。它封装了我们自己写的顺序表、单链表、队列等数据结构,提供了方便的操作接口。在容器中,我们最常使用的就是vector。 如果你想遍历一个二维vector中的所有元素,你可以使用以下代码: void Print(vector<vector<int>> a) { vector<vector<int>>::iterator p1; vector<int>::iterator p2; for (p1 = a.begin(); p1 != a.end(); p1++) { for (p2 = p1->begin(); p2 != p1->end(); p2++) { cout << "[" << *p2 << "]"; } cout << endl; } cout << endl; } 这段代码可以遍历二维vector中的所有元素,并将其打印出来。你可以根据需要进行适当修改。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C++ 动态二维数组(二维vector)](https://blog.csdn.net/qq_38289815/article/details/106052582)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [动态二维数组类(C++ Vector)](https://blog.csdn.net/weixin_54186646/article/details/123442733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

~在下小吴

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

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

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

打赏作者

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

抵扣说明:

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

余额充值