본문 바로가기

자료구조 & 알고리즘

[std]set, map

set

set은 고유한 키를 특정한 순서로 저장하는 컨테이너다. set에 저장되는 원소들은 항상 const와 저장되기 때문에 수정할 수 없다. (삽입이나 삭제는 가능)

 

strict weak ordering criterion에 따라 정렬된다고 하는데 무슨 말인지 모르겠다.

 

먼저, <set>을 include해야 한다.

 

int를 저장하는 set은 다음과 같이 만들면 된다.(오름차순)

 

set<int> s;

 

내림차순으로 정렬하려면 다음과 같이 하면 된다.

 

set<int, greater<int>> s;

 

오름차순으로 정렬되는 set을 정의했다면 아래와 같이 넣고 출력해도 10, 20, 30, 40, 50이 출력된다.

 

s.insert(10);
s.insert(50);
s.insert(20);
s.insert(40);
s.insert(30);

 

원소를 출력하는 것은 다음과 같이 했다. 여러 튜토리얼을 보니 iterator로 set을 순회하며 출력하는 방법을 사용하던데 'auto &'를 사용하는 것이 백만배는 간편해 보인다.

 

for (auto &el : s) cout << el << " ";

 

아래는 set에 20이라는 원소가 있으면 Yes를 출력하고 없으면 No를 출력하는 것이다. s.find(20)을 사용해도 괜찮긴 하나, find 메서드는 iterator를 리턴한다. 그래서 사용하기 좀 까다롭다. 반면 아래처럼 count 메서드는 set에 해당 원소가 몇 개 있는지 리턴한다. 그러므로 20이 하나라도 있으면 Yes를 출력하고, 하나도 없으면 No를 출력한다.

 

if (s.count(20)) cout << "Yes" << '\n';
else cout << "No" << '\n';

 

그 외에도 사용할 법한 메서드가 몇 가지 있다.

1. erase(el) - set에서 해당 원소를 지운다.

2. clear() - set의 원소를 다 지운다.

3. empty() - set이 비었는지 확인한다.

 

아래는 사용자 정의 자료형을 만들고, 그것과 사용할 수 있는 비교 연산자 오버로딩을 한 것이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <set>
using namespace std;
 
struct node
{
    string name;
    int age;
};
 
bool operator < (const node &a, const node &b){
  if (a.age == b.age) return a.name < b.name;
  return a.age < b.age;
}
 
void print(set<node> &s) {
  for (auto &el : s) cout << el.name << " " <<  el.age << '\n';
}
 
int main() {
  set<node> s;
  s.insert(node{"A"10});
  s.insert(node{"B"10});
  s.insert(node{"A"20});
  s.insert(node{"C"40});
  s.insert(node{"D"30});
 
  print(s);
 
  if (s.count(node{"A"20})) cout << "Yes" << '\n';
  else cout << "No" << '\n';
 
  s.erase(node{"A"10});
 
  print(s);
 
  if (s.count(node{"D"40})) cout << "Yes" << '\n';
  else cout << "No" << '\n';
 
  return 0;
}
 

 

map

set이 key만 보관했던 반면, map은 key 와 value를 함께 보관한다.

 

set과 다른 점을 위주로 설명하겠다.

 

string과 int를 저장하는 m을 만들었다. 첫 번째 자료가 키이고, 두 번째 자료가 value다.

 

map<string, int> m;

 

map에 원소를 삽입할 때는 pair 형태로 넣어야 한다.

 

m.insert(make_pair("A", 10));
m.insert(make_pair("B", 10));
m.insert(make_pair("A", 20));
m.insert(make_pair("C", 40));
m.insert(make_pair("D", 30));

 

이 부분은 좀 특이했는데 아래와 같이 하면 map에 (F, 0)이 추가된다. 만약 키가 map에 존재한다면 데이터를 바꾼다.

 

m["F"] = 0;

 

아래처럼 출력할 수도 있다.

 

cout << m["A"] << '\n';

 

출력은 별 다를 것 없다. map에 저장된 것이 pair이므로 출력할 때도 first, second를 써줘야 한다.

 

for (auto &el : m) cout << el.first << " " <<  el.second << '\n';

 

원소를 찾는 것은 위와 같이 count를 사용한다. 키로 조회할 수 있다.

 

if (m.count("A")) cout << "Yes" << '\n';
else cout << "No" << '\n';

 

지울 때도 키로만 지울 수 있다.

 

m.erase("A");

 

정리

 

line 32 A를 조회하면 0이 나온다. line 25에서 A를 삭제했는데 0이 나오는 이유는 map은 데이터를 출력할 때 그 키가 없다면 디폴트 값을 출력하기 때문이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <map>
#include <string>
using namespace std;
 
void print(map<stringint> &m) {
  for (auto &el : m) cout << el.first << " " <<  el.second << '\n';
}
 
int main() {
  map<stringint> m;
  m.insert(make_pair("A"10));
  m.insert(make_pair("B"10));
  m.insert(make_pair("E"20));
  m.insert(make_pair("C"40));
  m.insert(make_pair("D"30));
 
  print(m);
 
  m["A"= 0;
 
  if (m.count("A")) cout << "Yes" << '\n';
  else cout << "No" << '\n';
 
  m.erase("A");
 
  print(m);
 
  if (m.count("F")) cout << "Yes" << '\n';
  else cout << "No" << '\n';
 
  cout << m["A"<< '\n';
  return 0;
}