C++11新特性应用--介绍几个新增的便利算法(用于分区的几个算法)

今天继续。

C++11新增的关于Non-modifying sequence operations和Modifying sequence operations的算法已经写了,详细信息见之前的博客。

下面开始C++11新增的关于Partitions的算法:

Partitions:即分区的意思。

很多人可能还不熟悉partition,所以先说一说partition算法,需要说明的是这不是C++11新增的内容。但为了更方便大家理解,还是先写一写std::partition。

std::partition

原型:

template <class ForwardIterator, class UnaryPredicate>
  ForwardIterator partition (ForwardIterator first,
                             ForwardIterator last, UnaryPredicate pred);

作用:

Rearranges the elements from the range [first,last), in such a way that all the elements for which pred returns true precede all those for which it returns false. The iterator returned points to the first element of the second group.

需要注意一下返回值:

An iterator that points to the first element of the second group of elements (those for which pred returns false), or last if this group is empty

返回的迭代器是指向第二个区间的第一个元素!!!

应用:

#include <iostream>     // std::cout
#include <algorithm>    // std::partition
#include <vector>       // std::vector

bool IsOdd(int i) { return (i % 2) == 1; }

int main() {
    std::vector<int> myvector;

    // set some values:
    for (int i = 1; i<10; ++i)
        myvector.push_back(i); // 1 2 3 4 5 6 7 8 9

    std::vector<int>::iterator bound;
    bound = std::partition(myvector.begin(), myvector.end(), IsOdd);

    // print out content:
    std::cout << "odd elements:";
    for (std::vector<int>::iterator it = myvector.begin(); it != bound; ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "even elements:";
    for (std::vector<int>::iterator it = bound; it != myvector.end(); ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "Now myvector is: ";
    for (auto it = myvector.begin(); it != myvector.end(); it++)
    {
        std::cout << ‘ ‘ << *it;
    }
    std::cout << std::endl;

    return 0;
}
//输出:
//odd elements : 1 9 3 7 5
//even elements : 6 4 8 2
//Now myvector is : 1 9 3 7 5 6 4 8 2

我们是想按照奇数偶数进行分组,目的达到了。但是还不够完美,因为每个分区部分的元素与之前相比,相对位置变化了。

这个时候,就需要更稳定的算法了,直接上代码了,运行结果对比的非常明显:

stable_partition

#include <iostream>     // std::cout
#include <algorithm>    // std::partition
#include <vector>       // std::vector

bool IsOdd(int i) { return (i % 2) == 1; }

int main() {
    std::vector<int> myvector;

    // set some values:
    for (int i = 1; i<10; ++i)
        myvector.push_back(i); // 1 2 3 4 5 6 7 8 9

    std::vector<int>::iterator bound;
    bound = std::partition(myvector.begin(), myvector.end(), IsOdd);

    // print out content:
    std::cout << "odd elements:";
    for (std::vector<int>::iterator it = myvector.begin(); it != bound; ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "even elements:";
    for (std::vector<int>::iterator it = bound; it != myvector.end(); ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "Now myvector is: ";
    for (auto it = myvector.begin(); it != myvector.end(); it++)
    {
        std::cout << ‘ ‘ << *it;
    }
    std::cout << std::endl;

    std::cout << "Now let us " << std::endl;
    std::vector<int> myvector2;

    // set some values:
    for (int i = 1; i<10; ++i)
        myvector2.push_back(i); // 1 2 3 4 5 6 7 8 9

    std::vector<int>::iterator bound2;
    bound2 = std::stable_partition(myvector2.begin(), myvector2.end(), IsOdd);

    // print out content:
    std::cout << "odd elements:";
    for (std::vector<int>::iterator it = myvector2.begin(); it != bound2; ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "even elements:";
    for (std::vector<int>::iterator it = bound2; it != myvector2.end(); ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "Now myvector is: ";
    for (auto it = myvector2.begin(); it != myvector2.end(); it++)
    {
        std::cout << ‘ ‘ << *it;
    }
    std::cout << std::endl;

    return 0;
}
//输出:
//odd elements : 1 9 3 7 5
//even elements : 6 4 8 2
//Now myvector is : 1 9 3 7 5 6 4 8 2
//Now let us
//odd elements : 1 3 5 7 9
//even elements : 2 4 6 8
//Now myvector is : 1 3 5 7 9 2 4 6 8

现在开始介绍C++11新增的。

is_partitioned

原型:

template <class InputIterator, class UnaryPredicate>
  bool is_partitioned (InputIterator first, InputIterator last, UnaryPredicate pred);

作用:

Test whether range is partitioned

Returns true if all the elements in the range [first,last) for which pred returns true precede those for which it returns false.

应用:

#include <iostream>     // std::cout
#include <algorithm>    // std::partition
#include <vector>       // std::vector

bool IsOdd(int i) { return (i % 2) == 1; }

int main() {
    std::vector<int> myvector;

    // set some values:
    for (int i = 1; i<10; ++i)
        myvector.push_back(i); // 1 2 3 4 5 6 7 8 9

    std::vector<int>::iterator bound;
    bound = std::partition(myvector.begin(), myvector.end(), IsOdd);

    // print out content:
    std::cout << "odd elements:";
    for (std::vector<int>::iterator it = myvector.begin(); it != bound; ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "even elements:";
    for (std::vector<int>::iterator it = bound; it != myvector.end(); ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "Now myvector is: ";
    for (auto it = myvector.begin(); it != myvector.end(); it++)
    {
        std::cout << ‘ ‘ << *it;
    }
    std::cout << std::endl;

    std::cout << "Now let us use stable_partition:" << std::endl;
    std::vector<int> myvector2;

    // set some values:
    for (int i = 1; i<10; ++i)
        myvector2.push_back(i); // 1 2 3 4 5 6 7 8 9

    std::vector<int>::iterator bound2;
    bound2 = std::stable_partition(myvector2.begin(), myvector2.end(), IsOdd);

    // print out content:
    std::cout << "odd elements:";
    for (std::vector<int>::iterator it = myvector2.begin(); it != bound2; ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "even elements:";
    for (std::vector<int>::iterator it = bound2; it != myvector2.end(); ++it)
        std::cout << ‘ ‘ << *it;
    std::cout << ‘\n‘;

    std::cout << "Now myvector is: ";
    for (auto it = myvector2.begin(); it != myvector2.end(); it++)
    {
        std::cout << ‘ ‘ << *it;
    }
    std::cout << std::endl;

    std::cout << "Now, let us use is_partitioned on myvector2:" << std::endl;
    if (std::is_partitioned(myvector2.begin(), myvector2.end(), IsOdd))
        std::cout << " (partitioned)\n";
    else
        std::cout << " (not partitioned)\n";

    std::cout << "Now, let us use  is_partitioned on en empty vector:" << std::endl;
    std::vector<int> myvector3;
    if (std::is_partitioned(myvector3.begin(), myvector3.end(), IsOdd))
        std::cout << " (partitioned)\n";
    else
        std::cout << " (not partitioned)\n";

    return 0;
}
//输出:
odd elements : 1 9 3 7 5
even elements : 6 4 8 2
Now myvector is : 1 9 3 7 5 6 4 8 2
Now let us use stable_partition :
odd elements : 1 3 5 7 9
even elements : 2 4 6 8
Now myvector is : 1 3 5 7 9 2 4 6 8
Now, let us use is_partitioned on myvector2 :
(partitioned)
Now, let us use  is_partitioned on en empty vector :
(partitioned)

从输出结果看,我们需要明确:

If the range is empty, the function returns true.

上面的几个算法,不管如何折腾,都是在一个vector进行的,结果也还是在一个vector中,于是C++11新增了这个:

partition_copy

原型:

template <class InputIterator, class OutputIterator1,
          class OutputIterator2, class UnaryPredicate pred>
  pair<OutputIterator1,OutputIterator2>
    partition_copy (InputIterator first, InputIterator last,
                    OutputIterator1 result_true, OutputIterator2 result_false,
                    UnaryPredicate pred);

作用:

Copies the elements in the range [first,last) for which pred returns true into the range pointed by result_true, and those for which it does not into the range pointed by result_false.

应用:

#include <iostream>     // std::cout
#include <algorithm>    // std::partition_copy, std::count_if
#include <vector>       // std::vector

bool IsOdd(int i) { return (i % 2) == 1; }

int main() {
    std::vector<int> foo{ 1,2,3,4,5,6,7,8,9 };
    std::vector<int> odd, even;

    // resize vectors to proper size:
    unsigned n = std::count_if(foo.begin(), foo.end(), IsOdd);
    odd.resize(n); even.resize(foo.size() - n);

    // partition:
    std::partition_copy(foo.begin(), foo.end(), odd.begin(), even.begin(), IsOdd);

    // print contents:
    std::cout << "odd: ";  for (int& x : odd)  std::cout << ‘ ‘ << x; std::cout << ‘\n‘;
    std::cout << "even: "; for (int& x : even) std::cout << ‘ ‘ << x; std::cout << ‘\n‘;

    return 0;
}
//输出:
//odd:  1 3 5 7 9
//even : 2 4 6 8

接下来剩最后一个:

partition_point

从算法名字就能略知一二,于是直接上代码示例:

#include <iostream>     // std::cout
#include <algorithm>    // std::partition, std::partition_point
#include <vector>       // std::vector

bool IsOdd(int i) { return (i % 2) == 1; }

int main() {
    std::vector<int> foo{ 1,2,3,4,5,6,7,8,9 };
    std::vector<int> foo2{ 1,2,3,4,5,6,7,8,9 };
    std::vector<int> odd;
    std::vector<int> odd2;

    std::partition(foo.begin(), foo.end(), IsOdd);

    auto it = std::partition_point(foo.begin(), foo.end(), IsOdd);
    odd.assign(foo.begin(), it);

    auto bound = std::partition(foo2.begin(), foo2.end(), IsOdd);
    for (std::vector<int>::iterator it = foo2.begin(); it != bound; ++it)
        odd2.push_back(*it);
    //odd2.assign(foo.begin(), bound);

    // print contents of odd:
    std::cout << "odd:";
    for (int& x : odd) std::cout << ‘ ‘ << x;
    std::cout << ‘\n‘;

    std::cout << "odd2:";
    for (int& x : odd2) std::cout << ‘ ‘ << x;
    std::cout << ‘\n‘;

    return 0;
}

因此:

partition_point

Returns an iterator to the first element in the partitioned range [first,last) for which pred is not true, indicating its partition point.

个人觉得这个算法用处不大。

个人觉得主要应用于已经partition的range上还算有优势!

时间: 2025-01-02 09:27:45

C++11新特性应用--介绍几个新增的便利算法(用于分区的几个算法)的相关文章

C++11新特性应用--介绍几个新增的便利算法(stl中的heap使用,最大堆)

有的时候为了维护数据,我们使用stl的堆去维护一序列. 首先您要弄清楚堆和栈的区别,即heap和stack stl中的堆默认是最大堆. 先介绍 push_heap,pop_heap,make_heap,sort_heap这四个算法,这四个不是C++11新增加的内容. 首先是如何产生一个最大推: make_heap 原型: template <class RandomAccessIterator> void make_heap (RandomAccessIterator first, Rando

C++11新特性应用--介绍几个新增的便利算法(更改容器中元素顺序的算法)

昨天罗列了C++11中新增的几个算法,包括 find_if_not.all_of.any_of.none_of四个算法,这四个算法的共同点就是Non-modifying sequence operations. 所以,今天就来八一八C++11中新增的算法,而这些算法的特点是:Modifying sequence operations. copy算法我们很熟悉,这里介绍一下C++11新增的copy_n. copy_n 原型: template <class InputIterator, class

C++11新特性应用--介绍几个新增的便利算法(不更改容器中元素顺序的算法)

总所周知,C++ STL中有个头文件,名为algorithm,即算法的意思. The header<algorithm>defines a collection of functions especially designed to be used on ranges of elements. 所以,要八一八这个头文件中C++11新增的几个算法,今天主要描述的几个算法不改变容器中元素的顺序. 这里还要啰嗦一句,使用stl算法时,如果与lambda表达式组合使用,那么代码会更加简洁. find_

C++11新特性应用--介绍几个新增的便利算法(用于排序的几个算法)

继续C++11在头文件algorithm中添加的算法. 至少我认为,在stl的算法中,用到最多的就是sort了,我们不去探索sort的源代码.就是介绍C++11新增的几个关于排序的函数. 对于一个序列,我们怎么知道他是不是有序的呢?这就用到了: is_sorted 原型: template <class ForwardIterator> ForwardIterator is_sorted_until (ForwardIterator first, ForwardIterator last);

Java 11 新特性介绍

Java 11 已于 2018 年 9 月 25 日正式发布,之前在Java 10 新特性介绍中介绍过,为了加快的版本迭代.跟进社区反馈,Java 的版本发布周期调整为每六个月一次——即每半年发布一个大版本,每个季度发布一个中间特性版本,并且做出不会跳票的承诺.通过这样的方式,Java 开发团队能够将一些重要特性尽早的合并到 Java Release 版本中,以便快速得到开发者的反馈,避免出现类似 Java 9 发布时的两次延期的情况. 按照官方介绍,新的版本发布周期将会严格按照时间节点,于每年

C++11新特性:自动类型推断和类型获取

声明:本文是在Alex Allain的文章http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html的基础上写成的. 加入了很多个人的理解,不是翻译. 转载请注明出处 http://blog.csdn.net/srzhz/article/details/7934483 自动类型推断 当编译器能够在一个变量的声明时候就推断出它的类型,那么你就能够用auto关键字来作为他们的类型: [c

C++11新特性:Lambda函数(匿名函数)

声明:本文参考了Alex Allain的文章http://www.cprogramming.com/c++11/c++11-lambda-closures.html 加入了自己的理解,不是简单的翻译 C++11终于知道要在语言中加入匿名函数了.匿名函数在很多时候可以为编码提供便利,这在下文会提到.很多语言中的匿名函数,如C++,都是用Lambda表达式实现的.Lambda表达式又称为lambda函数.我在下文中称之为Lambda函数. 为了明白Lambda函数的用处,请务必先搞明白C++中的自动

C++培训 C++11新特性:杂项

C++培训之前小编给大家总结了一些C++的新特性,这一篇文章是介绍的C++11新特性之杂项,在后面的文章中,小编还会给大家总结一些C++11新特性的知识出来! 类型别名声明 类似typedef,新标准中可以使用using为类型声明一个别名(alias). std::cout<<"test using alias:\n"; using HT = double; using NAME = std::string; HT h = 1.78; NAME name = "R

C++:C++11新特性超详细版(1)

前言: 虽然目前没有编译器能够完全实现C++11,但这并不意味着我们不需要了解,学习它.深入学习C++11,你会发现这根本就是一门新的语言,它解决了c++98中许多遗留下来的问题.早晚会有一天,C++11便会普及大部分编译器.因此,提早做些准备也是应该的. 在此我想做一个关于C++11的专题,将C++11的新特性进行一一讲解,以通俗易懂的语言及例子帮助读者入门C++11.本文便是C++11新特性超详细版系列文章的第一篇, 即C++:[C++11]新特性超详细版(1). 不过我要强调的是,这些文章