정글에서 온 개발자

12/30 TIL C++ 알고리즘을 위한 STL 소소팁 본문

TIL

12/30 TIL C++ 알고리즘을 위한 STL 소소팁

dev-diver 2024. 12. 30. 23:43

연차 덕분에 조금 많이 공부할 수 있었다.

map, set

파이썬 보다 편한 counter

map을 선언했을 때,  m[key] 로 접근하면, 해당 key가 없는 경우 자동으로 기본값으로 key,value가 생성된다.
이를 이용해 counter를 만들 수 있다.

unordered_map<int,int> m;
m[3]++;

위 코드에서 3은 자동으로 1로 증가한다.
자동으로 생기는 게 불편하다면 m.at(index) 와 같이 접근해야 한다.

요소 확인

위 내용처럼 if(m[index]) 와 같이 접근하면 기본값으로 요소가 생겨버리기 때문에 불편하다. find나 count를 써야 하는데 count가 더 편하다.

if(m.count(3)) //0을 false로 취급한다.
//또는
if(m.find(3)!=m.end())
//find는 iterator를 반환한다. count보다 번거로운대신, count보다 빠르다.

vector화

map은 key, value pair를 갇는 vector로 바로 복사할 수 있다.  pair가 아닌 다른 vector( vector<vector<int,int>> 등) 로는 복사되지 않는다.

vector<pair<int,int>> vec1(m.begin(), m.end());

sort

map 선언시 key에 대해 sort되게 compare lambda를 만들 수 있다. 

function<bool(int,int)> compare = [](int a, int, b){return a > b;};
map<int, string, function<bool(int,int)>> m(compare);

//혹은

std::map<int, string, decltype(auto)> m(
    [](int a, int b) { return a > b; }
);

그러나 value에 대해 sort 되게는 생성시에는 못한다.

vector를 key로 가지기

map<vector<int>,int> m;   //이건 되고
unorderd_map<vector<int>, int> um; //이건 안된다.

vector<int> 에 대한 hash가 정의되어 있지 않기 때문에, 기본적으로 map에서 key로 사용할 수 없다.
그러나 map의 경우 ordering을 위해 key를 '비교' 하는데 이 때문에 비교가 구현된 type은 key로 사용할 수 있게 된다.

관련문제 > [leetcode] 2352.Equal Row and Column Pairs

pair

make_pair를 통해 생성자 대신 사용할 수도 있지만, 추론을 이용할 수도 있다.

stack<pair<int,TreeNode*>> stk;


stk.push(make_pair(root->val, root));
//자동 추론
stk.push({root->val ,root}};

튜플

튜플은 index로 접근을 못한다.

//이렇게 접근하거나
auto first = get<0>(tup);

//다 써야 한다면 차라리 이렇게 풀어버리자
auto [first, second, third] = tup;

vector<int> vec ={1,3,5,2};
priority_queue<int> pq(vec.begin(), vec.end());

make_heap을 쓰는 방법도 있다.

make_heap은 최우선순위를 가장 앞으로 뺀다. con.front()로 접근 가능

pop_heap()은 제거해야 할 원소를 가장 뒷쪽으로 빼고, 나머지는 heap으로 유지한다. 따라서 맨 앞 요소는 두번째 최우선 요소다.
push_heap() 가장 뒷쪽의 원소를 heap을 유지하면서 다시 넣는다.
위 두 메서드 모두 실제로 제거, 추가하는 메서드는 아니므로, con.push_back(), con.pop_back()의 도움이 필요하다.

vector<int> vec = {1,3,5,6,2,5};
make_heap(vec.begin(), vec.end());
auto prime = vec.front(); //최우선순위는 맨 앞에 있음

pop_heap(vec.begin(), vec.end()); //가장 뒷쪽으로뺌
vec.pop_back();  //실제 제거

vec.push_back(30); //실제 추가
push_heap(vec.begin(), vec.end()); //heapify

일반

begin, end

begin(vec) 은 vec.begin() 과 같다.  end() 도 마찬가지.  대부분의 STL 컨테이너는 모두 가지고 있다.
 -> stack, queue는 없음, map,set은 오히려 있음

begin, end가 있어야  initializer_list로 초기화 할 수 있다.  그래서 stack, queue는 {} 로 초기화를 못한다.

구조화 바인딩

아래 셋다 유효한 문법이다.

auto [key,value] = p;
auto &[key, value] = p;
auto [key, &value] = p;

max, minmax_element, min_element

int mx = max(a,b);

auto [miniter, maxiter] = minmax_element(vec);
auto it = min_element(vec);

count, count_if

count(vec.begin(), vec.end(), 2);
count_if(vec.begin(), vec.end(), [](int x) { return x % 2 == 0; });

'TIL' 카테고리의 다른 글

1/1 오픈소스, C++  (0) 2025.01.01
12/31 TIL C++ 소소한 배움  (0) 2024.12.31
12/28 TIL 좋은 단위 테스트의 4대 요소  (1) 2024.12.29
12/28 TIL 단위 테스트의 구조  (1) 2024.12.28
12/27 TIL 게임 객체 모델의 종류  (0) 2024.12.28