c ++如何将向量表示为矩阵并转置它?

时间:2016-04-20 15:26:00

标签: c++ performance matrix vector transpose

我有一个大小为n的向量; n是2的幂。我需要将此向量视为矩阵n = R * C。然后我需要转置矩阵。

例如,我有矢量:[1,2,3,4,5,6,7,8]

我需要找到R和C.在这种情况下,它将是:4,2。并将矢量视为矩阵:

[1,2]
[3,4]
[5,6]
[7,8]

将其转置为:

[1, 3, 5, 7]
[2, 4, 6, 8]

换位后,载体应为:[1, 3, 5, 7, 2, 4, 6, 8]

是否存在执行就地非方矩阵转置的算法?我不想重新发明轮子。

我的矢量非常大,所以我不想创建中间矩阵。我需要一个就地算法。表现非常重要。

  • 所有修改都应在oroginal vector中完成。理想情况下,算法应该适用于适合CPU缓存的块。
  • 由于内存局部性,我无法使用迭代器。所以我需要真正的换位。
  • 矩阵是2x4还是4x2
  • 无关紧要

3 个答案:

答案 0 :(得分:0)

由于您还未向我们提供任何代码,我是否可以建议采用不同的方法(我不知道哪种方法适用于您的特定情况)?

我会使用基于矩阵的算法自己将值转换为新矩阵。由于性能是一个问题,这将有助于更多,因为您不必创建另一个矩阵。如果这适用于您。

有一个载体

[1, 2, 3, 4, 5, 6, 7, 8]

创建矩阵

[1, 2]
[3, 4]
[5, 6]
[7, 8]

在没有其他矩阵的情况下重新排序矢量

[1, 3, 5, 7, 2, 4, 6, 8]

覆盖当前矩阵中的值(因此您不必创建新值)并根据当前矩阵重新排序值。

按顺序添加值

R1 and C1 to transposed_vector[0]
R2 and C1 to transposed_vector[1]
R3 and C1 to transposed_vector[2]
R4 and C1 to transposed_vector[3]
R1 and C2 to transposed_vector[4]

等等。

答案 1 :(得分:0)

问题可分为两部分。首先,找到RC,然后重新整形矩阵。以下是我要做的事情:

由于n2的强项,即n = 2^k,如果k是偶数,我们会:R=C=sqrt(n)。如果k为奇数,则为R = 2^((k+1)/2)C=2^((k-1)/2)

注意:由于您提到要避免使用额外的内存,我已经为原始答案制作了一些版本。

计算RC的代码如下:

void getRandC(const size_t& n, size_t& R, size_t& C)
{
    int k = (int)log2(double(n)),
        i, j;

    if (k & 1)  // k is odd
        i = (j = (k + 1) / 2) - 1;
    else
        i = j = k / 2;

    R = (size_t)exp2(i);
    C = (size_t)exp2(j);
}

哪个需要C ++ 11。对于第二部分,如果您想保留原始矢量:

void transposeVector(const std::vector<int>& vec, std::vector<int>& mat)
{
    size_t R, C;
    getRandC(vec.size(), R, C);

    // first, reserve the memory
    mat.resize(vec.size());

    // now, do the transposition directly
    for (size_t i = 0; i < R; i++)
    {
        for (size_t j = 0; j < C; j++)
        {
            mat[i * C + j] = vec[i + R * j];
        }
    }
}

而且,如果你想修改原始矢量并避免使用额外的内存,你可以写:

void transposeInPlace(std::vector<int>& vec)
{
    size_t R, C;
    getRandC(vec.size(), R, C);

    for (size_t j = 0; R > 1; j += C, R--)
    {
        for (size_t i = j + R, k = j + 1; i < vec.size(); i += R)
        {
            vec.insert(vec.begin() + k++, vec[i]);
            vec.erase(vec.begin() + i + 1);
        }
    }
}

请参阅the live example

答案 2 :(得分:0)

对于非方形矩阵表示,我认为它可能很棘手,并且不值得努力使平面向量转置而不创建另一个。这是我想出的一个片段:

chrono::steady_clock::time_point start = chrono::steady_clock::now();
int i, j, p, k;
vector<int> t_matrix(matrix.size());
for(k=0; k< R*C ;++k)
{
    i = k/C;
    j = k - i*C;
    p = j*R + i;
    t_matrix[p] = matrix[k];
}
cout << chrono::duration_cast<chrono::milliseconds> chrono::steady_clock::now() - start).count() << endl;

在这里,matrix是您的平面向量,t_matrix是&#34;转置&#34;平面向量,RC分别是您为矩阵表示找到的行和向量。