【heap】是算法不是容器哦

前面是一些小Tips和关键点,以及代码里不好理解的点,后面是源码,重要的函数全部都写了满满的注释嘿嘿嘿!
为什么是这种形式呢,因为看书的时候就是讲解源码的,于是顺着读代码的时候就加了注释。

heap

  • heap不归属于STL容器组件,是扮演priority queue(允许任何次序推入容器内,但取出一定是从优先权最高的元素开始取)的助手。binary max heap就适合做它的底层机制。关键:内部排序!

  • binary heap:完全二叉树的形态(好处:可用array存储所有节点,左右子节点为2i和2i+1,父节点i/2,称为隐式表述法)。故heap是一个array和一组heap算法,为了动态改变大小,用vector代替array。

  • heap分为max-heap和min-heap,STL默认前者。不提供遍历,故没有迭代器。

  • push_heap:上溯程序在这里插入图片描述

  • pop_heap:去掉根节点,下溯。注意:pop取走根节点的操作实际上是将其移至底部容器vector的最后一个元素,为了维持二叉树,需要将下一层的最右节点拿掉,补充到上面的空缺。在这里插入图片描述

  • 调用方法:(以算法形式呈现)vector< int> a; make_heap(a.begin(),a.end());
    a.push_back(7); push_heap(a.begin(),a.end());
    pop_heap(a.begin(),a.end());
    sort_heap(a.begin(),a.end());在这里插入图片描述

#ifndef __SGI_STL_INTERNAL_HEAP_H
#define __SGI_STL_INTERNAL_HEAP_H

__STL_BEGIN_NAMESPACE

#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1209
#endif

//这组push_back()不允许指定“大小比较标准”
//first是头结点存放的下标(并不默认就是0)
template <class RandomAccessIterator, class Distance, class T>
void __push_heap(RandomAccessIterator first, Distance holeIndex,
                 Distance topIndex, T value) {
   
  Distance parent = (holeIndex - 1) / 2; // 找出父节点
  while (holeIndex > topIndex && *(first + parent) < value) {
   
  // 当尚未到达顶端且父节点小于新值,fisrt是起始点
    *(first + holeIndex) = *(first + parent);//令洞值为父值
    holeIndex = parent;//调整洞号,向上提升至父节点
    parent = (holeIndex - 1) / 2;//新洞的父节点
  }    //持续至顶端或满足heap次序特性为止
  *(first + holeIndex) = value;//令洞值为新值,完成插入操作
}

template <class RandomAccessIterator, class Distance, class T>
inline void __push_heap_aux(RandomAccessIterator first,
                            RandomAccessIterator last, Distance*, T*) {
   
  __push_heap(first, Distance((last - first) - 1), Distance(0), 
              T(*(last - 1)));
   //容器的最尾端为第一个洞号
}

template <class RandomAccessIterator>
inline void push_heap(RandomAccessIterator first, RandomAccessIterator last) {
   
  //注意此函数被调用时新元素应该已经置于底部容器的最尾端
  __push_heap_aux(first, last, distance_type(first), value_type(first));
}

//这里是指定compare排序方式的push
template <class RandomAccessItera
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,队列和容器也可以使用 `std::pop_heap` 操作。虽然 `std::pop_heap` 函数通常与堆结构一起使用,但它实际上是一个通用的算法,适用于任何随机访问迭代器的容器。 在 C++ STL 中,队列和容器是使用不同的数据结构来实现的。队列通常使用双端队列(deque)或者链表(list)来实现,而容器可以是数组(array)、向量(vector)、链表(list)等。 使用 `std::pop_heap` 操作队列或容器时,需要保证容器中的元素满足堆的性质。也就是说,堆的性质是指父节点的值要大于等于(或小于等于)子节点的值。在使用 `std::pop_heap` 之前,通常需要先使用 `std::make_heap` 或者手动构建堆结构。 以下是使用 `std::pop_heap` 操作队列或容器的示例代码: ```cpp std::vector<int> vec = {9, 5, 7, 2, 4}; std::make_heap(vec.begin(), vec.end()); // 构建堆结构 std::pop_heap(vec.begin(), vec.end()); int maxElement = vec.back(); // 获取最大元素 vec.pop_back(); // 移除最大元素 // 现在 vec 中的堆结构已经被更新,最后一个元素不再是最大的 ``` 在上述示例中,我们使用 `std::vector` 容器来存储元素,并使用 `std::make_heap` 构建堆结构。然后,通过 `std::pop_heap` 移除堆中的最大元素,并通过 `vec.back()` 获取到被移除的最大元素。最后,使用 `vec.pop_back()` 移除最大元素后,容器中的堆结构已经被更新。 需要注意的是,对于不同类型的容器或队列,可能需要使用不同的迭代器或比较函数对象作为参数。请根据具体情况参考相关文档或示例代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值