我正在尝试将具有x值的每个元素移动到向量的开头,以便具有x值的所有元素都位于向量的前面,但它不起作用,所以你能告诉我我的内容吗?做错了,拜托?
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
template <typename Container, typename Arg>
void move_x(Container& c, Arg x)
{
typename Container::iterator it = find(c.begin(), c.end(), x);
if (it!=c.end()) {
c.insert(c.begin(), *it);
remove (it, c.end(), x);
}
}
int main()
{
int x=1;
vector <int> v{1,2,4,6,7,1,3,1,1,8,9};
move_x(v, x);
for(auto i:v)
cout<<v[i];
return 0;
}
当我运行它时我得到了这个输出
411613848811
答案 0 :(得分:2)
插入容器后,迭代器不再有效
c.insert(c.begin(), *it); // This invalidates 'it'
remove (it, c.end(), x); // oops! trying to use invalid iterator
使用std::rotate
提供了更好的替代方法,它不会使迭代器失效:
template <typename Container, typename Arg>
void move_x(Container& c, Arg x)
{
typedef typename Container::iterator It;
It write_it = c.begin(), read_it = c.begin();
for (;;) {
It found_it = find(read_it, c.end(), x);
if (found_it==c.end()) break;
read_it = found_it;
++read_it;
std::rotate(write_it,found_it,read_it);
++write_it;
}
}
只要你处理像int这样的简单项目,这是一个很好的方法:
template <typename Container, typename Arg>
void move_x(Container& c, Arg x)
{
typename Container::reverse_iterator it = std::remove(c.rbegin(),c.rend(),x);
for (;it!=c.rend();++it) {
*it = x;
}
}
答案 1 :(得分:1)
这是一个固定的实现,代码中包含的内容:
template <typename Container, typename Arg>
void move_x(Container& c, Arg x)
{
typename Container::iterator it = find(c.begin(), c.end(), x);
if (it!=c.end()) {
c.erase(it);
c.insert(c.end(), x);
}
}
您的实施的一个问题是,insert
任何位置but the end都可能导致重新分配,并且无论在插入位置后是否会使任何内容无效。因此,根据定义,因为您在开始时插入it
将无效。
第二个问题是cout<<v[i];
它应该是cout<<i;
。
使用反向迭代器并移动所有x
的更好的实现。这个删除它并保持count
,然后在完成时count
插入。使用erase with reverse iterators有点棘手:
template <typename Container, typename Arg>
void move_all_x(Container& c, Arg x)
{
unsigned int count = 0 ;
for( typename Container::reverse_iterator it = c.rbegin() ; it != c.rend(); )
{
if( *it == x )
{
c.erase(--(it++).base() ) ;
++count ;
}
else
{
++it ;
}
}
for( unsigned int i = 0; i < count; ++i )
{
c.insert(c.begin(), x) ;
}
}
答案 2 :(得分:1)
您可以使用std :: partition,它会将符合给定谓词的范围内的所有元素移动到范围的开头,并将迭代器返回到不符合谓词的第一个元素。
template <typename Container, typename Arg>
void move_x(Container& c, Arg x)
{
typename Container::iterator endrange =
std::partition(c.begin(), c.end(), [&x](Arg ele){ return ele == x; });
}
在这种情况下,我们没有使用返回值,但我认为它可能会有用。
答案 3 :(得分:0)
输出错误。应该for (auto i:v) cout << i;
而不是v[i]
。您也会看到使用正确算法的垃圾
答案 4 :(得分:0)
您需要一个循环来处理所有匹配(或使用count和insert)。 v
定义为list<int>
:
template <typename Container, typename Arg>
void move_x(Container& c, Arg x)
{
for (auto it = find(c.begin(), c.end(), x);
it != c.end();
it = find(it, c.end(), x)) {
c.insert(c.begin(), x);
it = c.erase(it);
}
}