Programming/c++

[c++] Stable_sort() vs Sort() 함수 차이

owls 2022. 11. 24. 22:59
728x90

1.함수 헤더 파일

#include <algorithm>

2.함수 원형

-sort 함수

// < 를 이용한 비교 (1)
template <class RandomIt>
void sort(RandomIt first, RandomIt last);

// 비교 함수 (comp) 를 이용한 비교 (2)
template <class RandomIt, class Compare>
void sort(RandomIt first, RandomIt last, Compare comp);

// Execution policy 를 지정한 경우 (3)
template <class ExecutionPolicy, class RandomIt>
void sort(ExecutionPolicy&& policy, RandomIt first, RandomIt last);

template <class ExecutionPolicy, class RandomIt, class Compare>
void sort(ExecutionPolicy&& policy, RandomIt first, RandomIt last, Compare comp);

-stable_sort함수

template <class RandomIt>
void stable_sort(RandomIt first, RandomIt last);  // (1)

template <class RandomIt, class Compare>
void stable_sort(RandomIt first, RandomIt last, Compare comp);  // (2)

// 아래 두 함수는 위와 동일하지만 ExecutionPolicy 를 추가로 받을 수 있다.
template <class ExecutionPolicy, class RandomIt>
void stable_sort(ExecutionPolicy&& policy, RandomIt first, RandomIt last);

template <class ExecutionPolicy, class RandomIt, class Compare>
void stable_sort(ExecutionPolicy&& policy, RandomIt first, RandomIt last, Compare comp);

 

3.return 값(반환 값)

없음

 

4.예제

#include <iostream>
#include <vector>
#include <algorithm>

int main(){
	
    vector<int> A = {1, 3, 2, 5, 4, 5, 2, 3};
    
    stable_sort(A.begin(), A.end());   // 1 2 2 3 3 4 5 5   
    stable_sort(A.rbegin(), A.rend()); // 5 5 4 3 3 2 2 1
    
    return 0;
}

 

5. sort vs stable_sort

▶ 기능의 차이

  : 기존에 두 요소가 가지고 있던 순서를 보장하는가 하지 않는가에 따른 기능적 차이가 있다.

sort() 동일한 값의 요소들에 대해, 두 요소가 기존에 가지고 있던 순서를 보장하지 않는다.
stable_sort() 동일한 값의 요소들에 대해, 두 요소가 기존에 가지고 있던 순서를 보장한다.

ex ) {1, 5, 4, 5, 3} → sort : {1, 3, 4, 5, 5 } or { 1, 3, 4, 5,  5 } 

먼저 나오는 파란색 5, 그 다음에 나오는 빨간색 5 는 sort함수에 의해 정렬될 때 순서가 기존의 순서로 보장되지 않는다. 결과에 따라 순서가 바뀔 수 있다.

{1, 545, 3} → stable_sort : {1, 3, 4, 5, 5 

기존의 파란색 5가 빨간색 5보단 먼저 온다는 순서가 보장된다. 

 

- 예제

bool cmp(const pair<char, int>& a, const pair<char, int>& b){
    return a.first < b.first;
}

int main(){
    vector<pair<int, int> > vec = { {1, 10}, {5, 3}, {3, 1}, {1, 10} };

    auto address0 = &vec[0];

    std::sort(vec.begin(), vec.end(), cmp); //{1, 10}, {1, 10}, {5, 3}, {3, 1}
    auto address1 = &vec[0];
    auto address2 = &vec[1];

    stable_sort(vec.begin(), vec.end(), cmp); // {1, 10}, {1, 10}, {5, 3}, {3, 1}
    auto address3 = &vec[0];
    auto address4 = &vec[1];
    return 0;
}

sort, stable_sort 둘다 결과는 동일하게 나온다. 

첫번째 인덱스인 {1, 10} 요소가 먼저 나오는지 체크를 해야한다.

주소값을 이용하여 비교하였다.

address3이 기존 순서인 address0과 같다면 순서 보장이 된 것이다.

address1은 기존 순서인 address0과 같을 수도 다를 수도 있다. sort함수는 순서를 보장하지 않기 때문이다.

 

 내부 정렬 알고리즘 차이

sort() Quick
stable_sort() Merge Sort

 

 시간복잡도 차이

sort() 평균적으로 O(N log N) 으로 실행되며 여기서 N = std::distance(first, last) 으로 정의됩니다.
stable_sort() N 을 전달하는 원소의 개수 (N = std::distance(first, last)) 라고 할 때, O(N (log N)^2) 이다. 만일 추가적인 메모리를 사용할 수 있다면 복잡도는 O(N\log N) 으로 줄어든다.
참고로 함수 내부적으로 정렬해야 할 컨테이너와 같은 크기의 메모리를 처음에 할당하려고 한다. 만일 메모리 할당이 성공 한다면 O(Nlog N) 의 속도로 실행이 될 것이고, 실패한다면 조금 느린 버전의 알고리즘이 사용되어 O(N (log N)^2) 으로 정렬된다.

 

 

728x90