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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java转大数据的学习路线

    java转大数据的学习路线首先这个文章是转载的,留着后面基础再扎实一点之后开始学习,感谢原文的作者,写出了如此清晰的学习路线。原文作者文章链接:https://blog.csdn.net/gitchat/article/details/78341484【不要错过文末彩蛋】申明:本文旨在为普通程序员(Java程序员最佳)提供一个入门级别的大数据技术学习路径,不适用于大数据工程师的进阶学习,也不适用于零编程基础的同…

    2022年6月10日
    32
  • 大学四年零基础自学Java的路线

    大学四年零基础自学Java的路线屌丝逆袭,成神之路

    2022年6月20日
    22
  • matlab中importdata函数导入数据 到工作空间[通俗易懂]

    用load函数导入mat文件大家都会。但是今天我拿到一个数据,文件后缀名居然是‘.data’。该怎么读呢?我只好用matlab界面Workspace区域的“importdata”按钮手工导入该文件。恩,还好,居然成功了。顺便提一下,这个“importdata”按钮功能很强大,连excel文件都能导入。但是如果在脚本里如何导入这种非mat文件呢?这时候就轮到“import

    2022年4月17日
    224
  • JDBC中DatabaseMetaData用法

    JDBC中DatabaseMetaData用法DatabaseMetaData类中提供了许多方法用于获得数据源的各种信息,通过这些方法可以非常详细的了解数据库的信息。就如我们上面例子中所显示的几个信息[其他的方法请读者参考JDKAPI中的DatabaseMetaData类]:getURL()返回一个String类对象,代表数据库的URL。getUserName()返回连接当前数据库管理系统的用户名。isReadOnly(…

    2022年6月19日
    38
  • websocket token认证(websocket协议格式)

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mazaiting/article/details/78129542 JavaOkHttp使用本文使用eclipse编辑器,gradle依赖j…

    2022年4月17日
    77
  • java运行环境_如何搭建Java运行环境?

    java运行环境_如何搭建Java运行环境?前言对于运行一个Java程序,我们首先需要有一个运行Java程序的平台程序,这个平台程序就是Java虚拟机。本篇文章将介绍如何在Windows系统上搭建一个Java程序的运行环境,主要分为两个步骤:安装JDK,配置环境变量。Windows系统Java运行环境配置下载JDK并安装首先我们需要下载java开发工具包JDK,JDK中包含了JRE(Java运行环境)和一些官方提供给我们的工具,在oracl…

    2022年7月7日
    22

发表回复

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

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