unique함수는
https://velog.io/@whipbaek/c-unique-%ED%95%A8%EC%88%98%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC
의 블로그를 참고하여 작성하였습니다.
unique(구간의 시작값, 구간의 마지막값) ;
-범위내에 인접하는(연속적인) 중복 요소들을 제거해준다.
-정렬 후에 배열의 사이즈가 바뀌지 않음
-배열의 사이즈가 바뀌지 않고 중복요소인 원소들은 뒤로 밀려난다.
-반환값은 중복없이 나열된 마지막 원소 다음의 반복자를 반환한다.
- <algorithm> 헤더를 사용한다.
unique함수 하나로는 vector 중복 원소 제거를 하는것은 어렵다.sort()함수를 사용하여 정렬 한 뒤 erase()함수를 활용하여 쓰레기값을 제거해줘야한다.
#include<iostream>
#include<vector>
#include<algorithm>
void main()
{
std::vector<int> v1 = { 10,10,20,30,20,10 };
std::vector<int>::iterator iter = unique(v1.begin(), v1.end());
for (int index : v1)
{
std::cout << index << " ";
}
std::cout << " 반환값 : " << *iter << " " << &iter << std::endl;
//======================================================
std::vector<int> v2 = { 10,10,20,30,20,10 };
sort(v2.begin(), v2.end()); // 10,10,10,20,20,30
iter = unique(v2.begin(), v2.end());
for (int index : v2)
{
std::cout << index << " ";
}
std::cout << " 반환값 : " << *iter << " " << &iter << std::endl;
v2.erase(iter, v2.end());
// v2.erase(unique(v2.begin(), v2.end()), v2.end());
//unique와 erase함수를 사용하여 정렬한 vector의 중복된 원소를 제거할 수 있다.
for (int index : v2)
{
std::cout << index << " ";
}
return;
}
<출력 결과>
첫번째 결과 : 정렬없이 unique함수를 동작했을때 반환되는 값은 v1[4]의 반복자가 반환된다.
두번째 결과 : 오름차순 정렬 뒤에 unique함수를 동작했을때 10의 원소가 한개씩 20,30으로 변경 되었다. 하지만 의미 중복을 제거하는 것이 목적이기에 의미 없는값들이다. (작동원리는 밑에서 서술)
세번쨰 결과 : v2.erase함수를 범위 : iter(v2[3]) ~ v2.end() 만큼 제거한뒤 출력한 값이다.
<작동 원리>
위 링크는 첫번째 결과값을 작동원리를 설명했으니 나는 정렬한 두번째 값(10 10 10 20 20 30)으로 설명을 해보겠다.
//unique함수 원문
template <class ForwardIterator>
ForwardIterator unique (ForwardIterator first, ForwardIterator last)
{
if (first==last) return last;
ForwardIterator result = first;
while (++first != last)
{
if (!(*result == *first)) // or: if (!pred(*result,*first)) for version (2)
*(++result)=*first;
}
return ++result;
}//출처 : https://www.cplusplus.com/reference/algorithm/unique/
if (first==last) return last;
first iter와 last iter가 같은경우는 원소가 1개 이하라는 뜻이므로 end() 값을 리턴
while 반복문에 들어와서
if (!(*result == *first)) , if조건문이 있는데 result와 first가 같으므로 true에 !를 만나 false를 반환
다시 while 반복문의 조건을 확인해서 계속 roop 시키면 ......
if (!(*result == *first)의 true임으로 if문이 동작한다.
*first 가 가르키고 있는 20의 data를 result의 다음 반복자(++result)에 data를 정의하는것이다.
그럼 vector의 [1] index의 data는 10-> 20으로 변경된다. 그리고 이 과정을 while이 false가 나올때까지 반복하게 되면
중복 되지 않은 원소는 전부 앞으로 정렬하게 되고, 중복된 원소들은 뒤로 밀리게 되며 반환되는 return 값은 현재 가르키고있는 result의 다음 iter 값이 반환된다. 즉, unique함수의 return값은 쓰게기값(중복값)들이 모여있는 첫번째 인덱스를 iter를 반환하게 된다.
이 점을 이용하여 unique한뒤 erase함수로 현재 반환 받은 값에서부터 end() 까지 지워버리면
10 20 30 만 남게 되는것이다.
'C++' 카테고리의 다른 글
std::vector (reverse_iterator,rbegin(),rend(),역방향반복자,내림차순정렬) (0) | 2023.06.09 |
---|---|
STL 범용 수치 알고리즘 (accumulate , inner_product) (0) | 2023.06.09 |
문자집합(Character Set) (0) | 2023.06.04 |