algorithm 헤더의 unique함수와 erase를 쓰던 중 막혀서
정리한 글이다.
두 가지로 사용이 가능하다.
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
첫번째 erase는 해당 position의 원소를 제거한다.
두번째 erase는 지울 범위를 parameter로 받는다.
주의할 점은 first iterator에 해당하는 원소는 지우지만,
last에 해당하는 원소는 지우지 않는다.
두 erase 다 마지막으로 제거한 원소 다음 원소의 iterator을 반환한다.
따라서 두 번째 erase같은 경우는 두번째 parameter의 iterator을 반환한다.
erase함수는 지운 원소의 다음 원소 iterator을 반환하기 때문에,
for문을 통해 iterator을 순회할때 조심해야한다.
for (auto iter = a.begin(); iter != a.end(); ++iter) {
iter = a.erase(iter);
}
이런식으로 a의 모든 원소 제거를 for문 순회하며 실행한다고 해보자.
각 반복종료시 ++iter를 실행하면서 동시에 for문 내에서 erase를 같이 하게되면
iterator가 erase하면서 한번 증가하고, ++iter하면서 한 번더 증가한다.
따라서
vector<int> a = { 1,2,3,4,5 };
for (auto iter = a.begin(); iter != a.end(); ) {
iter = a.erase(iter);
}
이런식으로 erase만 써야 의도대로 동작한다.
조건을 만족할때만 삭제한다고 하면
for (auto iter = a.begin(); iter != a.end(); ) {
if(condition)
iter = a.erase(iter);
else
++iter
}
위 코드처럼 조건을 만족할때는 ++iter실행을 안 해줘야 한다.
<algorithm>헤더에 존재하는 함수로 벡터에 적용할 수 있다.
첫 parameter로 벡터의 begin()을 넣고, 두번째로 벡터의 end()를 넣어주면
==연산자를 사용하여 원소들이 같은지 비교한다.
기본적인 원리는 first, result포인터 두 개를 이용하며,
first가 가리키는 값과 result가 가리키는 값이 다르다면
result를 한 칸 옮기고 거기에 *first 값을 덮어 씌우는 방식으로 작동한다.
결과적으론 연속된 위치의 중복값만 제거되고, 다른 원소에 의해
분리된다면 중복값이라 하더라도 남아있다.
또한 앞에서 뒤로 포인터가 진행하므로 중복값들의 첫 번째 원소들의 순서는 보장된다.
함수의 반환 값은 중복제거를 한 후, 나머지 쓰레기 값들의 첫번째 원소의
iterator이다.
따라서 위의 erase함수와 조합해서
v.erase(unique(v.begin(),v.end()),v.end());
이런식으로 나머지 쓰레기값들을 한번에 제거가 가능하다.
위 설명에서 적은 것처럼 unique()함수는 연속된 원소만 중복으로 판단한다.
따라서 {1,2,2,1} 이런 배열이 있다고하자.
unique 사용시 {1,2,1}
이렇게 연속된 원소인 2만 제거된다.
위 설명처럼 자동으로 중복된 값들이 제거가 되는게 아니다.
중복값들중 첫번째값만 벡터의 앞에 순서대로 채운 후, 나머지 부분은 first포인터가 가리키는 값으로 덮는다.
따라서 벡터의 size는 그대로다.