操作:
重载赋值、输入、输出运算符;
稀疏矩阵加法、乘法、转置。
代码:
#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;
}
}
}