2013-03-11 3 views
3

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 

답변

2

를 실행할 때이 출력을지고있어, 반복자는 std::rotate를 사용

c.insert(c.begin(), *it); // This invalidates 'it'  
    remove (it, c.end(), x); // oops! trying to use invalid iterator 

더 나은 대안을 제공합니다 더 이상 유효하지 않습니다 , 이터레이터를 무효화하지는 않습니다.

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; 
    } 
} 
,210

만큼 당신의 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

이, 당신은 당신의 코드에서 한 무슨의 고정 구현 :

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) ; 
     } 
} 
0

출력이 잘못되었습니다. for (auto i:v) cout << i;이 아닌 v[i]이어야합니다. 올바른 알고리즘을 가진 쓰레기도 볼 수 있습니다.

0

모든 일치를 처리하거나 카운트 및 삽입을 사용하려면 루프가 필요합니다. 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); 
    } 
} 
1

당신은 범위의 시작 부분에 주어진 조건을 충족 범위의 모든 요소를 ​​이동하는 표준 : 파티션을 사용하고, 아무튼 첫 번째 요소로 반복자를 반환 할 수 술어를 만난다.

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; }); 
} 

이 경우 반환 값은 사용하지 않지만 유용하다고 생각합니다.

+0

깔끔한 해결책, 두 가지 문제, 당신은'x'를 잡아 내지 못하고 결국';'을 잘못 놓았습니다. 그 두 가지를 고친 후에는 정상적으로 작동하는 것처럼 보입니다. –

+0

그 점을 지적 해 주셔서 감사합니다. 나는 이것을 컴파일러로 실행하려고 계획했지만 멀리 호출되었다. 지금 컴파일하는 것 같습니다. – Muscles

관련 문제