Effective STL学习笔记-条款31

了解你的排序选择

个人认为掌握并灵活的使用stl的算法,对我们c++编程有着事半功倍的效果,排序算法的使用和掌握更加重要。

使用的最多的算法可能就是sort了,或者qsort(条款46的存在可能会让更多人倾向于使用sort而不是qsort)。例如有一个Widget的Vector,你需要挑选出Widget质量最好5个,剩下的可以保持无序。
这时候我们不需要完全排序,sort显得有些浪费。
而partail_sort可以胜任这个目标:

partail_sort

struct Widget
{
    Widget(int value) :m_value(value) {}
    int m_value;
};

    vector vec = 
    {   Widget(0),
        Widget(11),
        Widget(12),
        Widget(3),
        Widget(8),
        Widget(6),
        Widget(2),
        Widget(1),
        Widget(8),
        Widget(7),
        Widget(10),
        Widget(9) 
    };

    std::partial_sort(vec.begin(), vec.begin() +5, vec.end(), [](const Widget& lhs, const Widget& rhs)
    {
        return rhs.m_value < lhs.m_value;
    });
    for (auto v : vec)
    {
        cout << " element : "<

Effective STL学习笔记-条款31_第1张图片
可以看到只是前5个元素进行了排序。这对于大容器很实用。

nth_element

按照文档的解释应该是不关心顺序的得到质量较好的Widget,而partail_sort则关心这个顺序(实际上在我的测试中nth_element也都是排序的状态,不知是否是我理解错误,希望有人可以指出!!!)
Effective STL学习笔记-条款31_第2张图片
图片来自于原书

稳定算法stable_sort

稳定的含义就是例如:未排序的时候A在B之前并且两者质量相同,在排序之后A依旧会在B之前,而partail_sort、nth_element不关心这个顺序。

排序用法

  1. 比如我们想要获取中间值的大小
  2. 获取75%的大小
  3. 第二大的值
    等等。
    以下给出简单示例,没有其他的安全判断,供参考。
    std::nth_element(vec.begin(), vec.begin() + vec.size() / 2, vec.end(), [](const Widget& lhs, const Widget& rhs)
        {
            return rhs.m_value < lhs.m_value;
        });
    cout << " min value : " << vec[vec.size() / 2].m_value << endl;
    std::nth_element(vec.begin(), vec.begin() + vec.size() * 0.25, vec.end(), [](const Widget& lhs, const Widget& rhs)
        {
            return rhs.m_value < lhs.m_value;
        });
    cout << " 75% value : " << vec[vec.size() * 0.25].m_value << endl;
    std::nth_element(vec.begin(), vec.begin() + 1, vec.end(), [](const Widget& lhs, const Widget& rhs)
        {
            return rhs.m_value < lhs.m_value;
        });
    cout << " second value : " << vec[1].m_value << endl;

partition

有时候你需要质量等级为10级以上的Widget,而其他的属于不合格的。如果使用sort等,你需要排序并找到第一个不符合要求的位置,这样略嫌麻烦。而partition实现的功能就是分开符合某一标准的元素都在区间开头。

    auto iterGoodEnd = std::partition(vec.begin(), vec.end(), [=](const Widget& item)
    {
        return item.m_value > 10;
    });
    auto iterBegin = vec.begin();
    while (iterBegin != iterGoodEnd)
    {
        cout << (*iterBegin).m_value << endl;
        ++iterBegin;
    }

这里写图片描述

总结

Effective STL学习笔记-条款31_第3张图片
另外性能很可能也是我们关注的一点,按照需要更少的资源(时间、空间)排序:

  1. partition
  2. stable_partition
  3. nth_element
  4. partition_sort
  5. sort
  6. stable_sort

你可能感兴趣的:(C++)