문제
특정 값을 기준으로 배열을 두개의 영역으로 분할하려고 한다. 특정값을 pivot이라고 하자. pivot을 기준으로 pivot보다 작은 값들과 pivot보다 큰값들이 모인 영역으로 배열을 분할한다.
아이디어
구현의 편의상 배열의 맨 끝 원소를 pivot으로 삼는다. pivot보다 작지만 가장 마지막에 배치 된 원소의 인덱스를 i, 배열을 순회하는 인덱스를 j, 배열의 첫번째 인덱스를 lo, 마지막 index를 hi라고 하자.
- 포인터 j가 배열 전체를 순회한다.
- j가 가리키는 값이 pivot보다 작다면 i를 값을 1만큼 증가한 후에 j의 값과 교체한다. 교체 후에 j를 전진시킨다.
- j가 가리키는 값이 pivot보다 크다면 j를 전진시킨다.
- j가 pivot에 도달할 때까지 반복한다.
- j가 pivot에 도달하면 i + 1 번째 원소와 위치를 교체한다.
pivot이 위치를 교체한 결과, pivot의 왼쪽은 pivot보다 작은 값들이, pivot의 오른쪽에는 pivot보다 큰 값들이 모여있다. 양 영역이 반드시 정렬되어 있는 것은 아니다.
구현
#include <iostream>
#include <vector>
using namespace std;
void Print(vector<int> &arr) {
for (int i = 0; i < arr.size(); i++)
cout << arr[i] << " ";
cout << endl;
}
int main() {
vector<int> arr = {5, 2, 7, 3, 8, 5, 6, 4};
// vector<int> arr = { 2, 8, 7, 1, 3, 5, 6, 4 };
// vector<int> arr = { 9, 8, 7, 6, 4, 3, 2, 1, 5 };
// vector<int> arr = { 5, 2, 7, 3, 4, 4, 6, 4 };
int lo = 0; // 첫 인덱스
int hi = arr.size() - 1; // 마지막 인덱스
int x = arr[hi]; // 분할 기준으로 사용하는 pivot 4
int i = lo - 1; // pivot보다 것들중 가장 큰 인덱스
Print(arr);
// REVIEW
for (int k = lo; k < hi; k++) { // i: 현재 검사하는 위치
if (arr[k] <= x) {
swap(arr[k], arr[++i]);
}
}
swap(arr[i + 1], arr[hi]);
Print(arr);
cout << i + 1 << endl; // 피벗 이하인 값들의 마지막 인덱스
}