본문 바로가기
[C++] Data Structure & Algorithm/STL

[STL] algorithm

by song.ift 2023. 5. 22.

기존 문제점

  • 예제를 하나씩 풀어봤는데, 가독성이 좋지 않다는 걸 알 수 있다. 코드는 굉장히 단순하지만, 그래도 분석하는데 최소 10초는 걸릴 수 있다고 생각할 수 있다. 또한 정형화된 패턴이 아니다보니 프로그래머 마다 스타일이 다를 수도 있다. 그래서 바로 보자마자 이해하기 어렵다.
  • 더욱 큰 단점은 코드는 vector를 사용했기 때문에, 코드 내에선 특정 인덱스에 접근(v[i])하는 임의 접근 코드가 들어가있지만, 만약 삽입/삭제의 효율 때문에 list로 바꿔야 한다면 문법의 문제가 생길것이다.
cpp
닫기
#include <list> #include <map> #include <iostream> using namespace std; int main() { ​​​​srand(static_cast<unsigned int>(time(nullptr))); ​​​​ ​​​​vector<int> v; ​​​​ ​​​​for (int i = 0; i < 100; ++i) ​​​​{ ​​​​​​​​int num = rand() % 100; ​​​​​​​​v.push_back(num); ​​​​} ​​​​ ​​​​// Q1) number 라는 숫자가 벡터에 체크하는 기능 (bool, 첫 등장 iterator) ​​​​{ ​​​​​​​​int number = 50; ​​​​​​​​ ​​​​​​​​bool found = false; ​​​​​​​​vector<int>::iterator it = v.end(); ​​​​​​​​ ​​​​​​​​for (unsigned int i = 0; i < v.size(); ++i) ​​​​​​​​{ ​​​​​​​​​​​​if (v[i] == number) ​​​​​​​​​​​​{ ​​​​​​​​​​​​​​​​found = true; ​​​​​​​​​​​​​​​​it = v.begin() + i; ​​​​​​​​​​​​​​​​break; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​} ​​​​ ​​​​// Q2) 11로 나뉘는 숫자가 벡터에 있는지 체크하는 기능 (bool, 첫 등장 iterator) ​​​​{ ​​​​​​​​bool found = false; ​​​​​​​​vector<int>::iterator it; ​​​​​​​​ ​​​​​​​​for (unsigned int i = 0; i < v.size(); ++i) ​​​​​​​​{ ​​​​​​​​​​​​int data = v[i]; ​​​​​​​​​​​​if ((data % 11) == 0) ​​​​​​​​​​​​{ ​​​​​​​​​​​​​​​​found = false; ​​​​​​​​​​​​​​​​it = v.begin() + i; ​​​​​​​​​​​​​​​​break; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​} ​​​​ ​​​​// Q3) 홀수인 숫자의 개수는? (count) ​​​​{ ​​​​​​​​int count = 0; ​​​​​​​​ ​​​​​​​​for (unsigned int i = 0; i < v.size(); ++i) ​​​​​​​​{ ​​​​​​​​​​​​int data = v[i]; ​​​​​​​​​​​​if (data % 2) != 0) ​​​​​​​​​​​​​​​​count++; ​​​​​​​​} ​​​​} ​​​​ ​​​​// Q4) 벡터에 들어가있는 모든 숫자들에 3을 곱해주세요. ​​​​{ ​​​​​​​​for (unsigned int i = 0; i < v.size(); ++i) ​​​​​​​​{ ‌​​​​​​​​v[i] *= 3; ​​​​​​​​} ​​​​} ​​​​ ​​​​// Q5) 홀수인 데이터를 일괄 삭제 ​​​​{ ​​​​​​​​for (auto it = v.begin(); it != v.end(); ) ​​​​​​​​{ ‌‌‌if ((*it % 2) != 0) ‌​​​​​​​​​​​​it = v.erase(it); ​​​​​​​​​​​​else ‌​​​​​​​​​​​​++it; ​​​​​​​​} ​​​​} }

 

알고리즘 사용

