partial_sort接受一个middle迭代器,使序列中的middle-first个最小元素以递增顺序排序。置于[first, middle)内。以下是測试代码:

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int main()
{int a[] = {10,9,8,7,6,5,4,3,2,1,0};vector<int> vec(a, a+11);vector<int>::iterator b = vec.begin();vector<int>::iterator e = vec.end();partial_sort(b, b+6, e);     // 前6个最小元素排序while (b != e)cout << *(b++) << ' ';return 0;
}
执行结果:
从结果能够看出,前6个最小元素放在了前6个位置上,而剩下的元素则放于容器后面未排序。
实现partial_sort的思想是:对原始容器内区间为[first, middle)的元素运行make_heap()操作构造一个最大堆。然后拿[middle, last)中的每一个元素和first进行比較,first内的元素为堆内的最大值。假设小于该最大值,则互换元素位置,并对[first, middle)内的元素进行调整。使其保持最大堆序。

比較完之后在对[first, middle)内的元素做一次对排序sort_heap()操作。使其按增序排列。注意。堆序和增序是不同的。

以下分析STL的源代码。partial_sort有两个版本号,一个默认以小于作为比較规则,出来的顺序为递增排列。

还有一个能够传入一个仿函数。即自己定义比較规则。这里仅仅分析前者。

template <class RandomAccessIterator>
inline void partial_sort(RandomAccessIterator first,RandomAccessIterator middle,RandomAccessIterator last) {__partial_sort(first, middle, last, value_type(first));
}

进入__partial_sort函数:
template <class RandomAccessIterator, class T>
void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle,RandomAccessIterator last, T*) {make_heap(first, middle); // [first, middle)区间构造一个heapfor (RandomAccessIterator i = middle; i < last; ++i)if (*i < *first)        // 当前元素比堆中最大的元素小__pop_heap(first, middle, i, T(*i), distance_type(first));  // first值放i中,i的原值融入heap并调整sort_heap(first, middle);
}

此函数和上面的文字描写叙述基本同样。有一点小的差别在于当*i < *first时,代码中没有互换i所指元素和first所指元素。究竟怎么做的?来看看__pop_heap函数:
template <class RandomAccessIterator, class T, class Distance>
inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,RandomAccessIterator result, T value, Distance*) {*result = *first; // 弹出元素放vector尾端__adjust_heap(first, Distance(0), Distance(last - first), value);
}

此函数把first中的元素放在了result,也就是i位置上。成功地把最大值挤出了[first, middle)区间。

但此时first位置形成了一个空洞。即索引值Distance(0)。所以须要调整heap,这由__adjust_heap函数负责。调整大致过程是找出最大元素放入first,然后把value保存的值插入到堆的适当位置,在这里value即为T(*i),即把i所指元素融入到了[first, middle)区间。

由此可见,__adjust_heap的复用性还是非常高的。

再回到__partial_sort函数。for循环就是反复上面的“挤出”和“融入”操作直到容器末尾。

当跳出for循环时,区间[first, middle)中已经存放有容器的前middle-first个最小元素了。最后运行sort_heap(),由堆序变为增序排列:

template <class RandomAccessIterator>
void sort_heap(RandomAccessIterator first, RandomAccessIterator last) {while (last - first > 1) pop_heap(first, last--);
}

弹出堆的最大值并放入尾部,然后缩小堆的范围。循环运行弹出操作直至堆仅仅剩下最后一个元素。

这样就能够达到排序效果了。注意。此函数仅仅能用于堆上。

若要对整个普通容器施行堆排序操作。能够借partial_sort接口。仅仅需把middle參数改为last就可以:

partial_sort(first, last, last);
这样的方法用到了STL的高速排序身上,感觉越来越有意思了。
个人认为这个局部排序还是蛮重要的,至少是它的排序思想非常好,要不然STL也不会使用它了。
參考:
《STL源代码剖析》 P386.

转载于:https://www.cnblogs.com/bhlsheji/p/5276771.html

