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

jh Seo·2023년 6월 12일
0

C++공부

목록 보기
18/23

개요

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개의 댓글

관련 채용 정보