用与构造函数中矩阵的列相对应的索引填充矢量的最有效方法?

时间:2018-11-24 18:46:41

标签: c++ arrays performance vector std

我有一个动态的Matrix模板类,我希望创建一个矢量,并在其上填充列而不是行的索引。正如您可能从我刚才所说的那样猜测到的那样,我将行的主要形式的矩阵的实际数据存储在std::vector<T>中。这是我的Matrix类定义的简化版本,仅包含相关部分。

template<typename T>
class Matrix {
    public:
        Matrix(std::size_t m, std::size_t n, const T &elem = T());
        Matrix(const std::vector<T> &vec, std::size_t m, std::size_t n); 
        Matrix(std::initializer_list<T> list, std::size_t m, std::size_t n);

    private:
        typedef std::vector<std::size_t> reindex_scheme;

        std::vector<T> _data;
        reindex_scheme _colindices;
        std::size_t _m;
        std::size_t _n;

};

基本上,我想发生的就是给出以下这段代码:

std::vector<int> input {1, 2, 4, 6, 5, 4};
Matrix<int> A(input, 2, 3); // creates a 2x3 matrix with entries 1 2 4
                            //                                   6 5 4

将其按以下顺序存储在_colindices中:

0 3 1 4 2 5

((如果您了解我在做什么,如果您像这样遍历矩阵,我就是在抓取元素的索引:

 |   /|   /|
 | /  | /  |
\/   \/   \/

希望您能弄清楚箭头)

到目前为止,我为构造函数提供的是基于“ for”的“天真”方法:

template<typename T>
Matrix<T>::Matrix(std::size_t m, std::size_t n, const T &elem)
    : _data(m * n, elem),
      _colindices(m * n), 
      _m(m),
      _n(n) {
    for (std::size_t i = 0; i < _n; i++)
        for (std::size_t j = 0; j < _m; j++)
            _colindices[i * _m + j] = j * _n + i;
}

template<typename T>
Matrix<T>::Matrix(const std::vector<T> &vec, std::size_t m, std::size_t n)
    : _data(vec),
      _colindices(m * n), 
      _m(m),
      _n(n) {
    for (std::size_t i = 0; i < _n; i++)
        for (std::size_t j = 0; j < _m; j++)
            _colindices[i * _m + j] = j * _n + i;
}

template<typename T>
Matrix<T>::Matrix(std::initializer_list<T> list, std::size_t m, std::size_t n)
    : _data(list),
      _colindices(m * n), 
      _m(m),
      _n(n) {
    for (std::size_t i = 0; i < _n; i++)
        for (std::size_t j = 0; j < _m; j++)
            _colindices[i * _m + j] = j * _n + i;
}

此外,作为旁注,您可以看到我对三个构造函数所做的愚蠢代码重复。如果您知道将三合一或至少三合二的最佳方法,也请在这里告诉我。(对不起,这变成了双重问题)

for方法有效,但显然是O(mn),我想认为有更好,更有效的方法,也许可以使用某些std方法吗?我正在考虑使用0 3创建向量,然后对其进行迭代,通过将每个元素增加std::transform或类似的方式来组成一个新向量,并将其添加到最终向量的末尾直到我走到尽头(如果您明白我的意思)。有点像

Loop Iteration 1:
0 3
Loop Iteration 2:
0 3 1 4
Loop Iteration 3:
0 3 1 4 2 5

您有什么想法?

1 个答案:

答案 0 :(得分:0)

我首先想到的是您的程序已经完成很长时间了,而我的回答为时已晚。

但是,也许其他SO用户也想听听可能的解决方案。

读到您正在使用

  

std :: vector中以行为主的形式

建议使用std::valarray。使用std::slice(或其他类型的切片),您可以简单地对可以想象的所有索引进行操作。索引运算符[]与slice一起仅在需要时才计算inde。那是非常强大且快速的。

用于构建矩阵的标准C ++方法是使用类型为std::vector的{​​{1}}。然后访问该数据或对其进行操作。请注意:std::vector也使用连续内存。您可以不同地访问它。例如:行很容易访问。您可以只使用第一个维度。对于std::vector<std::vector<int>>,您只需编写std::vector<std::vector<int>> data;即可访问该行中的所有列。

使用列会更困难。我的猜测是您想以某种方式实现对列的访问。否则,将无需计算列索引或列顺序的索引。

这样做的缺点是您不能将矩阵与data[row]库一起使用。没有迭代器可用,嗯,很难。

我可以为您提供一个矩阵的解决方案,该矩阵具有行和列的迭代器。为此,我们使用了按列对algorithm中正确值的引用向量。然后,我们可以遍历行和列并使用std::vector<std::vector<int>> data;

为了优化速度,可以在需要时创建列引用。这样可以减少构造函数的复杂性。

对于您的副节点:在构造函数中重复的代码。请在您的类中创建一个私有函数,然后在构造函数中调用它。

请查看带有一些测试代码(MSVS19)的矩阵的骨架:

std::algorithm

希望这对如何工作提供了一个思路