以一维数组存储的矩阵C++语言描述(包括稀疏矩阵三元组的表达),实现矩阵的基本运算(加减乘)及矩阵类的拷贝控制

行主映射:将矩阵依此从每一行的索引从左至右连续编号,将二维矩阵的索引映射为一维数组。
列主映射:将矩阵依此从每一列的索引从上至下连续编号,将二维矩阵的索引映射为一维数组。
本文的多种矩阵均采用行主映射,使用一维数组来表达多种矩阵。例如按照常规对二维矩阵进行描述的C++二维数组中,矩阵元素M(3,5)对应二维数组Array[2][4]。而采用一维映射后,该元素对应一维数组的Array[3*矩阵的列+5-1]。这样映射的好处在于节省内存空间,提高一些操作(如转置,矩阵乘法)的运行效率,虽然对于一般矩阵的提升不够明显,但是对于类似一些特殊矩阵(如对角矩阵、三对角矩阵、稀疏矩阵)所带来的效果极其明显。
对于特殊矩阵,需要重新定义数据结构进行存储。常见的一种方法是用三元组表达(row,col,value),以节省空间并提高效率。同时,因为与常规矩阵结构的不同,其加减乘除等操作需要重新编写算法。
本文中会用到以前编写的自定义异常类、数组线性表等程序。见线性表–数组/vecotr描述

一般矩阵(m*n):

实现矩阵的加/减/乘运算和矩阵类的各种拷贝控制成员以及其它一些读写操作。具体思想以及其他一些思考见注释。

#pragma once
#include <iostream>
#include <algorithm>
#include <iomanip>
#include "../../../ch06/ChainList/ChainList/illegalParameterValue.h"
using std::cin; using std::cout; using std::ends; using std::endl;

//前置声明
template <typename T> class myMatrix;
//将operator<<声明为模板 使用myMatrix的模板形参作为自己的模板实参 限定友好关系
template <typename T> std::ostream& operator<<(std::ostream& os,const myMatrix<T>& matrix);

template <typename T>
class myMatrix{
   
	friend std::ostream& operator<<<T>(std::ostream& os,const myMatrix<T>& matrix);
public:
	myMatrix()= default;
	myMatrix(size_t _row,size_t _col);
	myMatrix(const myMatrix<T>& rhs);//copy constructor
	myMatrix(myMatrix<T>&& rhs);//move construcotr
	~myMatrix() {
    delete element; }

	size_t get_row()const {
    return row; }
	size_t get_col()const {
    return col; }
	T& operator()(size_t _row,size_t _col) const;//重载()来表示矩阵行列的索引 并完成矩阵数学逻辑上的索引到内存数组索引的映射
	void set(size_t _row,size_t _col,const T& _element);//改变矩阵(i,j)元素
	void reset();//将矩阵全部元素复位为0
	myMatrix<T>& tranpose();//将矩阵转置

	myMatrix<T>& operator=(const myMatrix<T>& rhs);//copy assignment
	myMatrix<T>& operator=(myMatrix<T>&& rhs);//move assignment
	myMatrix<T> operator+(const myMatrix<T>& rhs) const;//矩阵加法
	myMatrix<T> operator-(const myMatrix<T>& rhs) const;//矩阵减法
	myMatrix<T> operator*(const myMatrix<T>& rhs) const;//矩阵乘法
	myMatrix<T> operator+() const;//一元操作符+ 取正
	myMatrix<T> operator-() const;//一元操作符- 取负
	myMatrix<T>& operator+=(const myMatrix<T>& rhs);//复合赋值运算符
	myMatrix<T>& operator+=(size_t _unit);//复合赋值运算符 该矩阵加上一个数_unit(即_unit个单位矩阵)
	myMatrix<T>& operator-=(const myMatrix<T>& rhs);//复合赋值运算符
	myMatrix<T>& operator-=(size_t _unit);//复合赋值运算符 该矩阵减去一个数_unit(即_unit个单位矩阵)
	myMatrix<T>& operator*=(size_t _unit);//复合赋值运算符 该矩阵乘以一个数_unit(即_unit个单位矩阵)
private:
	size_t row, col;//矩阵的行列
	T* element;//数组element
	
	void check_if_same_size(size_t rhs_col,size_t rhs_row)const;//检查2个矩阵是否行可加减(行数列数相同)
	void check_if_multiplicable(size_t rhs_row) const;//检查2个矩阵是否可相乘(列数=行数)
};

template <typename T>
myMatrix<T>::myMatrix(size_t _row,size_t _col):row(_row),col(_col) {
   
	//检验矩阵行列参数的有效性
	if (row < 0 || col < 0) throw illegalParameterValue("Rows and columns must be>=0!");
	//行列不能只有其中一个为0(可以同时为0 生成0*0的矩阵)
	if ((row == 0 || col == 0) && (row != 0 || col != 0))
		throw illegalParameterValue("Either both or neither rows and columns should be 0!");
	element = new T[row*col];
}

template <typename T>
myMatrix<T>::myMatrix(const myMatrix<T>& rhs):row(rhs.row),col(rhs.col) {
   //拷贝构造函数
	element = new T[row*col];
	//利用std::copy拷贝rhs的元素
	//注意 copy(start,end,target)的拷贝范围是[start,end) 所以end要比元素个数多1
	std::copy(rhs.element, rhs.element + rhs.row*rhs.col, element);
}

template <typename T>
myMatrix<T>::myMatrix(myMatrix<T>&& rhs) :row(rhs.row),col(rhs.col),element(rhs.element){
   //移动构造函数
	//直接接管资源 然后将rhs置于可析构状态
	cout << "move constructor" << endl;
	rhs.element = nullptr;
}

template <typename T>
T& myMatrix<T>::operator()(size_t _row,size_t _col) const{
   
	//检查序列(row,col)是否合法
	if (_row<1 || _col<1 || _row>row || _col>col)
		throw illegalParameterValue("i or j of matrix(i,j) out of range");
	return element[(_row-1)*col+(_col-1)];//数学逻辑到物理地址的映射
}

template <typename T>
void myMatrix<T>::set(size_t _row,size_t _col,const T& _element) {
   
	operator()(_row,_col) = _element;
}

template <typename T>
void myMatrix<T>::reset() {
   //将所有元素置为0
	for (size_t i = 0; i < row*col; ++i)
		element[i] = 0;
}

template <typename T>
void myMatrix<T>::check_if_same_size(size_t rhs_row,size_t rhs_col)const {
   
	if (row != rhs_row || col != rhs_col)
		throw illegalParameterValue("rows and columns of two matrixs must be the same!");
}

template <typename T>
void myMatrix<T>::check_if_multiplicable(size_t rhs_row)const {
   
	if (col != rhs_row)
		throw illegalParameterValue("columns of left matrix and rows of right matrix must be the same to multiply!");
}
template <typename T>
myMatrix<T>& myMatrix<T>::operator=(const myMatrix<T>& rhs) {
   //拷贝赋值运算符
	//先拷贝再释放内存避免自赋值
	row = rhs.row;
	col = rhs.col;
	T* newdata = new T[row*col];
	std::copy(rhs.element, rhs.element + row*col, newdata);
	delete[] element;
	element = newdata;
}

template <typename T>
myMatrix<T>& myMatrix<T>::operator=(myMatrix<T>&& rhs) {
   //移动赋值运算符
	//直接接管资源
	if (this!=&rhs) {
   //避免自赋值
		row = rhs.row;	
		col = rh
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值