Effective STL学习笔记-条款31

来源:互联网 发布:微信假红包软件生成器 编辑:程序博客网 时间:2024/06/05 03:35

了解你的排序选择

个人认为掌握并灵活的使用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<Widget> 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 : "<<v.m_value << endl;    }

这里写图片描述
可以看到只是前5个元素进行了排序。这对于大容器很实用。

nth_element

按照文档的解释应该是不关心顺序的得到质量较好的Widget,而partail_sort则关心这个顺序(实际上在我的测试中nth_element也都是排序的状态,不知是否是我理解错误,希望有人可以指出!!!)
这里写图片描述
图片来自于原书

稳定算法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;    }

这里写图片描述

总结

这里写图片描述
另外性能很可能也是我们关注的一点,按照需要更少的资源(时间、空间)排序:

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