【STL】算法 — partial_sort相关推荐

  1. STL算法algorithm,

    2019独角兽企业重金招聘Python工程师标准>>> STL算法部分主要由头文件<algorithm>,<numeric>,<functional&g ...

  2. STL算法学习[转]

    原文:http://www.cppblog.com/mzty/archive/2007/03/14/19819.html STL算法学习,小结如下: 前提: 下载stl源码:  http://www. ...

  3. C++ 笔记(19)— 标准模板库(STL容器、STL迭代器、STL算法、STL容器特点、STL字符串类)

    C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...

  4. 【C++】C++11 STL算法(一):非修改序列操作(Non-modifying sequence operations)

    目录 一.all_of.any_of.none_of: 1.官方说明 2.谓词 3.STL算法对谓词的说明 4.谓词的五种模式 5.all_of (C++ 11) 6.any_of (C++ 11) ...

  5. C++中的STL算法详解

    1.STL算法详解 STL提供能在各种容器中通用的算法(大约有70种),如插入.删除.查找.排序等.算法就是函数模板,算法通过迭代器来操纵容器中的元素.许多算法操作的是容器上的一个区间(也可以是整个容 ...

  6. c++STL算法基础

    STL算法基础 算法概述 STL中算法分类 查找算法(13个) adjacent_find binary_search count count_if equal_range find find_end ...

  7. 大顶堆删除最大值_C++|使用STL算法创建、调整、输出最大堆、最小堆

    最大堆(又叫大根堆.大顶堆)和最小堆是二叉堆的两种形式,一类很重要的数据结构,如用于堆排序等. 最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小. 最大堆:根结点的键值是所 ...

  8. C++语言基础 —— STL —— 算法

    [概述] STL 是指 C++ 标准模板库,是 C++ 语言标准中的重要组成部分,其以模板类和模版函数的形式提供了各种数据结构与算法的精巧实现,如果能充分使用 STL,可以在代码空间.执行时间.编码效 ...

  9. STL 算法接口及用法说明 (二)

    STL 算法接口及用法说明 copy copy 有两个重载,意义和用法较为明显,不做过多说明: template<class _InIt, class _OutIt> inline_Out ...

  10. STL 算法/容器——总论

    0. 序列式容器与关联式容器 在 STL 库中,序列式容器主要有: vector.list.deque.stack.queue.heap.priority_queue.slist 关联式容器主要有: ...

最新文章

  1. 使用Java企业级技术开发大型系统(3)
  2. 嵌入式程序调用函数的内部过程和机制
  3. Linux下搜索文件常用方法
  4. USACO 3.1 Agri-Net 最短网络 (最小生成树)(普里姆算法)
  5. 【转】ROWNUM与ORDER BY先后关系
  6. 分区助手扩大c盘后自动修复_C盘空间不够,如何扩大?
  7. Datawhale-零基础入门NLP-新闻文本分类Task02
  8. 不妨问问自己,学习C语言是为了什么?
  9. Vue+Vue Router+Vuex页面演示
  10. win7 ASP.NET 2.0 部署
  11. 二叉树的inorder实现:递归、栈、Morris遍历
  12. 线性代数及其应用(第三版)5.1节习题解答
  13. 电脑连接移动设备android驱动程序,手机连接电脑驱动程序下载汇总
  14. 【vue源码工程阅读1:下载源码】认识工程并打包
  15. Java如何实现贪吃蛇小游戏
  16. html字体外围有黄色边框,input或textarea在chrome、safari浏览器点击获得焦点时出现黄色边框去掉的方法...
  17. CTF-数据分析(二)
  18. PromQL 直方图 跟踪请求的延迟或响应大小 99%的请求是在多少延迟下完成的?
  19. python---关于集合
  20. pandas数据分析常用的一些方法

热门文章

  1. OpenCV-python学习笔记(二)——image processing图像基本处理
  2. 初一辍学学php能行吗_那些初中就辍学的小姑娘现在过得如何了?
  3. centos 命令行执行多个命令_命令行如何执行jar包里面的方法
  4. 数据清理--去掉空值
  5. Postman系列之基本操作及设置
  6. 欧易OKEx交易大数据:BTC合约多空持仓人数比0.98,合约持仓总量为24.90亿美元
  7. SAP License:SAP信用控制
  8. SAP License:外购和自产货物视同销售业务理解
  9. 素拓活动策划书的撰写范文
  10. Python结合Shell/Hadoop实现MapReduce