cpp
닫기
#include <list> #include <map> #include <iostream> // 주제 : 알고리즘 #include <algorithm> using namespace std; int main() { ​​​​// 자료구조 (데이터를 저장하는 구조) ​​​​// 알고리즘 (데이터를 어떻게 사용할 것인가?) ​​​​ ​​​​// find ​​​​// find_if ​​​​// count ​​​​// count_if ​​​​// all_of ​​​​// any_of ​​​​// for_each ​​​​// remove ​​​​// remove_if ​​​​ ​​​​srand(static_cast<unsigned int>(time(nullptr))); ​​​​ ​​​​vector<int> v; ​​​​ ​​​​for (int i = 0; i < 100; ++i) ​​​​{ ​​​​​​​​int num = rand() % 100; ​​​​​​​​v.push_back(num); ​​​​} ​​​​ ​​​​// Q1) number 라는 숫자가 벡터에 체크하는 기능 (bool, 첫 등장 iterator) ​​​​{ ​​​​​​​​int number = 50; ​​​​​​​​ ​​​​​​​​bool found = false; ​​​​​​​​vector<int>::iterator it = v.end(); ​​​​​​​​ ​​​​​​​​for (unsigned int i = 0; i < v.size(); ++i) ​​​​​​​​{ ​​​​​​​​​​​​if (v[i] == number) ​​​​​​​​​​​​{ ​​​​​​​​​​​​​​​​found = true; ​​​​​​​​​​​​​​​​it = v.begin() + i; ​​​​​​​​​​​​​​​​break; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​ ​​​​​​​​auto itFind = find(v.begin(), v.end(), number); ​​​​​​​​if (itFind == v.end()) ​​​​​​​​​​​​cout << "못 찾았음" << endl; ​​​​​​​​else ​​​​​​​​​​​​cout << "찾았음" << endl; ​​​​} ​​​​ ​​​​// Q2) 11로 나뉘는 숫자가 벡터에 있는지 체크하는 기능 (bool, 첫 등장 iterator) ​​​​{ ​​​​​​​​bool found = false; ​​​​​​​​vector<int>::iterator it; ​​​​​​​​ ​​​​​​​​for (unsigned int i = 0; i < v.size(); ++i) ​​​​​​​​{ ​​​​​​​​​​​​int data = v[i]; ​​​​​​​​​​​​if ((data % 11) == 0) ​​​​​​​​​​​​{ ​​​​​​​​​​​​​​​​found = false; ​​​​​​​​​​​​​​​​it = v.begin() + i; ​​​​​​​​​​​​​​​​break; ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​ ​​​​​​​​struct CanDivideBy11 ​​​​​​​​{ ​​​​​​​​​​​​bool operator()(int& n) ​​​​​​​​​​​​{ return (n % 11) == 0; } }; vector<int>::iterator itFind = std::find_if(v.begin(), v.end(), CanDivideBy11()); vector<int>::iterator itFind = std::find_if(v.begin(), v.end(), [](int n) { return (n % 11) == 0; }); if (itFind == v.end()) cout << "못 찾았음" << endl; else cout << "찾았음" << endl; } // Q3) 홀수인 숫자의 개수는? (count) { int count = 0; for (unsigned int i = 0; i < v.size(); ++i) { int data = v[i]; if (data % 2) != 0) count++; } struct IsOdd { ​​​​​​​​​​​​bool operator()(int& n) ​​​​​​​​​​​​{ return (n % 2) != 0; } }; int n = std::count_if(v.begin(), v.end(), IsOdd()); // 모든 데이터가 홀수입니까? bool b1 = std::all_of(v.begin(), v.end(), IsOdd()); // 홀수인 데이터가 하나라도 있습니까? bool b2 = std::any_of(v.begin(), v.end(), IsOdd()); // 모든 데이터가 홀수가 아닙니까? bool b3 = std::none_of(v.begin(), v.end(), IsOdd()); } // Q4) 벡터에 들어가있는 모든 숫자들에 3을 곱해주세요. { for (unsigned int i = 0; i < v.size(); ++i) { v[i] *= 3; } struct MultiplyBy3 { ‌​​​​​​​​void operator()(int& n) ​​​​​​​​​​​​{ n *= 3; } }; std::for_each(v.begin(), v.end(), MultiplyBy3()); } // Q5) 홀수인 데이터를 일괄 삭제 { for (auto it = v.begin(); it != v.end(); ) { if ((*it % 2) != 0) it = v.erase(it); else ++it; } v.clear(); v.push_back(1); v.push_back(4); v.push_back(3); v.push_back(5); v.push_back(8); v.push_back(2); struct IsOdd { ​​​​​​​​​​​​bool operator()(int& n) ​​​​​​​​​​​​{ return (n % 2) != 0; } }; // 기존 : 1 4 3 5 8 2 // 결과 : 4 8 2 5 8 2 (이상한 결과가 나온다는 것을 볼 수 있다) std::remove_if(v.begin(), v.end(); IsOdd()); // std::remove(v.begin(), v.end(), 4); // 직접 동작을 까보니 /* template<class ForwardIt, class UnaryPredicate> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p) { first = std::find_if(first, last, p); if (first != last) for (ForwardIt i = first; ++i != last;) if (!p(*i)) *first++ = std::move(*i); return first; } */ // 불필요한 데이터를 일일이 삭제하는 것이 아니라 // 필요한 데이터만 남겨두는 것으로 작동하고 있다. // 리턴해주는 first 데이터는 사용하지 않아야 하는 이터레이터(위치)를 리턴해준다. // 말 그대로 4 8 2 위치(5) 8 2 // 정리하자면, remove란 이름때문에 삭제해주는 걸로 느껴지는데 // 실질적으로 데이터를 날려주는 부분은 없고, // 필요한 데이터만 재조정한 후, 사용하지 않는 데이터의 첫 위치를 반환해준다고 보면 된다. // 그래서 remove만 단독적으로 사용한다기 보다는 // remove와 erase를 같이 사용해서 필요하지 않는 쓰레기 데이터를 지워줘야 한다. vector<int>::iterator it = std::remove_if(v.begin(), v.end(); IsOdd()); v.erase(it, v.end()); // v.erase(std::remove_if(v.begin(), v.end(); IsOdd()), v.end()); } }

'[C++] Data Structure & Algorithm > STL' 카테고리의 다른 글

[STL] set, multimap, multiset  (0) 2023.05.20
[STL] map  (1) 2023.05.19
[STL] deque  (0) 2023.05.19
[STL] list #2  (0) 2023.05.19
[STL] list #1  (0) 2023.05.15

댓글