当我们在储存稀疏矩阵时(很少有效数据,大部分为0的矩阵),如果我们用二维数组去储存的话,就会浪费很多存储空间,所以我们就用三元组类来储存。
储存思想
只储存有效数据的行和列以及数据值(做成结构体)。
在类中用一个一维数组储存这个结构体。
typedef struct
{
int col, row;
int item;
}Triple;
class TripleMatrix
{
private:
Triple data[MAX];
int mu, nu, num;
public:
TripleMatrix();
TripleMatrix(int m, int n);
~TripleMatrix();
void setItem(int row, int col, int item);
int getItem(int row, int col);
void printMatrix();
void printTriple();
friend bool matrixAdd(TripleMatrix a, TripleMatrix b, TripleMatrix& result);
friend bool matrixMulty(TripleMatrix a, TripleMatrix b, TripleMatrix& result);
};
TripleMatrix::TripleMatrix()
{
mu = 0;
nu = 0;
num = 0;
}
TripleMatrix::TripleMatrix(int m, int n)
{
mu = m;
nu = n;
num = 0;
}
TripleMatrix::~TripleMatrix()
{
}
void TripleMatrix::setItem(int row, int col, int item)
{
if (item == 0)
{
return;
}
Triple tri;
tri.row = row;
tri.col = col;
tri.item = item;
for (int i = 0; i < num; i++)
{
if (row == data[i].row && col == data[i].col)
{
data[i].item = item;
}
if (row < data[i].row || (col < data[i].col && row == data[i].row))
{
for (int j = num - 1; j >= i; j--)
{
data[j + 1] = data[j];
}
data[i] = tri;
num++;
return;
}
}
data[num] = tri;
num++;
}
int TripleMatrix::getItem(int row, int col)
{
for (int i = 0; i < num; i++)
{
if (row == data[i].row && col == data[i].col)
{
return data[i].item;
}
}
return 0;
}
void TripleMatrix::printMatrix()
{
//cout << "Print sparse matrix." << endl;
int t = 0;
for (int i = 0; i < mu; i++)
{
for (int j = 0; j < nu; j++)
{
if (i == data[t].row && j == data[t].col)
{
cout << data[t].item << ' ';
t++;
}
else
cout << 0 << ' ';
}
cout << endl;
}
cout << "line=" << mu << ",column=" << nu << ",nonzero number=" << num;
}
void TripleMatrix::printTriple()
{
cout << "Print triple array." << endl;
cout << "row col item" << endl;
for (int i = 0; i < num; i++)
{
cout << data[i].row + 1 << ' ' << data[i].col + 1 << ' ' << data[i].item << endl;
}
}
bool matrixAdd(TripleMatrix a, TripleMatrix b, TripleMatrix& result)
{
int i = 0;
int j = 0;
if (a.mu != b.mu || a.mu != result.mu || a.nu != b.nu || a.nu != result.nu)
return false;
else
{
while (i < a.num && j < b.num)
{
if (a.data[i].row < b.data[j].row || a.data[i].row == b.data[j].row && a.data[i].col < b.data[j].col)
{
result.setItem(a.data[i].row, a.data[i].col, a.data[i].item);
i++;
}
else if (a.data[i].row == b.data[j].row && a.data[i].col == b.data[j].col)
{
result.setItem(a.data[i].row, a.data[i].col, a.data[i].item + b.data[j].item);
i++;
j++;
}
else
{
result.setItem(b.data[j].row, b.data[j].col, b.data[j].item);
j++;
}
}
while (i < a.num)
{
result.setItem(a.data[i].row, a.data[i].col, a.data[i].item);
i++;
}
while (j < b.num)
{
result.setItem(b.data[j].row, b.data[j].col, b.data[j].item);
j++;
}
}
return true;
}
bool matrixMulty(TripleMatrix a, TripleMatrix b, TripleMatrix& result)
{
int sum = 0;
if (a.nu != b.mu || result.mu != a.mu || result.nu != b.nu)
return false;
else
{
for (int i = 0; i < a.mu; i++)
{
for (int j = 0; j < b.nu; j++)
{
sum = 0;
for (int k = 0; k < a.nu; k++)
sum += a.getItem(i, k) * b.getItem(k, j);
result.setItem(i, j, sum);
}
}
}
return true;
}
部分函数的思路
插入函数
我们这个三元组的储存是有顺序的,行号小的在前面,行号相同列号小的在前面。
所以我们在插入一个新元素时让它和前面的一一比较行号直到它的行号比一个元素的行号小了,说明新元素比前面的元素都大但比现在比较的元素小,那么这里就是新元素该插入的地方
注意:不仅要比较行号还要比较列号,且插入的位置有元素时只需要替换元素的值,元素数不增加。
void TripleMatrix::setItem(int row, int col, int item)
{
if (item == 0)
{
return;
}
Triple tri;
tri.row = row;
tri.col = col;
tri.item = item;
for (int i = 0; i < num; i++)
{
if (row == data[i].row && col == data[i].col)
{
data[i].item = item;
}
if (row < data[i].row || (col < data[i].col && row == data[i].row))
{
for (int j = num - 1; j >= i; j--)
{
data[j + 1] = data[j];
}
data[i] = tri;
num++;
return;
}
}
data[num] = tri;
num++;
}
三元组的加法
这个声名的时候函数名前加了一个 friend 意思是友元函数,但其实这个函数是类外面的函数,在类中声名成友元函数就可以访问到类中的私有属性。
先比较三个三元组的行号,列号相不相同,必须三个都相同才能相加。
相加时需要比较两个对象当前的元素行列号,小的先插入,相同则相加插入。
最后再把没插入的元素插入。
bool matrixAdd(TripleMatrix a, TripleMatrix b, TripleMatrix& result)
{
int i = 0;
int j = 0;
if (a.mu != b.mu || a.mu != result.mu || a.nu != b.nu || a.nu != result.nu)
return false;
else
{
while (i < a.num && j < b.num)
{
if (a.data[i].row < b.data[j].row || a.data[i].row == b.data[j].row && a.data[i].col < b.data[j].col)
{
result.setItem(a.data[i].row, a.data[i].col, a.data[i].item);
i++;
}
else if (a.data[i].row == b.data[j].row && a.data[i].col == b.data[j].col)
{
result.setItem(a.data[i].row, a.data[i].col, a.data[i].item + b.data[j].item);
i++;
j++;
}
else
{
result.setItem(b.data[j].row, b.data[j].col, b.data[j].item);
j++;
}
}
while (i < a.num)
{
result.setItem(a.data[i].row, a.data[i].col, a.data[i].item);
i++;
}
while (j < b.num)
{
result.setItem(b.data[j].row, b.data[j].col, b.data[j].item);
j++;
}
}
return true;
}
三元组的乘法
我们先来了解一下矩阵乘法的规则
矩阵c的m行k列的元素等于矩阵a的m行每个元素分别和矩阵b的k列每个元素相乘再相加。
比如
矩阵a 矩阵b 矩阵c
1 2 3 4 0 32 0
0 0 0 + 5 0 = 0 0
0 0 0 6 0 0 0
0 0 0 0 0
所以必需保证矩阵a的列数等于矩阵b的行数,才能相加。
bool matrixMulty(TripleMatrix a, TripleMatrix b, TripleMatrix& result)
{
int sum = 0;
if (a.nu != b.mu || result.mu != a.mu || result.nu != b.nu)
return false;
else
{
for (int i = 0; i < a.mu; i++)
{
for (int j = 0; j < b.nu; j++)
{
sum = 0;
for (int k = 0; k < a.nu; k++)
sum += a.getItem(i, k) * b.getItem(k, j);
result.setItem(i, j, sum);
}
}
}
return true;
}