在序列中分区元素会重新对元素进行排列,所有使给定谓词返回 true 的元素会被放在所有使谓词返回 false 的元素的前面。这就是 std::partition和std::stable_partition算法所做的事。
从名字上就可以看得出来 std::partition是不稳定的,而std::stable_partition是稳定的。
代码示例一:
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>
using namespace std;
bool above40(int n) { return (n > 40); }
int main()
{
cout << "Illustrating the generic partition and stable_partition algorithms." << endl;
const int N = 7;
int arrary0[N] = { 50, 30, 10, 70, 60, 40, 20 };
int arrary1[N];
copy(&arrary0[0], &arrary0[N], &arrary1[0]);
ostream_iterator<int> out(cout, " ");
cout << "Original sequence: ";
copy(&arrary1[0], &arrary1[N], out);
cout << endl;
int* split = partition(&arrary1[0], &arrary1[N], above40);
cout << "Result of (unsatable) partitioning: ";
copy(&arrary1[0], split, out);
cout << "| ";
copy(split, &arrary1[N], out);
cout << endl;
split = stable_partition(&arrary0[0], &arrary0[N], above40);
cout << "Result of (stable_partition) partitioning: ";
copy(&arrary0[0], split, out);
cout << "| ";
copy(split, &arrary0[N], out);
cout << endl;
getchar();
return 0;
}
运行结果:
Illustrating the generic partition and stable_partition algorithms.
Original sequence: 50 30 10 70 60 40 20
Result of (unsatable) partitioning: 50 60 70 | 10 30 40 20
Result of (stable_partition) partitioning: 50 70 60 | 30 10 40 20
说明的一点是std::partition和std::stable_partition都会重排序范围 [first, last) 中的元素,所以将arrary0[N]复制了一份到arrary1[N];然后对在arrary1[N]上进行std::partition划分,对arrary0[N]上进行std::stable_partition划分。
代码示例二:
#include <algorithm>
#include <vector>
#include <iostream>
#include <iterator>
int main()
{
std::vector<int> vec0{ 50, 30, 10, 70, 60, 40, 20 };
std::vector<int> vec1(vec0); //将vec0拷贝一份到vec1
std::cout << "Orginal vector: ";
std::copy(vec0.begin(), vec0.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::cout << "Result of (unsatable) partitioning: ";
auto it = std::partition(vec0.begin(), vec0.end(), [](int i) {return i > 40; });
std::copy(std::begin(vec0), it, std::ostream_iterator<int>(std::cout, " "));
std::cout << "| ";
std::copy(it, std::end(vec0), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::cout << "Result of (stable_partition) partitioning: ";
it = std::stable_partition(vec1.begin(), vec1.end(), [](int i) {return i > 40; });
std::copy(std::begin(vec1), it, std::ostream_iterator<int>(std::cout, " "));
std::cout << "| ";
std::copy(it, std::end(vec1), std::ostream_iterator<int>(std::cout, " "));
getchar();
return 0;
}
将序列容器划分成大于40和小于40的部分,分别采用std::partition和std::stable_partition的算法进行划分。
运行结果:
Orginal vector: 50 30 10 70 60 40 20
Result of (unsatable) partitioning: 50 60 70 | 10 30 40 20
Result of (stable_partition) partitioning: 50 70 60 | 30 10 40 20
官方的例子:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <forward_list>
template <class ForwardIt>
void quicksort(ForwardIt first, ForwardIt last)
{
if(first == last) return;
auto pivot = *std::next(first, std::distance(first,last)/2);
ForwardIt middle1 = std::partition(first, last,
[pivot](const auto& em){ return em < pivot; });
ForwardIt middle2 = std::partition(middle1, last,
[pivot](const auto& em){ return !(pivot < em); });
quicksort(first, middle1);
quicksort(middle2, last);
}
int main()
{
std::vector<int> v = {0,1,2,3,4,5,6,7,8,9};
std::cout << "Original vector:\n ";
for (int elem : v)
std::cout << elem << ' ';
auto it = std::partition(v.begin(), v.end(), [](int i){return i % 2 == 0;});
std::cout << "\nPartitioned vector:\n ";
std::copy(std::begin(v), it, std::ostream_iterator<int>(std::cout, " "));
std::cout << " * ";
std::copy(it, std::end(v), std::ostream_iterator<int>(std::cout, " "));
std::forward_list<int> fl = {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};
std::cout << "\nUnsorted list:\n ";
for (int n : fl)
std::cout << n << ' ';
std::cout << '\n';
quicksort(std::begin(fl), std::end(fl));
std::cout << "Sorted using quicksort:\n ";
for(int fi : fl) std::cout << fi << ' ';
std::cout << '\n';
}
运行结果:
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
参考:
https://zh.cppreference.com/w/cpp/algorithm/partition
https://zh.cppreference.com/w/cpp/algorithm/stable_partition
https://zh.cppreference.com/w/cpp/algorithm/copy
https://zh.cppreference.com/w/cpp/iterator/ostream_iterator
https://zh.cppreference.com/w/cpp/algorithm/accumulate