728x90
728x90

pair(페어)와 tuple(튜플)

pair(페어)

개념

  • 사용자가 지정한 2개의 타입의 데이터를 저장하기 위해 사용되는 클래스
  • 서로 연관된 2개의 데이터를 한 쌍으로 묶어서 다룰 때 사용하면 편리하다.
  • 구조체(struct) 대신 편리하게 2개의 데이터를 관리할 수 있다.

 

헤더 파일

  • 페어(pair)를 사용하려면 다음의 헤더를 불러와야 한다.
#include <utility>
  • 하지만, <vector>, <algorithm> 헤더를 사용할 경우, <utility> 헤더가 포함되어 있어 따로 불러와 주지 않아도 된다.
#include <vector>    // <utility> 헤더 포함
#include <algorithm>    // <utility> 헤더 포함

 

형태

  • 페어(pair)의 형태는 다음과 같다. 
template <class T1, class T2> struct pair;
  • T1에 첫 번째 인자를, T2에 두 번째 인자를 넣어주면 된다.

 

사용 방법

초기화

  • 다음과 같이 페어(pair)를 초기화할 수 있다.
pair<int, int> p1(3, 12);         // C++ 스타일 
pair<int, int> p2 = { 3, 12 };    // C 스타일

 

  • 또는 다음과 같이 .first, .second 를 이용하여 초기화할 수도 있다.
pair<int, int> p3;

p3.first = 3;
p3.second = 12;

 

  • 또는 다음과 같이 make_pair() 함수를 이용해 선언과 초기화를 분리할 수 있다.
pair<int, int> p4;

p4 = make_pair(3, 12);    // p의 첫 번째 인자와 두 번째 인자에 2와 3을 넣어준다.

 

  • 페어(pair)의 인자의 자료형은 서로 동일하지 않아도 된다. 
pair<int, int> p1;
pair<int, double> p2;
pair<double, double> p3;
pair<string, int> p4;

 

원소 접근

  • 페어 클래스의 첫 번째 인자에 접근하려면 .first를, 두 번째 인자에 접근하려면 .second를 변수명 뒤에 붙여준다.
pair<int, int> p;

p.first = 3;    // 첫 번째 인자에 대입
p.second = 12;  // 두 번째 인자에 대입

cout << p.first << endl;    // 첫 번째 인자 출력
cout << p.second << endl;    // 두 번째 인자 출력

 

다른 컨테이너와 함께 사용

  • 다음과 같이 벡터(vector) 컨테이너와 함께 사용할 수 있다.
vector<pair<string, int>> user1;
user1 = make_pair("Kim", 38);

vector<pair<string, int>> user2;
user2.first = "Park";
user2.second = "17";

 

  • 벡터(vector)와 같은 컨테이너와 함께 사용할 경우, 가독성을 위해 다음과 같이 사용할 수 있다.
typedef pair<int, int> p;    // pair<int, int>를 p로 별칭 부여
vector<p> v;     // vector<pair<int, int>> v; 와 동일한 표현

 

사용 예

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool Compare(pair<int, int> a, pair<int, int> b) {
    if (a.second == b.second) {    // y좌표가 같으면
        return a.first < b.first;    // x 좌표를 오름차순으로 정렬
    }
    return a.second < b.second;    // y좌표가 증가하는 순으로 정렬
}

int N, x, y;
vector<pair<int, int>> xy;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin >> N;

    for (int i = 0; i < N; i++) {
        cin >> x >> y;
        xy.push_back({x, y});
    }

    sort(xy.begin(), xy.end(), Compare);

    for (auto i : xy) {
        cout << i.first << " " << i.second << '\n';
    }

    return 0;
}

 

tuple(튜플)

개념

  • 튜플(Tuple)은 '사물의 유한한 순서'를 의미하며, 파이썬 등 다양한 언어에서 2개 이상의 값들을 정리할 때 사용된다.
  • 사용자가 지정한 2개 이상의 타입의 데이터를 저장하기 위해 사용되는 클래스이다.
  • 서로 연관된 2개 이상의 데이터를 한 쌍으로 묶어서 다룰 때 사용하면 편리하다.
  • C++11부터 사용 가능하다.

 

