[STL] vector 의 정렬 - object pointer 정렬

[STL] vector 의 정렬 - object pointer 정렬

enter image description here
이 주제는 C++ STL 의 기본에 가까운 듯 한데, 평소에 C++ 로 프로젝트가 진행되는 경우가 없어서 익숙하지가 않아, 쓸때마다 헷갈려서 ( 특히 object pointer 타입을 다룰 때… ) 정리차원에서 한 번 포스팅해 좀.

1. Primitive 타입

먼저 가장 기본 형태. primitive type 의 vector 를 보자.

vector<int> v;  
  
for (int i = 0; i < 20; i++)  
    v.push_back(i);  
  
random_shuffle(v.begin(), v.end());  
  
for (int i = 0; i < 20; i++) cout << v[i] << " ";  
cout << endl;  
  
sort(v.begin(), v.end());  
  
for (int i = 0; i < 20; i++) cout << v[i] << " ";  
cout << endl;

(실행결과)

1 11 15 0 14 7 16 13 8 10 17 5 2 19 18 9 4 3 6 12  
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

위와 같이 오름차순으로 정렬이 된다. 기본적으로 std::sort 함수는 elements 비교에 ‘<’ 연산자를 사용하기 때문이다.

그럼 내림차순으로 정렬을 하려면 어떻게 해야 하는가?

바로 compare 하는 함수를 지정해 주거나, compare object 를 지정해 주는 것이다. 이때 함수는 bool comp(int a, int b) 형태로 표현하면 된다.

중요한 점은 comp 함수의 return value 가 true 라면 a 가 b 보다 앞으로 간다는 것이다.

위의 코드에서 comp 함수를 추가하고 sort 를 아래와 같이 바꿔서 실행해 보면

// compare function  
bool comp(int a, int b) {  
    return (a > b);  
}

// compare object  
struct comp_object {  
    bool operator() (int a, int b) {  
        return (a > b);  
    };  
} comp_obj;  
.
.
.
sort(v.begin(), v.end(), comp);
sort(v.begin(), v.end(), comp_obj);

(실행결과)

1 11 15 0 14 7 16 13 8 10 17 5 2 19 18 9 4 3 6 12  
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

위와같이 내림차순으로 정렬이 된다. (compare object 에 대해서는 나도 잘 알지 못하기에 뒤의 class T, class T* 타입에 대한 내용에서는 패스한다.)

2. Clsas T 타입

이제 본격적으로 vector 타입의 정렬에 대해서 알아보자.

기본 사용법은 아래와 같다. 위에서 언급하였듯이 std::sort 는 elements 비교에 ‘<’ 연산자를 사용하므로 ‘<’ 연산자를 오버로딩 해 주어야 한다.

class T {  
public:  
    int data;  
  
    T (int a) { data = a; }  
    bool operator<(const T &t) const {  
        return (data < t.data);  
    }  
};

vector<T> v;  
  
for (int i = 0; i < 20; i++) {  
    v.push_back(T(i));  
}  
  
random_shuffle(v.begin(), v.end());  
  
for (int i = 0; i < 20; i++) cout << v[i].data << " ";  
cout << endl;  
  
sort(v.begin(), v.end());  
  
for (int i = 0; i < 20; i++) cout << v[i].data << " ";  
cout << endl;

‘<’ 연산자는 sort 뿐만 아니라 다른 코드에서도 사용할 수 있으므로, ‘<’ 연산결과와 다른 순서로 sorting 을 하고 싶다면, compare 함수를 직접 지정해 주면 된다.

class T {  
public:  
    int data;  
    T (int a) { data = a; }  
    bool operator<(const T &t) const {  
        return (data < t.data);  
    }  

    static bool comp(const T &t1, const T &t2) {  
        return (t1.data > t2.data);  
    }  
};  
.
.
.
sort(v.begin(), v.end(), T::comp);

물론 comp 함수가 class T 의 멤버함수일 필요는 없다.
( 하지만 더 깔끔해 보이지 않은가? )

3. Class T* 타입

(중요) T 타입은 class 의 ‘<’ 연산자 오버로딩을 하여도 제대로 동작하지 않는다!!!*
게다가 아래와 같은 코드가 함께 있다면, 빌드 에러도 발생하지 않는다.

bool operator<(const T &t) const { ... }  

가령 위의 코드에서 T 의 멤버함수에 아래와 같이 연산자 오버로딩을 하고,

bool operator<(const T *t) const {
    return(data < t->data);  
}

vector<T*> 에 대해서 std::sort 수행하여도 저 함수는 호출되지 않는다.
vector<T*> 에 대하여 std::sort 를 하기 위해서는, T* 에 대한 compare fuction 이나 compare object 를 지정해 주어야 한다.

class T {  
public:  
    int data;
    T (int a) { data = a; }  
    static bool comp(const T *t1, const T *t2) {  
        return (t1->data < t2->data);  
    }  
};
.
.
.
sort(v.begin(), v.end(), T::comp);

쓰다보니 가장 중요한 내용이 제일 마지막에 있게 되었는데, 잘 기억해 두자.

크리에이티브 커먼즈 라이선스
이 저작물은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

Written with StackEdit.

댓글

이 블로그의 인기 게시물

[게임개발 스토리] 장르/타입/조합 정보와 몇 가지 팁

[윈도우] 실행 중인 프로그램의 타이틀을 변경하는 유틸리티

Synergy 한글키 패치 공식 버전 적용 및 최종 정리