stl源码剖析 详细学习笔记heap
//
// heap.cpp
// 笔记
//
// Created by fam on 15/3/15.
//
//
//---------------------------15/03/15----------------------------
//heap
{
/*
heap概述:
heap并不是stl的容器,只是priority queue(优先队列)的助手
它允许用户以任意顺序插入容器,但是取出是,总是取出优先级最高的元素
heap用的是很常见的堆结构,用数组来表示,采用堆排序的方法排序,时刻保持堆的特性
*/
//push_heap
template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first,
RandomAccessIterator last)
{
__push_heap_aux(first,last, distance_type(first),
value_type(first));
}
template <class RandomAccessIterator,
class Distance, class T>
inline void __push_heap_aux(RandomAccessIterator first,
RandomAccessIterator last, Distance*,T*)
{
__push_heap(first,Distance((last - first) -
), Distance(),
T(*(last -
)));
}
template <class RandomAccessIterator,
class Distance, class T>
void __push_heap(RandomAccessIterator first, Distance holeIndex,
Distance topIndex, T value)
{
//取最后一个元素的父节点,先减1的原因是第一个节点时0,
//而不是1开始算的
Distance parent = (holeIndex -
) / ;
//一直循环到当前节点等于根节点
或者 父节点的值大于等于添加的值
while (holeIndex > topIndex && *(first + parent) < value)
{
//
把父节点的值赋值给当前节点
*(first + holeIndex) = *(first + parent);
//当前节点变成父节点
holeIndex = parent;
//父节点变成父节点的父节点
parent = (holeIndex -
) / ;
}
//把值赋值给恰当的位置
*(first + holeIndex) = value;
}
//push功能总结:push就是从最后一个元素开始一直和父节点比较,如果要插入的值(最后一个元素的值)
//比较大就不断上移,直到达到堆的根
//pop_heap
template <class RandomAccessIterator>
inline void pop_heap(RandomAccessIterator first,
RandomAccessIterator last)
{
__pop_heap_aux(first,last,value_type(first));
}
template <class RandomAccessIterator,
class T>
inline void __pop_heap_aux(RandomAccessIterator first,
RandomAccessIterator last, T*)
{
__pop_heap(first,last -
,last - , T(*(last -
))
distance_type(first));
}
template <class RandomAccessIterator,
class T, class Distance>
inline void __pop_heap(RandomAccessIterator first,
RandomAccessIterator last,
RandomAccessIterator result,
T value, Distance*)
{
*result = *first;
__adjust_heap(first, Distance(), Distance(last - first), value);
}
template <class RandomAccessIterator,
class Distance, class T>
void __adjust_heap(RandomAccessIterator first, Distance holeIndex,
Distance len, T value)
{
//topIndex == 0 -->> topelem == first + 0
Distance topIndex = holeIndex;
//由于从0开始计算
所以右儿子为 2n + 2;
//secondChild
其实也是Index,不是真的值
Distance secondChild =
* holeIndex + ;
//只要右儿子存在就一直循环
while (secondChild < len)
{
//如果有右儿子小于左儿子,secondChild就设置为左儿子
//目的是要让当前节点最后成为2个节点中最大的
if(*(first + secondChild) < *(first + (secondChild -
)))
secondChild--;//为什么不是 --secondChild,这样效率更高
//把当前节点的值设置为secondChild的值
*(first + holeIndex) = *(first +secondChild);
//当前节点切换成secondChild节点
holeIndex = secondChild;
//设置secondChild为右儿子
secondChild =
* (secondChild + );
}
//存在左儿子(如果有右儿子就会一直循环,最后只有两种情况,一是当前节点到达叶子节点
//一种情况是没有右儿子,但是有左儿子)
if(secondChild == len)
{
//把左儿子的值赋给当前节点
*(first + holeIndex) = *(first + (secondChild -
));
//把当前节点切换成左儿子
holeIndex = secondChild -;
}
//把当初标记的最后的一个节点插入堆中( T(*(last - 1) )
__push_heap(first, holeIndex, topIndex, value);
/*
总结:把根节点输出到result中
所以就要不断把儿子往上移来填充
填充到最后就会空缺一个节点(下面的往上移动总会有一个空缺的)
所以最后要把最后的一个元素插入到堆前面去,也就是最后空缺的是原先
最后面的位置,那就没影响了
如果空缺的已经是最后的元素了,那就是对已经排序好的堆做排序(最后的元素
已经比父节点大了,会马上排好.
*/
}
//sort
template<class RandomAccessIterator>
void sort_heap(RandomAccessIterator first,
RandomAccessIterator last)
{
)
{
pop_heap(first, last--);
}
}
//结束后就是已经排序好的序列,就不是堆了
//make_heap
template<class RandomAccessIterator>
inline void make_heap(RandomAccessIterator first,
RandomAccessIterator last)
{
__make_heap(first, last, value_type(first), distance_type(first));
}
template<class RandomAccessIterator,
class T, class Distance>
void __make_heap(RandomAccessIterator first,
RandomAccessIterator last, T*,Distance*)
{
//判断边界情况,如果只有一个元素
直接返回
) return;
//len==元素个数
Distance len = last - first;
//parent ==
最后一个元素的父节点
Distance parent = (len -
) / ;
while (true)
{
//一直循环,直到全部排序好,从最后的三角形(最后的元素,父节点,左儿子(如果有的话))
//开始,直到根节点,就调整完毕了
__adjust_heap(first, parent, len, T(*(first + parent)));
)
return ;
parent--;
}
}
}
stl源码剖析 详细学习笔记heap的更多相关文章
- stl源码剖析 详细学习笔记 算法总览
//****************************基本算法***************************** /* stl算法总览,不在stl标准规格的sgi专属算法,都以 *加以标 ...
- stl源码剖析 详细学习笔记 hashtable
//---------------------------15/03/24---------------------------- //hashtable { /* 概述: sgi采用的是开链法完成h ...
- stl源码剖析 详细学习笔记 set map
// // set map.cpp // 笔记 // // Created by fam on 15/3/23. // // //---------------------------15/03 ...
- stl源码剖析 详细学习笔记 RB_tree (1)
// // RB_tree_STL.cpp // 笔记 // // Created by fam on 15/3/21. // // #include "RB_tree_STL.h&q ...
- stl源码剖析 详细学习笔记priority_queue slist
// // priority_queue.cpp // 笔记 // // Created by fam on 15/3/16. // // //------------------------- ...
- stl源码剖析 详细学习笔记 空间配置器
//---------------------------15/04/05---------------------------- /* 空间配置器概述: 1:new操作包含两个阶段操作 1>调 ...
- stl源码剖析 详细学习笔记 算法(1)
//---------------------------15/03/27---------------------------- //算法 { /* 质变算法:会改变操作对象之值 所有的stl算法都 ...
- stl源码剖析 详细学习笔记 RB_tree (2)
//---------------------------15/03/22---------------------------- //一直好奇KeyOfValue是什么,查了下就是一个和仿函数差不多 ...
- stl源码剖析 详细学习笔记stack queue
// // stack.cpp // 笔记 // // Created by fam on 15/3/15. // // //---------------------------15/03/1 ...
随机推荐
- 使用代码段遍历,枚举类型Enum
最近项目中定义了一些枚举类型,需要将枚举的键值传给前端,用于制作下拉菜单. 1.首先定义了枚举类型 public enum 请假类型 : int { 病假 = 1, 事假 = 2, 婚假 = 3, 产 ...
- 如何在 Azure 门户中将托管数据磁盘附加到 Windows VM
本文介绍了如何通过 Azure 门户将新的托管数据磁盘附加到 Windows 虚拟机. 在开始之前,请查看以下提示: 虚拟机的大小决定了可以附加多少个磁盘. 有关详细信息,请参阅虚拟机大小. 对于新磁 ...
- UNIX高级环境编程(13)信号 - 概念、signal函数、可重入函数
信号就是软中断. 信号提供了异步处理事件的一种方式.例如,用户在终端按下结束进程键,使一个进程提前终止. 1 信号的概念 每一个信号都有一个名字,它们的名字都以SIG打头.例如,每当进程调用了ab ...
- Git & GitHub 的安装配置
参考 教你免费搭建个人博客,Hexo&Github 安装Git 1. 注册 GitHub 注册.登录 https://github.com/ 2. 创建仓库 在 GitHub 的右上角 ...
- CVE-2013-2551
目录 小白的CVE-2013-2551 分析 & 利用 0xFF 前言 0x00 环境和工具 0x01 分析POC POC 调试 0x02 利用 构造R3任意内存读写 劫持eip 利用利用 0 ...
- MySQL面试之说明myisam和innodb两种存储引擎的不同之处
1.事务的支持不同(innodb支持事务,myisam不支持事务) 2.锁粒度(innodb行锁应用,myisam表锁) 3.存储空间(innodb既缓存索引文件又缓存数据文件,myisam只能缓存索 ...
- 【Alpha 冲刺】 5/12
今日任务总结 人员 今日原定任务 完成情况 遇到问题 贡献值 胡武成 建立数据库 未完成 设计表结构的时候,有些逻辑没有设计好,重新review一番设想的功能才初步确定表结构 孙浩楷 根据UI设计, ...
- PyQt5--ToolBar
# -*- coding:utf-8 -*- ''' Created on Sep 14, 2018 @author: SaShuangYiBing ''' import sys from PyQt5 ...
- 【转】numpy中mean和average的区别
转自:https://blog.csdn.net/Muzi_Water/article/details/85104941 mean和average都是计算均值的函数,在不指定权重的时候average和 ...
- QGIS里的编程模型
项目(QgsProject) 用于读写项目状态 图层分组(QgsLayerTreeGroup) 项目树的分组节点,用来存放图层节点. 图层节点(QgsLayerTreeLayer) 项目树的图层节点. ...