[C++]vector.erase()와 unique(vector.begin(),vector.end())함수

jh Seo·2023년 6월 12일
0

C++공부

목록 보기
18/21

개요

algorithm 헤더의 unique함수와 erase를 쓰던 중 막혀서
정리한 글이다.

vector.erase()

두 가지로 사용이 가능하다.

iterator erase (iterator position);
iterator erase (iterator first, iterator last);

첫번째 erase는 해당 position의 원소를 제거한다.

두번째 erase는 지울 범위를 parameter로 받는다.
주의할 점은 first iterator에 해당하는 원소는 지우지만,
last에 해당하는 원소는 지우지 않는다.

두 erase 다 마지막으로 제거한 원소 다음 원소의 iterator을 반환한다.
따라서 두 번째 erase같은 경우는 두번째 parameter의 iterator을 반환한다.

erase에서 주의할 점

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실행을 안 해줘야 한다.

unique()

  1. <algorithm>헤더에 존재하는 함수로 벡터에 적용할 수 있다.

  2. 첫 parameter로 벡터의 begin()을 넣고, 두번째로 벡터의 end()를 넣어주면
    ==연산자를 사용하여 원소들이 같은지 비교한다.

  3. 기본적인 원리는 first, result포인터 두 개를 이용하며,
    first가 가리키는 값과 result가 가리키는 값이 다르다면
    result를 한 칸 옮기고 거기에 *first 값을 덮어 씌우는 방식으로 작동한다.

  4. 결과적으론 연속된 위치의 중복값만 제거되고, 다른 원소에 의해
    분리된다면 중복값이라 하더라도 남아있다.
    또한 앞에서 뒤로 포인터가 진행하므로 중복값들의 첫 번째 원소들의 순서는 보장된다.

  5. 함수의 반환 값은 중복제거를 한 후, 나머지 쓰레기 값들의 첫번째 원소의
    iterator이다.

  6. 따라서 위의 erase함수와 조합해서

    v.erase(unique(v.begin(),v.end()),v.end());

    이런식으로 나머지 쓰레기값들을 한번에 제거가 가능하다.

unique()함수의 주의할 점

  1. 위 설명에서 적은 것처럼 unique()함수는 연속된 원소만 중복으로 판단한다.
    따라서 {1,2,2,1} 이런 배열이 있다고하자.
    unique 사용시 {1,2,1}
    이렇게 연속된 원소인 2만 제거된다.

  2. 위 설명처럼 자동으로 중복된 값들이 제거가 되는게 아니다.
    중복값들중 첫번째값만 벡터의 앞에 순서대로 채운 후, 나머지 부분은 first포인터가 가리키는 값으로 덮는다.
    따라서 벡터의 size는 그대로다.

profile
코딩 창고!

0개의 댓글