STL heap 实现

先引用 《STL 源码剖析》(作者: 侯捷)的原话:

heap 并不属于 STL 的容器组件, 它是一个幕后英雄 ,扮演 priority queue 的助手。
binary heap 是一种 完全二叉树(completely binary tree),也就是说,整棵 binary tree
除了最底层的叶子节点以外,都是填满的 。而最底层的叶子节点由左到右又不得有空隙。
完全二叉树没有任何的节点漏洞,这带来了极大的好处是,允许我们以array 来存储所有的节点。
根据元素的排列顺序,heap 可以分为 max-heap 和 min-heap 两种。

原话结束。
但是,由于 array 并不能实现动态增长,所以,用了vector 作为完全二叉树的表达方式。

主要实现的函数是:
push_heap();
pop_heap();
make_heap();
sort_heap();

#include<iostream>
#include<vector>

using namespace std;

namespace Hheap 
{

template<class random_iterator>
void push_heap(random_iterator first, random_iterator last)
{
    /*其实就是一个上溯的过程,这里先用迭代器“榨汁机”,榨取类型*/
    typedef typename iterator_traits<random_iterator> :: value_type value_type;
    typedef typename iterator_traits<random_iterator> :: difference_type difference_type;

    if((last- 1)<=first)
        return;
    value_type value = *(last -1);
    // index of (last -1)
    difference_type hole_index= (last -1) -first ;
    //parents of (last -1 )
    difference_type parent = (hole_index-1)/2;
    //上溯的结束条件是 洞口小于零 或者 不如父节点的值大
    while(hole_index > 0 && *(first+ parent)<value)
    {
        *(first + hole_index) = *(first + parent) ;
        hole_index = parent;
        parent = (hole_index-1)/2;
    }
    *(first + hole_index) = value;
}

template<class random_iterator >
void pop_heap(random_iterator first , random_iterator last)
{
    /*取出最大值的过程比较麻烦,包含着一个 下溯,下溯完成又存在一个上溯*/
    typedef typename iterator_traits<random_iterator> :: difference_type difference_type;
    typedef typename iterator_traits<random_iterator> :: value_type value_type;

    value_type value = *first;
    //index of first 
    difference_type hole_index = 0;
    // left child
    difference_type left_child = hole_index*2+1;
    // right child
    difference_type right_child = left_child +1 ;

    while( right_child <(last - first))
    {
        if(*(first + right_child) < *(first + left_child) )
        {
            *(first + hole_index) = *(first + left_child);
            hole_index = left_child;
        }
        else
        {
            *(first + hole_index) = *(first + right_child);
            hole_index = right_child;
        }

        left_child =  hole_index*2+1;

        right_child = left_child +1;
    }

    // 如果还有左孩子 ,那么单独处理
    if(left_child < (last - first))
    {
        *(first + hole_index) = *(first + left_child);
        hole_index = left_child; //更改洞口 到最后一个。
    }

    *(first + hole_index) = *(last - 1);
    // 再执行一次上溯 
    push_heap(first , first + hole_index +1);
    *(last -1) = value;
}

template<class random_iterator >
void sort_heap(random_iterator first , random_iterator last)
{
    /*不断的执行 pop_heap 将最大值放到末尾 然后,去掉最后一个数,再次执行pop_heap
    */
    if(last - first <=1)
        return ;
    while(last - first >1)
        pop_heap(first,last--);

}

template<class random_iterator >
void make_heap(random_iterator first ,random_iterator last)
{
    typedef typename iterator_traits<random_iterator > ::difference_type difference_type;
    typedef typename iterator_traits<random_iterator > :: value_type      value_type;

    if(last - first <= 1)
        return ;

    difference_type i = 2;
    while((first +i )<=last)
        {
            Hheap::push_heap(first , (first+i) );
            ++i;
        }
}

template<class Sequence >
void print(Sequence& c)
{
    for(auto iter= c.begin() ;iter !=c.end();iter ++)
        cout<<*(iter)<<" ";
    cout<<endl;
}


}; //namespace end
int main()
{
    std::vector<int > v;
    v.push_back(4);
    v.push_back(6);
    v.push_back(3);
    v.push_back(2);
    v.push_back(8);
    v.push_back(9);

    Hheap::make_heap(v.begin(),v.end() );  //建立堆
    Hheap::print(v); //打印堆

    v.push_back(56);
    Hheap::push_heap(v.begin(),v.end()); //压入堆,上溯建立合法的堆
    Hheap::print(v); //打印堆

    Hheap::pop_heap(v.begin(),v.end()); //将最大值取出,先下溯 再上溯 建立合法的堆
    Hheap::print(v); //打印堆
    v.pop_back();

    Hheap::sort_heap(v.begin(),v.end()); //对堆进行重新排序
    Hheap::print(v); //打印堆


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值