STL算法---排序算法(一)

23 篇文章 0 订阅
13 篇文章 0 订阅

1. nth_element

将范围内的序列重新排序, 使所有小于等于第n个元素的元素都出现在它前面,而大于它的都出现在后面。
重载版本使用自定义的比较操作
函数原形
template<class RanIt> void nth_element(RanIt first, RanIt nth, RanIt last);
template<class RanIt, class Pred> void nth_element(RanIt first, RanIt nth, RanIt last, Pred pr);
/
#include "stdafx.h"
#include <algorithm>
#include <numeric>
#include <functional>
#include <vector>
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<int> nV2, nV1;
	std::vector<int>::iterator iter;

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(17);	// --
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(11);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(25);
	nV1.push_back(19);
	nV1.push_back(19);

	// 排序前: 14, 16, 15, 17, 10, 13, 11, 27, 24, 25, 19, 19
	std::nth_element(nV1.begin(), nV1.begin() + 3, nV1.end());
	// 排序后: 10, 11, 13, 14, 15, 16, 17, 19, 19, 24, 25, 27
	// 不是很明白!
	return 0;
}
说明:
1. 不是很明白.
2. 网上有这个解析: 例如你需要得到排序后第4位的值, 那么就可以std::nth_element(nV1.begin(), nV1.begin() + 3, nV1.end()); 此时, 第4位肯定是正确的, 其他位不一定正确.
但我测试的都是全排列的.
3. MSDN的解析: 
"The nth_element algorithm does not guarantee that elements in the sub-ranges either side of the nth element are sorted. 
(nth_element算法不保证nth元素两边的子区间是排序的)
It thus makes fewer guarantees than partial_sort, which orders the elements in the range below some chosen element, and may be used as a faster alternative to partial_sort when the ordering of the lower range is not required.
(大概意思是, 如果你想更快速, 而不需要小于区间排序的话, 你可以使用nth_element算法来替换partial_sort算法.)
"

2. partial_sort / partial_sort_copy (部分排序)


2.1 partial_sort

对序列做部分排序, 被排序元素个数正好可以被放到范围内.
重载版本使用自定义的比较操作

函数原形

template<class RanIt> void partial_sort(RanIt first, RanIt middle, RanIt last);
template<class RanIt, class Pred> void partial_sort(RanIt first, RanIt middle, RanIt last, Pred pr);

2.2 partial_sort_copy

与partial_sort类似,不过将经过排序的序列复制到另一个容器
函数原形
template<class InIt, class RanIt> RanIt partial_sort_copy(InIt first1, InIt last1,RanIt first2, RanIt last2);
template<class InIt, class RanIt, class Pred> RanIt partial_sort_copy(InIt first1, InIt last1,RanIt first2, RanIt last2, Pred pr);

说明:
1. partial_sort中middle后面的数据可能是没有排序的, 如果middle等于last, 那就等于做的是全排列.
2. 同理partial_sort_copy, last2后面且last1前面的数据也是没有排序的.
3. 如果[first1, last1)和[first2, last2)的范围大小是一样的partial_sort_copy等于做的是全排列.
/
#include "stdafx.h"
#include <algorithm>
#include <numeric>
#include <functional>
#include <vector>
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<int> nV2, nV1;
	std::vector<int>::iterator iter;

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(11);
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(17);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(25);
	nV1.push_back(19);
	nV1.push_back(19);

	// 排序前: 14, 16, 15, 11, 10, 13, 17, 27, 24, 25, 19, 19
	std::partial_sort(nV1.begin(), nV1.begin() + 3, nV1.end());
	// 排序后: 10, 11, 13, 16(从这里开始没有排序), 15, 14, 17, 27, 24, 25, 19, 19

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(11);
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(17);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(25);
	nV1.push_back(19);
	nV1.push_back(19);
	nV2.resize(nV1.size());
	// 排序前nV1: 14, 16, 15, 11, 10, 13, 17, 27, 24, 25, 19, 19
	iter = std::partial_sort_copy(nV1.begin(), nV1.end(), nV2.begin(), nV2.end());
	// 排序后nV2: 10, 11, 13, 14, 15, 16, 17, 19, 19, 24, 25, 27
	// 排序后nV1: 14, 16, 15, 11, 10, 13, 17, 27, 24, 25, 19, 19, end(iter)

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(11);
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(17);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(25);
	nV1.push_back(19);
	nV1.push_back(19);
	nV2.resize(nV1.size());
	// 排序前nV1: 14, 16, 15, 11, 10, 13, 17, 27, 24, 25, 19, 19
	iter = std::partial_sort_copy(nV1.begin(), nV1.end(), nV2.begin(), nV2.end() - 2);
	// 排序后nV2: 10, 11, 13, 14, 15, 16, 17, 19, 19, 24, 0, 0
	// 排序后nV1: 14, 16, 15, 11, 10, 13, 17, 27, 24, 25(iter), 19, 19

	return 0;
}

3. partition / stable_partition(分类排序)

在[first, last)内, 使用输入的函数,把结果为true的元素放在结果为false的元素之前

3.1 partition

函数原形
template<class BidIt, class Pred> BidIt partition(BidIt first, BidIt last, Pred pr);


3.2 stable_partition

与partition类似, 但了保留容器中的相对顺序
函数原形
template<class FwdIt, class Pred> FwdIt stable_partition(FwdIt first, FwdIt last, Pred pr);

说明:
1. 这里关键就是pr, 把结果为true的元素放在结果为false的元素之前.
2. pr操作符只有一个参数.
3. partition很适合对数据分类(分为两类, 因为只有true和false; 返回的BidIt就是分界线)
4. partition分成两类后, 左边/右边的元素与分类前的相对位置可能会变了.
5. stable_partition分成两类后, 左边/右边的元素与分类前的相对位置不变.
/
#include "stdafx.h"
#include <algorithm>
#include <numeric>
#include <functional>
#include <vector>
#include <iostream>

class MyObject1
{  
public:
	MyObject1(){}
	~MyObject1(){}
	// 括号操作符
    bool operator()(int val1)  
    {  
        return (val1 <= 0);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<int> nV2, nV1;
	std::vector<int>::iterator iter;

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(11);
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(17);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(25);
	nV1.push_back(19);
	nV1.push_back(19);

	// 排序前: 14, 16, 15, 11, 10, 13, 17, 27, 24, 25, 19, 19
	iter = std::partition(nV1.begin(), nV1.end(), MyObject1());
	// 排序后: 14(iter), 16, 15, 11, 10, 13, 17, 27, 24, 25, 19, 19

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(11);
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(-2);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(-1);
	nV1.push_back(19);
	nV1.push_back(19);

	// 排序前: 14, 16, 15, 11, 10, 13, -2, 27, 24, -1, 19, 19
	iter = std::partition(nV1.begin(), nV1.end(), MyObject1());
	// 排序后: -1, -2, 15(iter), 11, 10, 13, 16, 27, 24, 14, 19, 19

	nV1.clear();
	nV1.push_back(14);
	nV1.push_back(16);
	nV1.push_back(15);
	nV1.push_back(11);
	nV1.push_back(10);
	nV1.push_back(13);
	nV1.push_back(-2);
	nV1.push_back(27);
	nV1.push_back(24);
	nV1.push_back(-1);
	nV1.push_back(19);
	nV1.push_back(19);

	// 排序前: 14, 16, 15, 11, 10, 13, -2, 27, 24, -1, 19, 19
	iter = std::stable_partition(nV1.begin(), nV1.end(), MyObject1());
	// 排序后: -2, -1, 14(iter), 16, 15, 11, 10, 13, 27, 24, 19, 19
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值