Effective STL 学习笔记 31:排序算法

1 partial_sort

partial sort 能够进行部分排序,例如,仅 按顺序排出 某个容器中的前 20 名: css

bool qualityCompare(const Widget& lhs, const Widget& rhs);

partial_sort(widgets.begin(), widgets.begin()+20, widgets.end(), qualityCompare);

2 nth_element

与 partial_sort 相似, nth_element 也用于部分排序,但它只保证指定的排名前 N 个元素会存放到容器的前N,但这前 N 个元素之间的顺序不必定。更重要的是,它能够保证,若是咱们对容器进行彻底排序,排在 N 位置的那个元素必定和 nth_element 排序后 N 位置的元素相同(等值): java

nth_element(widgets.begin(),
            widgets.begin()+20,
            widgets.end(),
            qualityCompare);

此外, nth_element 能够方便地计算出指定容器中指定排名的元素: ios

vector<Widget>::size_type goalOffset = 0.21 * widgets.size();
nth_element(begin, begin+goalOffset, end, qualityCompare);

3 stability

对于任意的等价对象 AB ,若是 A 在容器中的位置比 B 靠前,且排序后 A 的位置仍然在 B 以前,则称该排序算法为稳定的 (stable) 。 partial_sortnth_element 都不是稳定的,但算法 stable_sort 能够保证这一点。 c++

4 partition

partition 能够将对 Sequence Container 进行排序,排序完成后返回的迭代器指向知足条件的最后一个元素: 算法

bool HasAcceptableQuality(const Widget& w);

vector<Widget>::iterator goodEnd =
        partition(widgets.begin(),
                  widgets.end(),
                  HasAcceptableQuality);

当上述表达式完成以后,返回的 goodEnd 指向了知足 HasAcceptableQuality 的最后一个元素,算法不保证 goodEnd 以前的元素顺序,但 stable_partition 能够保证 stability. sql

5 总结

  • 须要对 vector, string, dequeu, array 进行彻底排序 \(\rightarrow sort/stable\_sort\)
  • 须要从 vector, string, dequeu, array 中获取排好序的前 N 个元素:\(\rightarrow partial\_sort\)
  • 须要从 vector, string, dequeu, array 中获取无序的前 N 名或者指定的第 N 名: \(\rightarrow nth\_element\)
  • 须要从顺序容器中获取符合某种条件的全部元素: \(\rightarrow partition/stable\_partition\)
  • 须要对 List 进行排序,最好使用 List 自己的相关函数,或者将 List 转换成 vector 再使用 STL 算法。

上述各类算法的效率: bash

\(partition > stable\_partition > nth_element > partial\_sort > sort > stable\_sort\) less

#include <vector>
#include <algorithm>
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <stdlib.h>
#include <sys/time.h>

using namespace std;

#define N       1000000

typedef unsigned int   uint32;

static inline uint32 current_time_ms()
{
    struct timeval tv;
    return (gettimeofday(&tv, NULL) != -1) ? \
            tv.tv_sec * 1000 + tv.tv_usec / 1000 : 0;
}

#define show(s,e)           copy(s, e, os); cout << endl ;

#define nth(v, N)       *(v.begin()+N-1)

bool PartitionCond(int& i)
{
    return i < 50;
}

int main(int argc, char *argv[])
{
    srand(time(NULL));
    vector<int> v(N);
    for (int i = 0; i < N; ++i)
    {
        v[i] = i;
    }

    random_shuffle(v.begin(), v.end());

    ostream_iterator<int> os(cout, " ");

    cout << "Original array = " << endl;
    show(v.begin(),v.begin()+21);

    cout << "Partial_sort for 20 elements... "  << endl;

    vector<int> v1(v);
    uint32 ts = current_time_ms();

    partial_sort(v1.begin(), v1.begin()+21, v1.end(), less<int>());
    cout << "time = " << current_time_ms() - ts << endl;

    show(v1.begin(),v1.begin()+21);

    cout << "nth_element of the 20th elements... "  << endl;
    vector<int> v2(v);
    ts = current_time_ms();
    nth_element(v2.begin(), v2.begin()+20, v2.end(),less<int>());
    cout << "time = " << current_time_ms() - ts << endl;
    show(v2.begin(),v2.begin()+21);

    cout << "v1[19] = " << nth(v1, 21) << endl;
    cout << "v2[19] = " << nth(v2, 21) << endl;

    vector<int>v5(v);
    sort(v5.begin(), v5.end());

    if (nth(v5, 21) == nth(v2, 21))
    {
        cout << "nth_element works! " << endl;
    }
    else
    {
        cout << "nth_element is not working correctly! "  << endl;
    }


    cout << "Testing partition... " << endl;
    vector<int> v3(v);
    ts = current_time_ms();
    vector<int>::iterator i1 = partition(v3.begin(), v3.end(), PartitionCond);
    cout << "Time cost = " << current_time_ms() - ts << endl;
    show(v3.begin(), i1);

    cout << "Testing stable_partition... " << endl;
    vector<int> v4(v);
    ts = current_time_ms();
    vector<int>::iterator i2 = stable_partition(v4.begin(), v4.end(), PartitionCond);
    cout << "Time cost = " << current_time_ms() - ts << endl;
    show(v4.begin(), i2);

    return 0;
}
相关文章
相关标签/搜索