[C++]稀疏矩阵(一维数组描述)

操作:

重载赋值、输入、输出运算符;
稀疏矩阵加法、乘法、转置。

代码:

#include<iostream>
#include<vector>
using namespace std;
struct matrixTerm//定义矩阵元素
{
	int row;
	int col;
	int value;
	matrixTerm()//初始化
	{
		row = 0;
		col = 0;
		value = 0;
	}
	matrixTerm& operator=(matrixTerm& b)//重载赋值运算符
	{
		row = b.row;
		col = b.col;
		value = b.value;
		return *this;
	}
};
class sparseMatrix//定义稀疏矩阵
{
private:
	int rows;//行数
	int cols;//列数
	int size;//非零元素个数
	vector<matrixTerm> arr;//使用vector按照行主顺序保存稀疏矩阵非零元素

public:
	sparseMatrix()//初始化
	{
		arr.clear();
		rows = cols = size = 0;
	}
	~sparseMatrix() { arr.clear(); }
	void setMatrix()//稀疏矩阵赋值(只给出非零元素的坐标和数值)
	{
		cin >> rows >> cols >> size;
		arr.clear();
		for (int i = 0; i < size; i++)
		{
			matrixTerm m;
			cin >> m.row >> m.col >> m.value;
			//读入的行列数值都是从1开始,将其改为从0开始
			m.row--;
			m.col--;
			arr.push_back(m);
		}
	}


	sparseMatrix& operator=(sparseMatrix& b)//重载赋值运算符
	{
		rows = b.rows;
		cols = b.cols;
		size = b.size;
		arr.clear();
		if(b.size>0)
			arr.assign(b.arr.begin(), b.arr.begin()+b.size);
		return *this;
	}
	friend istream& operator>>(istream& input, sparseMatrix& matrix);
	friend ostream& operator<<(ostream& output, sparseMatrix& matrix);

	void Add(sparseMatrix& b)//稀疏矩阵相加
	{
		if (b.rows != rows || b.cols != cols) //不合法的情况
		{
			*this = b;
			cout << -1 << endl;
			return;
		}
		if (b.size == 0)
			return;
		sparseMatrix res;
		res.rows = rows;
		res.cols = cols;
		res.size = 0;
		int i = 0, j = 0;
		int idxA = 0, idxB = 0;
		while (i < size && j < b.size)
		{
			idxA = arr[i].row * cols + arr[i].col;//将元素的二维下标转化为行主顺序下的一维下标
			idxB = b.arr[j].row * b.cols + b.arr[j].col;
			if (idxA < idxB)//A的元素在B之前,则该位置为A的元素
			{
				res.arr.push_back(arr[i]);
				i++;
				res.size++;
			}
			else if (idxA > idxB)//B的元素在A之前,则该位置为A的元素
			{
				res.arr.push_back(b.arr[j]);
				j++;
				res.size++;
			}
			else if (idxA == idxB)//AB位置相同,则两个元素相加
			{
				if (arr[i].value + b.arr[j].value != 0)
				{
					matrixTerm m;
					m.row = arr[i].row;
					m.col = arr[i].col;
					m.value = arr[i].value + b.arr[j].value;
					res.arr.push_back(m);
					res.size++;
				}
				i++;
				j++;
			}

		}
		//当有一者遍历完全之后,另一者量剩余元素加入新数组中
		for (; i < size; i++)
		{
			res.arr.push_back(arr[i]);
			res.size++;
		}
		for (; j < b.size; j++)
		{
			res.arr.push_back(b.arr[j]);
			res.size++;
		}
		*this = res;
	}

	void Multiply(sparseMatrix& b)//稀疏矩阵相乘
	{
		if (cols != b.rows)//不合法的情况
		{
			*this = b;
			cout << -1 << endl;
			return;
		}
		sparseMatrix res;
		res.rows = rows;
		res.cols = b.cols;
		res.size = 0;
		res.arr.clear();
		if (size == 0 || b.size == 0)//如果有零矩阵参与相乘,则结果必为零矩阵
		{
			*this = res;
			return;
		}
		int* rowSize = new int[b.rows];//记录矩阵b每行非零元素个数
		int* rowStart = new int[b.rows + 1];//记录矩阵b每行第一个非零元素在一维数组中的下标
		int* temp = new int[b.cols];//用于临时存放结果矩阵每一行的所有元素的值
		int i, Current, lastInResult, RowA, ColA, ColB;  //Current用于遍历矩阵a
		for (i = 0; i < b.rows; i++)
			rowSize[i] = 0;
		for (i = 0; i < b.size; i++)
			rowSize[b.arr[i].row]++;
		rowStart[0] = 0;
		rowStart[b.rows] = b.size;
		for (i = 1; i < b.rows; i++)
			rowStart[i] = rowStart[i - 1] + rowSize[i - 1];
		Current = 0;
		while (Current < size) {
			RowA = arr[Current].row;
			for (i = 0; i < b.cols; i++)//临时数组初始化
				temp[i] = 0;
			while (Current < size && arr[Current].row == RowA) {//每次循环让矩阵a在同一行的元素参与运算,从而得到结果矩阵的一行
				ColA = arr[Current].col;
				for (i = rowStart[ColA]; i < rowStart[ColA + 1]; i++) {//让矩阵a的每个元素与在ColA行的矩阵b的元素相乘,结果加到temp中
					ColB = b.arr[i].col;
					temp[ColB] += arr[Current].value * b.arr[i].value;
				}
				Current++;
			}
			for (i = 0; i < b.cols; i++) {
				if (temp[i] != 0) //将temp的每个非零元素加入到结果矩阵一维数组中
				{
					matrixTerm m;
					m.row = RowA;
					m.col = i;
					m.value = temp[i];
					res.arr.push_back(m);
					res.size++;
				}
			}
		}
		delete[] rowSize;
		delete[] rowStart;
		delete[] temp;
		*this = res;

	}

