선택 정렬, 버블 정렬, 퀵 정렬, 병합 정렬, 삽입 정렬 등등 많은 정렬 알고리즘은 많이 존재합니다.
이를 공부하여 코딩 테스트나 대회 또는 실무에서 활용할 수도 있겠지만 정렬 관련 라이브러리를 사용하는 것이 훨씬 효율적이라는 생각이 듭니다.
그래서 본 포스팅에서는 c++ <algorithm> 헤더파일에 속해 있는 sort() 함수에 대해 다루어 보겠습니다.
sort() 함수
- sort()는 <algorithm> 헤더에 속해 있기때문에 사용하려면 “#include <algorithm>”을 해줘야 합니다.
- 기본적으로 sort(start, end) 형식으로 호출 되는데, 이는 start를 포함하면서 end를 포함하지 않는 바로 직전까지의 구간을 오름차순으로 정렬합니다.
- 평균 시간 복잡도는 O(n log n)이며, 이는 quick sort(퀵 정렬)를 기반하는 intro sort로 구현 되어있기 때문입니다. (최악의 경우에도 O(n log n)을 보장합니다.)
- unstable sort로 중복된 값들의 순서는 정렬하기 전과 다를 수 있습니다.
함수 원형 및 사용법
// 기본 함수 원형
template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);
// 사용자 정의 함수 원형
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
아래와 같이 사용할 수 있습니다.
sort(start, end);
sort(start, end, compare); // 사용자가 정의한 기준으로 정렬, compare는 사용자 정의 함수
sort(start, end, greater<자료형>()); // 내림차순
sort(start, end, less<자료형>()); // 오름차순
두개의 인자 또는 세개의 인자를 넣어서 함수를 호출할 수 있는데,
(start, end) 범위만 넣은 경우 자동으로 오름차순으로,
(start, end, 함수) 세 개 넣은 경우 함수를 기준으로 정렬할 수 있습니다.
예로, “greater<자료형>()” 함수를 넣어 내림차순으로 정렬할 수도 있고, 사용자 정의 함수를 넣어서 사용자가 정한 정렬 기준을 사용할 수도 있습니다.
이제 예제를 통해 하나씩 사용법을 알아보겠습니다.
예제
배열 오름차순, 내림차순 정렬하기
#include <algorithm> // std::sort
#include <iostream>
using namespace std;
// 배열 출력 함수
void printArray(int *arr, const int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
int main() {
const int n = 10;
// 정렬 전
cout << "정렬 전" << endl;
int arr[n] = {3, 9, 2, 6, 1, 5, 7, 8, 0, 4};
printArray(arr, n);
// 오름차순 정렬
cout << "오름차순 정렬 후" << endl;
sort(arr, arr + n);
printArray(arr, n); // 0 1 2 3 4 5 6 7 8 9
// 내림차순 정렬
cout << "내림차순 정렬 후" << endl;
sort(arr, arr + n, greater<int>());
printArray(arr, n); // 9 8 7 6 5 4 3 2 1 0
}
결과값:
주어진 범위에서만 배열을 정렬합니다. 내림차순으로 정렬하려면 “greater<자료형>()” 함수를 세 번째 인자로 넣어주어 더 큰 요소를 앞에 두는 방식으로 비교하게 합니다.
vector 컨테이너 오름차순, 내림차순 정렬하기
#include <algorithm> // std::sort
#include <iostream>
#include <vector>
using namespace std;
// vector 컨테이너 출력 함수
void printVector(vector<int> &v) {
for (int i = 0; i < 10; i++) {
cout << v[i] << " ";
}
cout << endl;
}
int main(void) {
vector<int> v;
const int n = 10;
// vector에 1의자리 숫자를 임의로 삽입
for (int i = 0; i < n; i++) {
v.push_back(rand() % 10);
}
// 정렬 전
cout << "정렬 전" << endl;
printVector(v);
// 오름차순 정렬
cout << "오름차순 정렬 후" << endl;
sort(v.begin(), v.end());
printVector(v);
// 내림차순 정렬
cout << "내림차순 정렬 후" << endl;
sort(v.begin(), v.end(), greater<int>());
printVector(v);
}
결과값:
주어진 범위에서만 vector 컨테이너를 정렬합니다. 내림차순으로 정렬하려면 “greater<자료형>()” 함수를 세 번째 인자로 넣어주어 더 큰 요소를 앞에 두는 방식으로 비교하게 합니다.
사용자 정의 기준으로 정렬하기
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// 학생 객체
// 이름하고 나이를 포함
class Student {
public:
string name;
int age;
Student(string name, int age) : name(name), age(age) {}
};
// 사용자 정의 함수
bool compare(Student a, Student b) {
if (a.name == b.name) { // 이름이 같으면, 나이가 적은순
return a.age < b.age;
} else { // 이름이 다르면, 이름 사전순
return a.name < b.name;
}
}
// vector 컨테이너 출력 함수
void printVector(vector<Student> &v) {
for (int i = 0; i < 5; i++) {
cout << "[" << v[i].name << ", " << v[i].age << "] ";
}
cout << endl;
}
int main(void) {
vector<Student> v;
v.push_back(Student("민호", 10));
v.push_back(Student("현준", 24));
v.push_back(Student("건우", 11));
v.push_back(Student("원준", 8));
v.push_back(Student("민호", 13));
// 정렬 전
cout << "정렬 전" << endl;
printVector(v);
// 사용자 정의 함수로 정렬
cout << "사용자 정의 함수로 정렬" << endl;
sort(v.begin(), v.end(), compare);
printVector(v);
}
결과값:
사용자가 직접 정의하는 자체 비교 함수를 작성하여 세 번째 인자로 넣어줄 수도 있습니다. 이 함수는 “첫 번째” 인자가 “두 번째” 인자 앞에 배치되어야 하는지 bool 값을 반환하여 정렬기준을 전달합니다.
“<” 연산자 오버로딩(Operator Overloading)으로 정렬하기
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// 학생 객체
// 이름하고 나이를 포함
class Student {
public:
string name;
int age;
Student(string name, int age) : name(name), age(age) {}
};
// 연산자 오버로딩 (operator overloading)
bool operator<(Student a, Student b) {
if (a.name == b.name) { // 이름이 같으면, 나이가 적은순
return a.age < b.age;
} else { // 이름이 다르면, 이름 사전순
return a.name < b.name;
}
}
// vector 컨테이너 출력 함수
void printVector(vector<Student> &v) {
for (int i = 0; i < 5; i++) {
cout << "[" << v[i].name << ", " << v[i].age << "]";
}
cout << endl;
}
int main(void) {
vector<Student> v;
v.push_back(Student("민호", 10));
v.push_back(Student("현준", 24));
v.push_back(Student("건우", 11));
v.push_back(Student("원준", 8));
v.push_back(Student("민호", 13));
// 정렬 전
cout << "정렬 전" << endl;
printVector(v);
// 연산자 오버로딩(Operator Overloading)으로 정렬
cout << "연산자 오버로딩(Operator Overloading)으로 정렬" << endl;
sort(v.begin(), v.end());
printVector(v);
}
결과값:
기본적으로 sort() 는 “<” 연산자를 이용하여 값들을 비교해 정렬하는데 연산자 오버로딩을 통해 정렬 기준을 사용자가 원하는 식으로 정의할 수 있습니다. “첫 번째” 인자가 “두 번째” 인자 앞에 배치되어야 하는지 bool 값을 반환하여 정렬기준을 전달합니다.