csr矩阵是比三元组效率还要高的矩阵存储方式,但实际上我用vector库并不能很好的体现出这一点。在python中,csr矩阵经常作为基本单元运算。
具体csr矩阵的情况参见以下代码。
ps:没事少整花活……
/*
<1> 设计算法实现稀疏矩阵的运算应用。
要求:1)设计稀疏矩阵类;2)给出测试用例,实现n组稀疏矩阵的相加与相乘。
CSR最优存储。
*/
#include
#include
#include
using namespace std;
class sparse_martix {
private:
vector<int> Offset;//偏移量数列
vector<int> Cloum;//列位置数列
vector<int> Element;//元素数列
int r;//行数
int c;//列数
protected:
void _creat_mar(string str) { //读取文件中稀疏矩阵到在线状态
char a = ' ';
char a1 = ' ';
int f = 0;
int j = 0;
int i = 0;
int e = 0;
c = 0;
ifstream infile;//以字符状态读取,获取行数,0元所在等信息
ifstream infile2;//以整数状态读取,获取非零元的值
infile.open(str);
infile2.open(str);
if (!infile.is_open()) {
cout << "Error in Open infile!" << endl;
exit(1);
}
else if (!infile2.is_open()) {
cout << "Error in Open infile2!" << endl;
exit(1);
}
else {
cout << "Begin read files!" << endl;
}
Offset.push_back(f);//首行偏移量
while (!infile.eof()) {
infile >> noskipws >> a;//不跳过不可见字符
if (a == ' ') {//遇到空格,说明是当前已经读完,开始进入下一个字符
j++;
}
if (a != '\n' && a != ' ') {
if (a1 == '\n' || a1 == ' ')
if (a != '0') {
Cloum.push_back(j);
f++;
}
}
a1 = a;
if (a == '\n') {//换行,到下一行。
Offset.push_back(f);
if (j > c) {
c = j;
}
j = 0;
i++;
}
}
r = i - 1;
while (!infile2.eof()) {
infile2 >> e;
if (e != 0) {
Element.push_back(e);
}
}
infile.close();
infile2.close();
cout << "Over!" << endl;
return;
}
void show_mar() {
bool flag = false;
int f = 0;//控制偏移量数组的
vector<int>::iterator it = this->Offset.begin();
vector<int>::iterator ite = it + 1;
while (ite != this->Offset.end() - 1) {
if (*it != *ite) {
for (int i1 = 0; i1 <= this->c; i1++) {//本次输出c+1个数。
flag = false;
for (int i = *it; i < *ite; i++) {
if (i1 == Cloum[i]) {//如果有里面的数
cout << Element[i] << ' '; //输
flag = true;
if (i1 == this->c) {
cout << endl;
}
}
}
if (flag == false) {
cout << 0 << ' ';
if (i1 == c) {
cout << endl;
}
}
}
}
else {
for (int i = 0; i <= c; i++) {
cout << 0 << ' ';
}
cout << endl;
}
it = ite;
ite++;
}
return;
}
public:
sparse_martix(string str) {//文件读入。
_creat_mar(str);
}
sparse_martix(int r, int c) {//创建R*C的空矩阵。
this->r = r;
this->c = c - 1;
for (int i = 0; i <= r + 1; i++) {
Offset.push_back(0);
}
}
sparse_martix() {//什么都没有,建立{}矩阵。
r = 0;
c = 0;
Offset.push_back(0);
Cloum.push_back(0);
Element.push_back(0);
}
sparse_martix(vector<vector<int>> a) {//二维容器建立。
int f = 0;//偏离值
int j = 0;//计数当前元素的列位置。
int i = 0;
c = 0;
vector<vector<int>>::iterator iter = a.begin();
vector<int>::iterator it = (*iter).begin();
Offset.push_back(f);
for (; iter != a.end(); iter++) {
if (j > c)
c = j - 1;
j = 0;//新的一行,从0开始。
i++;
for (it = (*iter).begin(); it != (*iter).end(); it++) {
if (*it != 0) {
Element.push_back(*it);
Cloum.push_back(j);
f++;
}
j++;//向下一个元素号挪动。
}
Offset.push_back(f);//存上本行偏离值。
}
r = i;
}
sparse_martix(sparse_martix& a) {//拷贝构造函数
this->r = a.r;
this->c = a.c;
copy(a.Cloum.begin(), a.Cloum.end(), this->Cloum.begin());
copy(a.Element.begin(), a.Element.end(), this->Element.begin());
copy(a.Offset.begin(), a.Offset.end(), this->Offset.begin());
return;
}
void show() {
show_mar();
return;
}
void midf() {
vector<int>::iterator it = this->Cloum.begin();
for (; it != Cloum.end(); it++) {
cout << *it << " ";
}
cout << endl << c << " " << r << endl;
}
void plus(sparse_martix &a) {
if (r != a.r || c != a.c) {
cout << "不同型无法相加!" << endl;
return ;
}
a.show();
cout << '+' << endl;
this->show();
cout << "结果是:" << endl;
sparse_martix s(r, c + 1);
int cs = 1;
vector<int>::iterator it = this->Offset.begin();
vector<int>::iterator ite = it + 1;
vector<int>::iterator its = a.Offset.begin();
vector<int>::iterator ites = its + 1;
while (ite != this->Offset.end() - 1 && ites != a.Offset.end() - 1) {
if (*it != *ite && *its != *ites) {
if (*it == *ite) {
s.Offset[cs] = s.Offset[cs - 1] + (*ites - *its);
for (int i1 = *its; i1 < *ites - *its; i1++) { //本次处理被加矩阵非零数。
s.Element.push_back(a.Element[i1]);
s.Cloum.push_back(a.Cloum[i1]);
}
cs++;
}
else if (*its == *ites) {
s.Offset[cs] = s.Offset[cs - 1] + (*ite - *it);
for (int i1 = *it; i1 < *ite - *it; i1++) { //本次处理被加矩阵非零数。
s.Element.push_back(this->Element[i1]);
s.Cloum.push_back(this->Cloum[i1]);
}
cs++;
}
else {
s.Offset[cs] = s.Offset[cs - 1] + max(*ites - *its, *ite - *it);
int i2 = 0;
int i3 = 0;
for (int i1 = 0; i1 <= c; i1++) { //本次处理c+1个数。
if (*ite - *it > i2 && i1 == this->Cloum[*it + i2]) {
s.Cloum.push_back(this->Cloum[*it + i2]);
if (*ites - *its > i3 && this->Cloum[*it + i2] == a.Cloum[*its + i3]) {
s.Element.push_back(this->Element[*it + i2] + a.Element[*its + i3]);
i3++;
i2++;
}
else {
s.Element.push_back(this->Element[*it + i2]);
i2++;
}
}
else if (*ites - *its > i3 && i1 == a.Cloum[*its + i3]) {
s.Element.push_back(a.Element[*its + i3]);
i3++;
}
}
cs++;
}
}
else {
s.Offset[cs] = s.Offset[cs - 1];
cs++;
}
if (ite != this->Offset.end() - 1 && ites != a.Offset.end() - 1) {
it = ite;
ite++;
its = ites;
ites++;
}
}
s.show();
return ;
}
void multy(sparse_martix& a) {
if (this-> c + 1 != a.r ){
cout << "不可乘!" << endl;
return ;
}
sparse_martix s(r, a.c + 1);
if (a.Element.empty()) {
s.show();
return;
}
if (this->Element.empty()) {
s.show();
return;
}
int cs = 1;
//for (vector::iterator it = a.Offset.begin(); it != a.Offset.end(); it++) {
// cout << *it << endl;
//}
vector<int>::iterator it = this->Offset.begin();
vector<int>::iterator ite = it + 1;
while (ite != this->Offset.end() - 1){//3行
if (*it == *ite) {//有全零行。
s.Offset[cs] = s.Offset[cs - 1];
}
else {
int n3 = 0;//确定此行算完需要偏移的量。
for (int j = 0; j <= a.c; j++) {//3列,j代表a的列数。确定结果矩阵的列数。
int n1 = 0;//第n1个元素,用来运算得到n2的变量,同时也是得到a中ele索引的变量
int n2 = 1;//第n2行,确定this矩阵的对应列数的变量
int x = 0;//this元素
int y = 0;//a元素
int sum = 0;//s的最终元素
vector<int>::iterator itr = a.Offset.begin();
for (vector<int>::iterator its = a.Cloum.begin(); its != a.Cloum.end(); its++, n1++) {
if (*its == j) {//如果找到本列非零元。
y = a.Element[n1];
n2 = 0;
itr = a.Offset.begin();
while (*itr <= n1) {//确定行数
n2++;
itr++;
}
bool flag = false;
for (int i = *it; i < *ite; i++) {//找到对应this元素
if (this->Cloum[i] == n2 - 1) {
x = this->Element[i];
flag = true;
break;
}
}
if (flag) {//如果有对应元素。
sum += x * y;
flag = false;
}
}
}
if (sum != 0) {//如果该元素的确非零
s.Element.push_back(sum);
s.Cloum.push_back(j);
n3++;
}
}
s.Offset[cs] = s.Offset[cs - 1] + n3;
}
it = ite;
ite++;
cs++;
}
s.show();
return;
}
void operator=(sparse_martix a) {
this->r = a.r;
this->c = a.c;
copy(a.Cloum.begin(), a.Cloum.end(), this->Cloum.begin());
copy(a.Element.begin(), a.Element.end(), this->Element.begin());
copy(a.Offset.begin(), a.Offset.end(), this->Offset.begin());
return;
}
};
int main() {
string str, str1;
cout << "文件位置?" << endl;
cin >> str >> str1;
sparse_martix sm(str);
sparse_martix sm1(str1);
sm.multy(sm1);
return 0;
}
需要注意的是:我们当前的矩阵最主要的时间耗费浪费在对齐上。如果想要高效地计算,重要方向就是如何使矩阵对齐变得简洁起来。