STL中heap算法(堆算法)

STL中heap算法(堆算法)



①push_heap算法
以下是push_heap算法的实现细节。该函数接收两个迭代器,用来表现一个heap底部容器(vector)的头尾,而且新元素已经插入究竟部的最尾端。
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*)
{
 //以上系依据heap的结构特性:新值必置于底部容器的最尾端,此即第一个洞号:(last-first)-1
 _push_heap(first,Distance((last-first)-1),Distance(0),T(*(last-1)));
}

template <class RandomAccessIterator,class Distance,class T>
void _push_heap(RandomAccessIterator first,Distance holeIndex,Distance topIndex,T value)
{
 Distance parent = (holeIndex-1)/2;
 while (parent > topIndex && *(first+parent)<value)
 {
  *(first + holeIndex) = *(first + parent);
  holeIndex = parent;
  parent = (holeIndex-1)/2;
 }
 *(first + holeIndex) = value;
}

②pop_heap算法
pop操作取走根节点(事实上是设至底部容器vector的尾端节点)后,为了满足complete binary tree的条件,必须割舍最下层最右边的叶节点,并将其值又一次安插至最大堆。
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-1,last-1,T(*(last-1)),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(0),Distance(last-first),value);
 //以上欲又一次调整heap,洞号为0(亦即树根处),欲调整值为value(原尾值)
}

template <class RandomAccessIterator,class Distance,class T>
void _adjust_heap(RandomAccessIterator first,Distance holeIndex,Distance len,T value)
{
 Distance topIndex = holeIndex;
 Distance secondChild = holeIndex*2+2;
 while (secondChild < len)
 {
  if(*(first+secondChild) < *(first+secondChild-1))
   secondChild–;
  *(first+holeIndex) = *(first+secondChild);
  holeIndex = secondChild;
  secondChild = holeIndex*2+2;
 }
 if (secondChild == len)
 {
  *(first+holeIndex) = *(first+secondChild-1);
  holeIndex = secondChild-1;
 }
 _push_heap(first,holeIndex,topIndex,value);
}

注意:pop_heap之后,最大元素仅仅是被置于底部容器的最尾端,尚未被取走。假设要取其值,可使用底部容器(vector)所提供的back()操作函数。假设要移除它,可使用底部容器(vector)所提供的pop_back()操作函数。
③sort_heap算法
既然每次pop_heap可获得heap中键值最大的元素,假设持续对整个heap做pop_heap操作,每次将操作范围从后向前缩减一个元素(由于pop_heap会把键值最大的元素放在底部容器的最尾端),当整个程序运行完成时,我们便有了一个递增序列。
template<class RandomAccessIterator>
void sort_heap(RandomAccessIterator first,RandomAccessIterator last)
{
 while(last – first > 1)
  pop_heap(first,last–);
}

④make_heap算法
这个算法用来将一段现有的数据转化为一个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*)
{
 if (last – first < 2) return;
 Distance len  = last-first;
 Distance parent = (len-1)/2;

 while (true)
 {
  _adjust_heap(first,parent,len,T(*(first+parent)));
  if (parent == 0)
   return;
  parent–;
 }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119095.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • cboard企业版源码_CBoard「建议收藏」

    cboard企业版源码_CBoard「建议收藏」CBoardAnopenBIDashboardplatformthatsupportsinteractivemulti-dimensionalreportdesignanddataanalysisServersideframeworkisSpring+MyBatisandfront-endisbasedonAngularJS1andBootstra…

    2025年8月25日
    3
  • Java解析XML文件的四种方法「建议收藏」

    Java解析XML文件的四种方法「建议收藏」【摘要】可扩展标志语言(XML)在实现信息标准化、信息的交流与共享上有其独特的技术优势,因此受到了广泛的重视。本文先简单的介绍了XML基本知识,然后从XML应用入手总结了四种现今最常见的XML的解析方法,介绍了这四种方法的特点,其中包括优点与不足之处。最后给出了一个简单的案例来对这四种解析进行代码介绍。【关键字】XML文件,DOM,SAX,JDOM,DOM4J【引言】XML即可扩展标记语

    2022年6月3日
    45
  • 网易邮箱(126/163):授权码获取攻略

    网易邮箱(126/163):授权码获取攻略一、网易免费邮箱1、因为网易限制,第三方邮件客户端登陆网易邮箱必须用授权码登陆。浏览器登录mail.163.com(126邮箱:mail.126.com),点击路径:“设置”>>“POP3/SMTP/IMAP”。2、在右边网页中,选择“开启”(IMAP/SMTP服务),弹出“帐号安全验证”,用手机扫码发送短信,并点击“我已发送”3、验证后获取客户端授权密码4、此处可管理多个客户端授权密码二、网易VIP邮箱

    2022年4月4日
    2.7K
  • 使用Python读取照片的GPS信息

    使用Python读取照片的GPS信息

    2022年2月13日
    38
  • iis由于权限不足无法读取配置文件_iis500内部服务器错误

    iis由于权限不足无法读取配置文件_iis500内部服务器错误Response对象错误’ASP0251:80004005’超过响应缓冲区限制此ASP页的执行造成响应缓冲区超过其配置限制。因为页面中数据较多,有上千条,导致出现“超过响应缓冲区限制。此ASP页的执行造成响应缓冲区超过其配置限制”。如果response.buffer=false这样设的话,可以查出,但是好慢。怎么解决?我们可以加大Buffer的缓冲区,办法是:先在服务里关闭i…

    2022年10月20日
    1
  • 教你画出业务架构图「建议收藏」

    教你画出业务架构图「建议收藏」1、什么是业务架构图?业务架构图是一种表达业务层级和关系的工具,业务架构服务于业务目标,通过描绘业务上下层关系,梳理一整套完整、简单的业务视图,降低业务系统的复杂度,提高客户理解度,最终给客户最直观的业务体现。2、业务架构图的三大核心要义简单来说可以分为三个核心步骤:分层、分模块、分功能。架构图核心要义之一:分层指的是将业务按照层级区分,每个层级都属于独立的版块。下层更抽象,上层更具体。层级需要有逻辑上的关联,比如下层为上层服务,或者提供能力支撑。架构图核心要义之二:分模块分

    2022年10月12日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号