STL算法之std::partition和std::stable_partition的使用

在序列中分区元素会重新对元素进行排列,所有使给定谓词返回 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

C++ partition(STL partition)算法使用详解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值