헤더 파일

  • 튜플(tuple)을 사용하려면 다음의 헤더를 불러와야 한다.
#include <tuple>

 

형태

template <class... Types> class tuple;

 

사용 방법

초기화

  • 다음과 같이 튜플(tuple)을 초기화할 수 있다.
tuple<string, int, char> t1("Kim", 26, 'M');          // C++ 스타일
tuple<string, int, char> t2 = { "Park", 22, 'F' };    // C 스타일

 

  • 또는 다음과 같이 make_tuple() 함수를 이용해 선언과 초기화를 분리할 수 있다.
tuple<string, int, char> t1;
t1 = make_tuple("Kim", 26, 'M');

 

원소 접근

  • get<>() 함수를 이용해 원소에 접근할 수 있다.
get<접근할_원소의_인덱스>(접근할_튜플의_이름)

 

tuple<string, int, char> t1("Kim", 26, 'M');

cout << get<0>(t1) << endl;    // Kim
cout << get<1>(t1) << endl;    // 26
cout << get<2>(t1) << endl;    // M

 

원소 분해

  • tie() 함수를 이용해 튜플의 원소를 각각의 변수에 분해하여 초기화 해줄 수 있다. 
    • 이 때, 자료형을 맞추어 주지 않으면 에러가 발생한다.
tuple<string, int, char> t1("Kim", 26, 'M'); 

string name;
int age;
char gender;

tie(name, age, gender) = t1;    // t1의 원소들을 각각 name, age, gender 변수에 대입

cout << name << endl;      // Kim
cout << age << endl;       // 26
cout << gender << endl;    // M

 

2개의 튜플 연결

  • tuple_cat() 함수를 이용하여 서로 다른 2개의 튜플을 연결할 수 있다.
  • 이 때, 두 튜플을 연결한 데이터를 저장할 새로운 튜플의 자료형은 프로그래머가 맞춰 주어야 한다.
tuple<int, int> t1(1, 2);
tuple<int, int> t2(3, 4);
tuple<int, int, int, int> t3 = tuple_cat(t1, t2);    // t1 튜플과 t2 튜플을 연결하여 t3 튜플 생성

cout << get<0>(t3) << endl;     // 1
cout << get<1>(t3) << endl;     // 2
cout << get<2>(t3) << endl;     // 3
cout << get<3>(t3) << endl;     // 4

 

  • t3의 자료형처럼 자료형을 일일이 맞춰주기 번거로우면 auto 키워드를 사용하면 된다.
auto t3 = tuple_cat(t1, t2);

 

서로 다른 튜플의 변경 

  • swap() 함수를 사용하면 서로 다른 2개의 튜플을 스왑할 수 있다.
  • 단, 변경 하고자 하는 두 튜플의 자료형은 모두 일치해야 한다.
tuple<int, int> t1(1, 2);
tuple<int, int> t2(3, 4);

cout << get<0>(t1) < endl;    // 1
cout << get<1>(t1) < endl;    // 2
cout << get<0>(t2) < endl;    // 3
cout << get<1>(t2) < endl;    // 4

t1.swap(t2);    // t1 튜플과 t2 튜플을 서로 스왑

cout << get<0>(t1) < endl;    // 3
cout << get<1>(t1) < endl;    // 4
cout << get<0>(t2) < endl;    // 1
cout << get<1>(t2) < endl;    // 2

 

사용 예

#include <iostream>
#include <vector>
#include <tuple>
using namespace std;

using myVector = vector<tuple<int, int, int>>;

int N, weight, height, rate;
myVector body;

void BruteForce(myVector v) {
    for (int i = 0; i < v.size(); i++) {
        for (int j = 0; j < v.size(); j++) {
            if ((get<0>(body[i]) < get<0>(body[j])) && (get<1>(body[i]) < get<1>(body[j]))) {
                get<2>(body[i])++;
            }
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin >> N;

    rate = 1;
    for (int i = 0; i < N; i++) {
        cin >> weight >> height;
        body.push_back({ weight, height, rate });
    }

    BruteForce(body);

    for (auto i : body) {
        cout << get<2>(i) << " ";
    }

    return 0;
}
728x90
728x90