【问题标题】:Rotating a vector (array)旋转向量(数组)
【发布时间】:2012-07-05 11:10:41
【问题描述】:

我正在尝试在 C++ 中旋转元素向量。我的意思是我有一个vector<point> 我希望最后一个元素成为第一个。

例子:

[1,2,3] 变为 [3,1,2] 然后 [2,3,1]

为此,我尝试执行以下操作:

//Add the last element at index 0
ObjectToRotate.insert(0, ObjectToRotate.at(ObjectToRotate.size()-1));
//Remove Last element
ObjectToRotate.erase(ObjectToRotate.size()-1);

但我收到此错误:

错误 6 错误 C2664: 'std::_Vector_iterator<_myvec> std::vectorTy>::insert<:point><_tp>&>(std::_Vector_const_iterator<_myvec>,_Valty)' : 无法将参数 1 从 'int' 转换为 'std::_Vector_const_iterator<_myvec>'

我该如何解决?

【问题讨论】:

    标签: c++ vector


    【解决方案1】:

    标准库中有一个std::rotate algorithm

    std::rotate(ObjectToRotate.begin(),
                ObjectToRotate.end()-1, // this will be the new first element
                ObjectToRotate.end());
    

    【讨论】:

    • 或使用std::deque.rotate(1) 成员函数。
    • @CharlesBeattie: deque 没有rotate 成员函数。
    • 糟糕。我有一个有旋转的版本(std::deque 很慢)。
    【解决方案2】:

    使用std::rotate 的建议当然是完全正确的; 在以下情况下,使用现有函数始终是首选解决方案 可用的。无论如何,值得指出您的解决方案的原因 没用。标准库中的容器,如std::vector, 以迭代器的形式获取位置信息,而不是索引。这 编写操作的惯用方式是:

    v.insert( v.begin(), v.back() );
    v.erase( std::prev( v.end() ) );
    

    (如果您没有 C++11,编写自己的版本非常简单 的prev。或者在vector的情况下,你可以写v.end() - 1。)

    【讨论】:

      【解决方案3】:

      inserterase 的参数是迭代器,而不是索引:

      ObjectToRotate.insert(ObjectToRotate.begin(), ObjectToRotate.back());
      ObjectToRotate.pop_back();  // or erase(ObjectToRotate.end()-1), if you prefer
      

      但先删除最后一个元素(在获取副本之后)可能更有效,以避免重新分配的可能性:

      auto back = ObjectToRotate.back();
      ObjectToRotate.pop_back();
      ObjectToRotate.insert(ObjectToRotate.begin(), back);
      

      或使用std::rotate:

      std::rotate(ObjectToRotate.begin(), ObjectToRotate.end()-1, ObjectToRotate.end());
      

      如果您经常这样做,那么deque 可能是更好的容器选择,因为它允许在两端高效插入和移除。但是,如果速度很重要,请确保您测量并验证这确实是一种改进;如果序列不是很大,那么更复杂的内存布局带来的开销可能会使deque 变慢。

      【讨论】:

      • 回复deque,有人会这么认为,但不会。事实上,对于具有很少廉价可复制元素的容器,事实证明vector 仍然更快。 (使用vector&lt;char&gt;deque&lt;char&gt; 完成测量,大约有十个元素。)有点让我吃惊,但事实就是这样。
      • @JamesKanze:确实,我应该添加关于过早优化或不进行测量的常见免责声明。
      • 在这种情况下...我想说,鉴于使用情况,std::deque 应该是默认容器——您在两端插入或删除。事实上,这是我最初使用的。由于我的使用是在一个关键位置,我最终对它进行了分析,并尝试了其他解决方案。至少对我来说,结果有些令人惊讶。 deque 中的额外间接操作等最终会比复制几个 POD 花费更多。
      【解决方案4】:

      【讨论】:

        【解决方案5】:

        James Kanze 建议使用以下代码 sn-p 旋转单个元素的绝妙答案。要旋转 x 个项目,只需将以下代码放入循环中即可。

        vec.insert( vec.begin(), vec.back() );
        vec.erase( std::prev( vec.end() ) );
        

        但是,如果您可以使用标准旋转功能,那将是您的最佳选择。下面的代码再次旋转 x 个项目。

        std::rotate(vec.rbegin(), vec.rbegin() + x, vec.rend());
        

        【讨论】:

          【解决方案6】:

          为了使 [1,2,3] 到 [2,3,1] 这里是代码

          vector<int> Solution::rotateArray(vector<int> &A, int B) {
            vector<int> ret; 
            for (int i = 0; i < A.size(); i++) {
              ret.push_back(A[(i + B) % A.size()]);
            }
            return ret; 
          }
          

          这里A是[1,2,3],B是1移动1个位置

          【讨论】:

            猜你喜欢
            • 2016-07-18
            • 2012-06-11
            • 2015-12-27
            • 1970-01-01
            • 2014-10-17
            • 1970-01-01
            • 2013-03-30
            • 1970-01-01
            • 2012-08-18
            相关资源
            最近更新 更多