페이지가 로드되지 않나요? 여기를 눌러보면 고쳐질 수도 있어요.
Placeholder

#8563

Tutorial : STL Sort 3 ( 구조체 정렬하기 ) 2s 1024MB

문제

STL Sort 함수에 정렬 기준을 넣는 방법과,

연산자 오버로딩 이론까지 모두 배웠다.

이제는 이들을 응용하여, 가장 중요한 기법 중 하나인 구조체(struct) 정렬을 익혀보자!


학생들의 정보가 이름(string)과 나이(int) 로 주어져 있다.

10명의 정보를 입력 받아, 1순위 : 나이 , 2순위 : 이름 을 기준으로 정렬하고 싶은 상황이다.

우선, 틀린 코드부터 보자.

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

struct Student{
    string name; //  이름
    int age; // 나이
};

int main(){
    int i;
    Student arr[10];

    // 입력
    for(i = 0; i < 10; i++) {
        cin >> arr[i].name >> arr[i].age;
    }
    
    // 정렬
    sort(arr, arr + 10);
}

위 코드를 컴파일하면, 오류가 발생한다. 왜 그럴까?

그냥 무작정 sort 함수를 돌리면, 컴퓨터 입장에서는 name, age 중 어떤 것을 기준으로 정렬해야 될 지 모르기 때문이다.

여러 변수를 관리하는 구조체를 정렬할 때는, 반드시 정렬 기준을 명시해야 한다.

방법은 크게 2가지다.


방법 1 : comp 함수를 이용한 정렬 기준 설정

이 방법은 STL Sort 함수에 정렬 기준을 넣는 것을 응용한다.

이 때 배운 방법대로, 두 개의 Student 구조체를 받아오는 bool comp 함수를 만들어, sort 함수 인자에 추가하면 된다.

bool comp(Student Left, Student Right){
    // 1순위 정렬 기준 : 나이
    // 나이가 다르다면, 무조건 나이를 기준으로 비교한다.
    if(Left.age != Right.age) return Left.age < Right.age;

    // 2순위 정렬 기준 : 이름
    // 나이가 같았다면, 이름을 기준으로 비교한다. 
    return Left.name < Right.name;
}

sort( arr , arr + 10 , comp ); // comp 함수를 마지막에 추가하여 정렬 기준을 설정


방법 2 : 연산자 오버로딩을 이용한 정렬 기준 설정

이 방법은 앞서 배운 연산자 오버로딩으로 정렬한다.

별도의 comp 함수를 만드는 것이 아니라, 구조체 안에 < 연산자 를 넣어서 비교하는 것이다.

이것을 이해하는 것도 앞선 논리와 비슷하다.

배열에서 오른쪽으로 갈수록 나이가 많아지길 원하니, age < Right.age 가 되는 것이다.

struct Student{
    string name;
    int age;
    bool operator<(const Student &Right) const{
        if(age != Right.age) return age < Right.age;
        return name < Right.name; 
    }    
}

// Student 구조체 안에 이미 정렬 기준이 들어가 있기에, sort 함수에 인자를 추가할 필요는 없다.
sort( arr , arr + 10 ); 


응용 : 서로 다른 정렬 기준으로 두 번 정렬하고 싶다면?

방금 우리는 "1순위 : 나이 , 2순위 : 이름" 으로 정렬했었다.

이후에, 이를 바꾸어 "1순위 : 이름 , 2순위 : 나이"한 번 더 정렬하고 싶다면 어떻게 하면 될까?

// 정렬 기준 1 : 나이, 이름 순서
bool comp1 ( Student Left , Student Right ){
    if(Left.age != Right.age) return Left.age < Right.age;
    return Left.name < Right.name;
}

// 정렬 기준 2 : 이름, 나이 순서
bool comp2 ( Student Left , Student Right ){
    if(Left.name != Right.name) return Left.name < Right.name;
    return Left.age < Right.age;
}

sort( arr , arr + 10 , comp1 ); // 정렬 기준 1 로 정렬
sort ( arr , arr + 10 , comp2 ); // 정렬 기준 2 로 정렬

위처럼, comp 함수를 2개 만들어서 하면 된다.

comp1 을 넣으면 comp1 대로, comp2 를 넣으면 comp2 대로 정렬된다.

아니면, 아래 코드처럼 해도 된다.

struct Student{
    string name;
    int age;
    bool operator<(const Student &Right) const{
        if(age != Right.age) return age < Right.age;
        return name < Right.name; 
    }
}

bool comp( Student Left , Student Right ){
    if(Left.name != Right.name) return Left.name < Right.name;
    return Left.age < Right.age;
}

sort( arr , arr + 10 ); // sort 뒤에 comp 가 없음 : 구조체에 들어있는 정렬 기준대로 정렬됨
sort( arr , arr + 10 , comp ); // sort 뒤에 comp 가 있음 : comp 의 정렬 기준대로 정렬됨

정렬 기준 하나는 구조체 안에 넣고 ( bool operator < ),

나머지 하나는 구조체 밖에 구현한 것이다. ( bool comp 함수 )

sort(arr, arr+10) 처럼 뒤에 comp 가 없을 때는, 우리가 bool operator < 로 구조체 안에 넣어준 정렬 기준대로 sort 된다.

sort(arr, arr+10, comp) 처럼 뒤에 comp 가 있을 때는, 구조체 밖 comp 함수의 정렬 기준대로 sort 된다.

( 구조체 안에 있는 bool operator < 는 무시된다. )


이제 이를 이용한 문제를 풀어보자.

나이(int), 키(double) 로 구성된 사람들의 정보가 N 개 입력된다.

1순위 : 나이의 내림차순, 2순위 : 키의 내림차순을 기준으로 정렬하여 출력하고,

이후에 1순위 : 키의 오름차순, 2순위 : 나이의 오름차순을 기준으로 정렬하여 출력하자.


입력

첫 줄에 N 이 입력된다. ( 1 ≤ N ≤ 100,000 )

이후 N 줄에 걸쳐 나이와 키가 입력된다. ( 나이와 키 모두 0 이상 1만 이하 )

모든 키는 소수점 아래 한 자리만 입력된다.


출력

1순위 : 나이의 내림차순, 2순위 : 키의 내림차순을 기준으로 정렬하여 출력한다.

이후 줄 바꿈을 한 번 더 하고,

1순위 : 키의 오름차순, 2순위 : 나이의 오름차순을 기준으로 정렬하여 출력한다.

( 키를 출력할 때는, 무조건 "소수점 둘째 자리에서 반올림"하여, 소수점 첫째 자리까지 출력한다. )

( 키가 100 으로 정수여도, 무조건 100.0 으로 출력해야 한다. )


예제

7
1 2.4
9 9.9
9 5.5
9 8.0
1 5.5
1 8.0
3 5.5
9 9.9
9 8.0
9 5.5
3 5.5
1 8.0
1 5.5
1 2.4

1 2.4
1 5.5
3 5.5
9 5.5
1 8.0
9 8.0
9 9.9



출처

againalgo

로그인해야 코드를 작성할 수 있어요.