파티셔닝 알고리즘 (Partitioning Algorithm)
-
partition 범위 내 원소들을 주어진 함수에 의해 두 그룹으로 나눔.
-
partition_copy 두 그룹으로 나뉘어진 원소들을 복사. (원본 유지)
-
// until C++11
template< class BidirIt, class UnaryPredicate >
BidirIt partition( BidirIt first, BidirIt last, UnaryPredicate p );
// since C++11 until C++20
template< class ForwardIt, class UnaryPredicate >
ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );
template< class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate >
std::pair<OutputIt1, OutputIt2>
partition_copy( InputIt first, InputIt last,
OutputIt1 d_first_true, OutputIt2 d_first_false,
UnaryPredicate p );
// since C++20
template< class ForwardIt, class UnaryPredicate >
constexpr ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );
template< class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate >
constexpr std::pair<OutputIt1, OutputIt2>
partition_copy( InputIt first, InputIt last,
OutputIt1 d_first_true, OutputIt2 d_first_false,
UnaryPredicate p );
// since C++17
template< class ExecutionPolicy, class ForwardIt, class UnaryPredicate >
ForwardIt partition( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, UnaryPredicate p );
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class ForwardIt3,
class UnaryPredicate >
std::pair<ForwardIt2, ForwardIt3>
partition_copy( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last,
ForwardIt2 d_first_true, ForwardIt3 d_first_false,
UnaryPredicate p );
// ----------------------------------------------------------------------------------
#include <iostream>
#include <vector>
#include <forward_list>
#include <algorithm>
#include <iterator>
using namespace std;
template <class ForwardIt>
void quicksort(ForwardIt first, ForwardIt last) {
if(first == last) return;
auto pivot = *next(first, distance(first,last)/2);
ForwardIt middle1 = partition(
first, last, [pivot](const auto& em){ return em < pivot; });
ForwardIt middle2 = partition(
middle1, last, [pivot](const auto& em){ return !(pivot < em); });
quicksort(first, middle1);
quicksort(middle2, last);
}
int main() {
vector<int> v = {0,1,2,3,4,5,6,7,8,9};
cout << "Original vector:\n ";
for(int elem : v) cout << elem << ' ';
auto it = partition(v.begin(), v.end(), [](int i){return i % 2 == 0;});
cout << endl << "Partitioned vector:\n ";
copy(begin(v), it, ostream_iterator<int>(cout, " "));
cout << " * ";
copy(it, end(v), ostream_iterator<int>(cout, " "));
forward_list<int> fl = {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};
cout << endl << "Unsorted list:\n ";
for(int n : fl) cout << n << ' ';
cout << endl;
quicksort(begin(fl), end(fl));
cout << "Sorted using quicksort:\n ";
for(int fi : fl) cout << fi << ' ';
cout << endl;
cout << "Call partition_copy():" << endl;
int arr [10] = {1,2,3,4,5,6,7,8,9,10};
int true_arr [5] = {0};
int false_arr [5] = {0};
cout << "Before: ";
for (int n : arr) cout << n << " ";
cout << endl;
partition_copy(begin(arr), end(arr), begin(true_arr), begin(false_arr),
[] (int i) {return i > 5;});
cout << "true_arr: ";
for (int x : true_arr) cout << x << ' ';
cout << endl;
cout << "false_arr: ";
for (int x : false_arr) cout << x << ' ';
cout << endl;
return 0;
}
/*
$ g++ test.cpp -std=c++14
$ ./a.out
Original vector:
0 1 2 3 4 5 6 7 8 9
Partitioned vector:
0 8 2 6 4 * 5 3 7 1 9
Unsorted list:
1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92
Sorted using quicksort:
-8 -5 -4 -4 1 1 1 2 3 5 6 30 64 92
Call partition_copy():
Before: 1 2 3 4 5 6 7 8 9 10
true_arr: 6 7 8 9 10
false_arr: 1 2 3 4 5
*/
-
is_partition 두 그룹이 주어진 함수에 의해 나뉘어져 있으면 true, 그렇지 않으면 false 반환.
// since C++11 until C++20
template< class InputIt, class UnaryPredicate >
bool is_partitioned( InputIt first, InputIt last, UnaryPredicate p );
// since C++20
template< class InputIt, class UnaryPredicate >
constexpr bool is_partitioned( InputIt first, InputIt last, UnaryPredicate p );
// since C++17
template< class ExecutionPolicy, class ForwardIt, class UnaryPredicate >
bool is_partitioned( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
UnaryPredicate p );
// ----------------------------------------------------------------------------------
#include <iostream>
#include <array>
#include <algorithm>
using namespace std;
int main() {
array<int, 9> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto is_even = [](int i){ return i % 2 == 0; };
cout.setf(ios_base::boolalpha);
cout << is_partitioned(v.begin(), v.end(), is_even) << ' ';
partition(v.begin(), v.end(), is_even);
cout << is_partitioned(v.begin(), v.end(), is_even) << ' ';
reverse(v.begin(), v.end());
cout << is_partitioned(v.cbegin(), v.cend(), is_even) << ' ';
cout << is_partitioned(v.crbegin(), v.crend(), is_even) << endl;
return 0;
}
/*
$ g++ test.cpp -std=c++11
$ ./a.out
false true false true
*/
-
stable_partition 상대적 순서를 유지한 상태로 두 그룹으로 나눔.
template< class BidirIt, class UnaryPredicate >
BidirIt stable_partition( BidirIt first, BidirIt last, UnaryPredicate p );
// since C++17
template< class ExecutionPolicy, class BidirIt, class UnaryPredicate >
BidirIt stable_partition( ExecutionPolicy&& policy, BidirIt first, BidirIt last,
UnaryPredicate p );
// ----------------------------------------------------------------------------------
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> v{0, 0, 3, 0, 2, 4, 5, 0, 7};
stable_partition(v.begin(), v.end(), [](int n){return n>0;});
for (int n : v) cout << n << ' ';
cout << endl;
return 0;
}
/*
$ g++ test.cpp -std=c++11
$ ./a.out
3 2 4 5 7 0 0 0 0
*/
-
partition_point 두 그룹으로 나뉜 상태에서 첫번째 파티션이 끝나는 위치의 iterator를 반환.
// since C++11 until C++20
template< class ForwardIt, class UnaryPredicate >
ForwardIt partition_point( ForwardIt first, ForwardIt last, UnaryPredicate p );
// since C++20
template< class ForwardIt, class UnaryPredicate >
constexpr ForwardIt partition_point( ForwardIt first, ForwardIt last,
UnaryPredicate p );
// ----------------------------------------------------------------------------------
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
using namespace std;
int main() {
array<int, 9> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto is_even = [](int i){ return i % 2 == 0; };
partition(v.begin(), v.end(), is_even);
auto p = partition_point(v.begin(), v.end(), is_even);
cout << "Before partition:\n ";
copy(v.begin(), p, ostream_iterator<int>(cout, " "));
cout << endl << "After partition:\n ";
copy(p, v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
/*
$ g++ test.cpp -std=c++11
$ ./a.out
Before partition:
8 2 6 4
After partition:
5 3 7 1 9
*/
'Programming Language > C++' 카테고리의 다른 글
표준 템플릿 라이브러리(STL) - 이진 탐색 알고리즘 (0) | 2020.11.20 |
---|---|
표준 템플릿 라이브러리(STL) - 정렬 알고리즘 (0) | 2020.11.20 |
표준 템플릿 라이브러리(STL) - 변경 가능 알고리즘 (0) | 2020.11.20 |
표준 템플릿 라이브러리(STL) - 변경 불가 알고리즘 (0) | 2020.11.19 |
표준 템플릿 라이브러리(Standard Template Library) (0) | 2020.11.17 |