如果我只在 list<list<pair<int,double>>> 中存储非零元素,如何将两个矩阵相乘?

问题描述

所以我得到了我的数据结构和算法项目。我基本上需要开发一个具有以下属性的类 Matrix:

  1. list>>,(其中只有矩阵的非零元素。某个元素的值存储为pair的第二个参数,a的第一个参数pair 表示该元素位于原始矩阵中的实际列)
  2. vector rows,(rows[i] - 分别代表上述列表列表中每个列表的实际行)
  3. 实际行数,
  4. 实际列数。

到目前为止,在我的项目中,我已经开发了特定的构造函数、矩阵相加和相减等。我唯一不能做的是将类 Matrix 的两个实例相乘,这意味着我无法为类矩阵。

问题说明:

假设我有以下两个 Matrix 类实例

实例 A:

        list<list<pair<int,double>>>: {{{10,5},{40,15}},{{50,25}},{{80,35}}}
        vector<int>: {2,10,70};
        actual number of rows: 100
        actual number of columns: 100

实例 B:

        list<list<pair<int,double>>>: {{{1,6},{2,{3,7}},{{3,4}},1}}}
        vector<int>: {1,2,33};
        actual number of rows: 100
        actual number of columns: 100

显然,乘法是为这些矩阵定义的,因为矩阵 A 的列数等于矩阵 B 的行数。 我无法找到正确的算法来乘以这些矩阵。 有人可以用短线写出什么是乘以这些的算法之一。

解决方法

主要思想在于使用方便的原语来设置/获取矩阵位置 (i,j) 处的值、行数和列数。

为了简单起见,我在以下代码中将您的顶级列表替换为一个向量(因为您可以随机访问第 i 个值,所以效率更高):

#include <cassert>
#include <iostream>
#include <list>
#include <vector>

using namespace std;

class Matrix {
    private:
        vector<list<pair<unsigned,double>>> data;
        unsigned m;
        unsigned n;
    public:
        Matrix(unsigned m,unsigned n):
            m(m),n(n),data(m)
        {}
        inline unsigned num_rows() const {
            return m;
        }
        inline unsigned num_columns() const {
            return n;
        }
        double get(unsigned i,unsigned j) const {
            for (pair<unsigned,double> p : data[i]) {
                if (p.first == j) return p.second;
            }
            return 0.0;
        }
        void set(unsigned i,unsigned j,double v) {
            for (pair<unsigned,double> p : data[i]) {
                if (p.first == j) {
                    p.second = v;
                    return;
                }
            }
            if (v) {
                data[i].push_back(make_pair(j,v));
            }
        }
};

Matrix operator * (const Matrix & a,const Matrix & b) {
    unsigned m = a.num_rows(),n = b.num_columns(),k_max = a.num_columns();
    assert (a.num_columns() == b.num_rows());
    Matrix c(m,n);
    for (unsigned i = 0; i < m; i++) {
        for (unsigned j = 0; j < n; j++) {
            double value = 0;
            for (unsigned k = 0; k < k_max; k++) {
                value += a.get(i,k) * b.get(k,j);
            }
            if (value) c.set(i,j,value);
        }
    }
    return c;
}

ostream & operator << (ostream & out,const Matrix & a) {
    for (unsigned i = 0; i < a.num_rows(); i++) {
        for (unsigned j = 0; j < a.num_columns(); j++) {
            out << a.get(i,j) << "\t";
        }
        out << endl;
    }
    return out;
}

int main() {
    Matrix a(2,3),b(3,1);

    for (unsigned i = 0; i < a.num_rows(); i++) {
        for (unsigned j = 0; j < a.num_columns(); j++) {
            a.set(i,10 * i + j);
        }
    }

    for (unsigned i = 0; i < b.num_rows(); i++) {
        for (unsigned j = 0; j < b.num_columns(); j++) {
            b.set(i,10 * (i + 1));
        }
    }
    Matrix c = a * b;
    cout << "a:" << endl << a << endl
         << "b:" << endl << b << endl
         << "c:" << endl << c << endl
         ;
    return 0;
}

结果:

a:
0       1       2
10      11      12

b:
10
20
30

c:
80
680