展平n维向量

时间:2017-03-19 14:26:06

标签: c++ templates vector

我制定了一个可以递归使用的算法,它以非递归方式工作,但是,我不能以递归形式测试它,因为我无法从模板中创建一个n-1维变量。
为了帮助我写下变量名称及其含义:

  • v:n维向量
  • dims:n具有每个维度的长向量(例如:如果它是一个类似int x[3][6][4]的数组,那么dims看起来像:{3,6,4})
  • p:尺寸的乘积,用于得到平面矢量的大小(例如:3 * 6 * 4)
  • ret:返回的平面向量
  • sub_dims:与没有第一个维度的dims execpt相同(例如:{6,4})
  • sub_p:与p相同,但没有第一个因素(例如:6 * 4)
  • sub_ret:n-1维向量的返回平面向量

代码:

template <typename T>
vector<int> dim_flat(vector<T> v, vector<int> dims)
{
    // creating variables and vectors
    int n = dims.size();
    int p = dims[0];
    for (int i = 1; i < n; i++)
    {
        p *= dims[i];
    }
    int sub_p = p / dims[0];
    vector<int> sub_dims;
    sub_dims.assign(dims.begin() + 1, dims.end());
    vector<int> ret(p);

    // algorithm
    if (n > 1)
    {
        for (int i = 0; i < dims[0]; i++)
        {
            vector<int> sub_ret = dim_flat(v[i], sub_dims);

            for (int j = 0; j < sub_p; j++)
            {
                ret[i * sub_p + j] = sub_ret[j];
            }
        }
    }
    else
    {
        // case for the input is 1D 
        // not yet written
    }

    return ret;
}

使用此代码构建项目,但是如果我在main中调用它:

vector<int> ret = dim_flat(v, dims);

其中v例如是4D向量和dims是包含{3,3,3,3}的向量,然后在尝试构建时得到以下内容:

error C2784: 'std::vector<_Ty> dim_flat(std::vector<T>,std::vector<_Ty>)' : could not deduce template argument for 'std::vector<T>' from 'int'

为行

vector<int> sub_ret = dim_flat(v[i], sub_dims);

我有点(但不是真的)理解这个错误的意思,所以我期望同样的事情发生,它为此做了:

T x = v[i];
vector<int> sub_ret = dim_flat(x, sub_dims);

这是我不再理解错误的部分,因为我认为使用参数vector<T> v我指定了输入,例如4D向量将被理解为T的向量,其中T是3D向量,由于其vector<T>,因此也可以被索引。所以遵循这个逻辑,我认为如果我给递归第一个T是一个3D向量,那么这个3D向量的深度现在将被理解为T'的向量,其中T'是2D矢量,依此类推。

显然,我的逻辑存在缺陷,或者我使用了错误的方法(或两者兼而有之),所以问题是:我该如何解决/解决这个问题?

编辑:
对于解决方案,请归功于Max66 代码可能可以更优化,但至少现在它可以工作 代码:

//// for integer only
// case input is 0-dimensional (simply a variable)
template <typename T>
vector<int> dim_flat (const T &v, const vector<int> &dims)
{
    return vector<int>(1, v);
}

// case input is n-dimensional
template <typename T>
vector<int> dim_flat(const vector<T> &v, const vector<int> &dims)
{
    // creating variables and vectors
    int n = dims.size();
    int p = dims[0];
    for (int i = 1; i < n; i++)
    {
        p *= dims[i];
    }
    int sub_p = p / dims[0];
    vector<int> sub_dims;
    sub_dims.assign(dims.begin() + 1, dims.end());
    vector<int> ret(p);

    // algorithm
    if (n > 1) // case n-dimensional
    {
        for (int i = 0; i < dims[0]; i++)
        {
            vector<int> sub_ret = dim_flat(v[i], sub_dims);
            for (int j = 0; j < sub_p; j++)
            {
                ret[i * sub_p + j] = sub_ret[j];
            }
        }
    }
    else // case 1-dimensional
    {
        for (int i = 0; i < p; i++)
        {
            vector<int> sub_ret = dim_flat(v[i], sub_dims);
            ret[i] = sub_ret[0];
        }
    }
    return ret;
}

1 个答案:

答案 0 :(得分:0)

简答:添加功能

std::vector<int> dim_flat (int v, std::vector<int> const &)
 { return {v}; }

如果您可以使用C ++ 11或更高版本,或

std::vector<int> dim_flat (int v, std::vector<int> const &)
 { return std::vector<int>(1, v); }

如果你必须使用C ++ 98

答案很长:如果我没错,问题在于,当您使用dim_flat()致电std::vector<int>时(Tint时),您有n == 1,因此dim_flat()未被调用(执行“输入1D的情况”)但是编译器不是那么聪明,没有必要要使用dim_flat()(而不是int)致电std::vector<T>,请查找dim_flat(int, std::vector<int>)但找不到。

因此,为了使编译器满意,您必须实现dim_flat(int, std::vector<int>)

可以是虚函数(返回空向量),但我建议你正确实现它。

一些话题:请避免使用无用的载体副本;在dim_flat()中,vdims仅被加入,未被修改;所以你可以接收它们作为const引用,如下所示

template <typename T>
std::vector<int> dim_flat(std::vector<T> const   &  v,
                          std::vector<int> const &  dims)

P.s。:为什么不简单地写如下?

std::vector<int> dim_flat (std::vector<int> const & v)
 { return v; }

template <typename T>
std::vector<int> dim_flat(std::vector<std::vector<T>> const & v)
 {
   std::vector<int>  ret;

   for ( auto const & e : v )
    {
      auto s = dim_flat(e);

      ret.reserve( ret.size() + s.size() );
      ret.insert( ret.end(), s.cbegin(), s.cend() );
    }

   return ret;
 }