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

*/-->

div.org-src-container {
font-size: 85%;
font-family: monospace;
}
pre.src {
background-color:#f8f4d7
}
p {font-size: 15px}
li {font-size: 15px}

1 partial_sort

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

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 位置的元素相同(等值):

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

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

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_sort
nth_element 都不是稳定的,但算法 stable_sort 可以保证这一点。

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.

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 算法。

上述各种算法的效率:

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

#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;
}

Effective STL 学习笔记 31:排序算法的更多相关文章

  1. STL学习笔记(排序算法)

    STL提供了好几种算法对区间内的元素排序.出来完全排序外,还支持局部排序. 对所有元素排序 void sort(RandomAccessIterator beg,RandomAccessIterato ...

  2. Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据

    Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...

  3. Effective STL 学习笔记 Item 21:Comparison Function 相关

    Effective STL 学习笔记 Item 21:Comparison Function 相关 */--> div.org-src-container { font-size: 85%; f ...

  4. Effective STL 学习笔记:19 ~ 20

    Effective STL 学习笔记:19 ~ 20 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  5. Effective STL 学习笔记 39 ~ 41

    Effective STL 学习笔记 39 ~ 41 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  6. Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value

    Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...

  7. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  8. Effective STL 学习笔记: Item 22 ~ 24

    Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...

  9. Effective STL 学习笔记: 多用 vector & string

    Effective STL 学习笔记: 多用 vector & string 如果可能的话, 尽量避免自己去写动态分配的数组,转而使用 vector 和 string . 原书作者唯一想到的一 ...

随机推荐

  1. git<Commit和Push的区别>

    git作为支持分布式版本管理的工具,它管理的库(repository)分为本地库.远程库. git commit操作的是本地库,git push操作的是远程库. git commit是将本地修改过的文 ...

  2. lumen 单元测试的一些问题

    1.一个 test 多个请求 如 $this->post,然后又  $this->post,我们会发现第二个请求中的请求参数是和第一个请求的参数是完全一样的,然后在 Controller ...

  3. libcurl代码示例

    http://note.youdao.com/noteshare?id=e60a679d1731c870ff45e403de81a2c0

  4. 开始 Dojo 开发

    原文出处:Joe Lennon 从头开始学习 Dojo,第 1 部分 开始 Dojo 开发 Dojo Toolkit 简介 Dojo 于 2004 年创建,使开发 DHTML 和 JavaScript ...

  5. Hadoop生态圈-hbase介绍-完全分布式搭建

    Hadoop生态圈-hbase介绍-完全分布式搭建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  6. sql 存储时空格转成问号问题

    最近做系统,从邮件中导出邮件,上传到系统中,遇到一个奇葩的问题,如下: 通过本地文件看,文件名中是一个空格,上传至数据库后,展示就变成了问号,究其原因,发现是一个特殊字符导致: 最近认真去查了一下这个 ...

  7. 图片截取插件Cropper

    自己仿照github上的例子写的demo,github上的例子太抽象了,自己写的最适合自己,通俗易懂. <!DOCTYPE html> <html> <head> ...

  8. 超厉害的CSS3图片破碎爆炸效果!

    var fx  = { buffer : function(obj, cur, target, fnDo, fnEnd, fs){ if(!fs)fs=6; var now={}; var x=0; ...

  9. ubuntu环境下eclipse的安装以及hadoop插件的配置

    ubuntu环境下eclipse的安装以及hadoop插件的配置 一.eclipse的安装 在ubuntu桌面模式下,点击任务栏中的ubuntu软件中心,在搜索栏搜索eclipse 注意:安装过程需要 ...

  10. 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛:Frequent Subsets Problem (状态压缩)

    题目链接 题目翻译: 给出一个数n,和一个浮点数a,数n代表全集U = {1,2,...,n},然后给出 M个U的子集,如果一个集合B(是U的子集),M个集合中有至少M*a个集合包含B, 则B这个集合 ...