	void Transpose()//稀疏矩阵转置
	{
		sparseMatrix res;
		res.rows = cols;
		res.cols = rows;
		res.size = size;
		res.arr.clear();
		if (size == 0)
		{
			*this = res;
			return;
		}
		int* rowSize = new int[cols];//记录原矩阵每列元素个数->转置之后的矩阵每行非零元素个数
		int* rowStart = new int[cols];//记录新矩阵每行第一个非零元素在新矩阵一维数组中的位次
		matrixTerm* tempArr = new matrixTerm[size];//由于容器vector不能访问未赋值的位置,故先将转置结果存放到临时数组中
		for (int i = 0; i < cols; i++)
			rowSize[i] = 0;
		for (int i = 0; i < size; i++)
			rowSize[arr[i].col]++;
		rowStart[0] = 0;
		for (int i = 1; i < cols; i++)
			rowStart[i] = rowSize[i - 1] + rowStart[i - 1];
		for (int i = 0; i < size; i++)//将元素依次填入新矩阵一维数组的对应位置
		{
			int j = rowStart[arr[i].col];
			tempArr[j].row = arr[i].col;
			tempArr[j].col = arr[i].row;
			tempArr[j].value = arr[i].value;
			rowStart[arr[i].col]++;
		}
		res.arr.assign(tempArr,tempArr+size);
		delete[]tempArr;
		delete[]rowSize;
		delete[]rowStart;
		*this = res;
	}
};
istream& operator>>(istream& input, sparseMatrix& matrix)//重载输入运算符,读入正常矩阵
{
	input >> matrix.rows >> matrix.cols;
	matrix.size = 0;
	matrix.arr.clear();
	int v = 0;
	for (int i = 0; i < matrix.rows; i++)//读入标准矩阵
	{
		for (int j = 0; j < matrix.cols; j++)
		{
			input >> v;
			if (v != 0)//若矩阵该项非零,则将其加入稀疏矩阵
			{
				matrixTerm m;
				m.value = v;
				m.row = i;
				m.col = j;
				matrix.arr.push_back(m);
				matrix.size++;
			}
		}

	}
	return input;

}
ostream& operator<<(ostream& output, sparseMatrix& matrix)//重载输出运算符,按照正常矩阵的格式输出稀疏矩阵
{
	output << matrix.rows << " " << matrix.cols << endl;
	if (matrix.rows == 0 || matrix.cols == 0)
		return output;
	if (matrix.size == 0)//矩阵全零,稀疏矩阵为空
	{
		for (int i = 0; i < matrix.rows; i++)
		{
			for (int j = 0; j < matrix.cols; j++)
			{
				output << 0 << " ";
			}
			output << endl;
		}
	}
	else
	{
		int count = 0;
		for (int i = 0; i < matrix.rows; i++)
		{
			for (int j = 0; j < matrix.cols; j++)
			{
				if (count < matrix.size&&matrix.arr[count].row == i && matrix.arr[count].col == j)
				{
					output << matrix.arr[count].value << " ";
				    count++;
				}
				else
					output << 0 << " ";
			}
			output << endl;
		}
	}
	return output;
}


int main()
{
	int n;//输入操作次数
	cin >> n;
	sparseMatrix matrix;
	sparseMatrix m;
	int t = 0;
	for (int i = 0; i < n; i++)
	{
		cin >> t;//输入操作指令

		switch (t)
		{

		case 1://稀疏矩阵赋值
			cin >> matrix;
			break;
		case 2://稀疏矩阵乘法
			m.setMatrix();
			matrix.Multiply(m);
			cout << matrix<<endl;
			cout << "----------------------------------------" << endl;
			break;
		case 3://稀疏矩阵加法
			m.setMatrix();
			matrix.Add(m);
			cout << matrix << endl;
			cout << "----------------------------------------" << endl;
			break;
		case 4://按照正常矩阵的格式输出稀疏矩阵
			cout << matrix;
			break;
		case 5://稀疏矩阵转置
			matrix.Transpose();
			cout << matrix << endl;
			cout << "----------------------------------------" << endl;
			break;
		}

	}
}



  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值