【STL 堆 】

一.heap

      在STL中,priority_queue(优先权队列)的底层机制是最大堆,因此有必要先来了解一下heap。heap采用完全二叉树的结构,当然不是真正的binary tree,因为对于完全二叉树,我们通常用一个数组来表示。

      以下几个算法都是STL的泛型算法,包含在头文件algorithm里,priority_queue的push(),pop()都有直接调用它们。

1.push_heap算法

      首先,将新元素插入到底层vector的end()处。为了满足最大堆原理(每个结点的值必须大于或等于其子结点的值),于是将新结点与其父亲结点比较,如果其值大于父亲结点,就交换父子结点,直到不需要交换或者它已经到达根结点为止。

2.pop_heap算法

      因为作为最大堆,根结点即为最大值。交换vector首尾(first和last)元素,并重新调整[first,last-1)部分,也就是将“新根结点”跟其较大子结点交换,并持续下放,知道叶子结点为止。注意,pop_heap之后,最大元素只是被放在底部容器的最尾端,并没有被取走。若要取走,可用vector的pop_back()函数。

3.sort_heap算法

      持续对整个heap做pop_heap操作,每次将操作范围从后向前缩减一个元素,于是我们得到一个递增序列。显然,排序后的heap不是一个合法的heap了。

4.make_heap算法

      这个算法用来将数组转化成一个heap


二,heap(堆)简介

        1)采用vector存储,是一颗完全二叉树(complete binary tree)的形式。

               heap分为 max_heap 和 min_heap,前者最大权值在根,后者最小权值在根。

        2)建立堆过程

              vector中元素先调整为堆的形式。

              插入元素时,将元素放到vector 的最后面end(),然后上溯调整堆。

        3)heap算法      // #include <algorithm>

               make_heap(first,last)       //初建堆

               push_heap(first,last)        //插入元素,并调整为堆

               pop_heap(first,last)         //弹出元素,并调整为堆

               sort_heap(first,last)         //堆排序

#include<cstdlib>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
    int a[9]={0,1,2,3,4,5,6,7,8,};
    vector<int>ivec(a,a+9);
    make_heap(ivec.begin(),ivec.end());
    for(int i=0;i<ivec.size();i++)
        printf("%d  ",ivec[i]);
    printf("\n");
    ivec.push_back(7);
    push_heap(ivec.begin(),ivec.end());
    for(int i=0;i<ivec.size();i++)
        printf("%d  ",ivec[i]);
    printf("\n");
    pop_heap(ivec.begin(),ivec.end());
    printf("%d\n",ivec.back());
    ivec.pop_back();
    for(int i=0;i<ivec.size();i++)
        printf("%d  ",ivec[i]);
    printf("\n");
    sort_heap(ivec.begin(),ivec.end());
     for(int i=0;i<ivec.size();i++)
        printf("%d  ",ivec[i]);
    printf("\n");
}

三,priority_queue 实例

#include<queue>
#include<algorithm>
#include<cstdio>
using namespace std;
int main(){
    int a[9]={1,2,4,3,6,5,9,8,7};
    priority_queue<int>ipq(a,a+9);
    printf("size;%d\n",ipq.size());
    for(int i=0;i<ipq.size();i++)
        printf("%d  ",ipq.top());
        printf("\n");
    while(!ipq.empty()){
        printf("%d  ",ipq.top());
        ipq.pop();
    }
    printf("\n");
}



1)STL里面默认用的是 vect or . 比较方式默认用 operator<  , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆

#include <iostream>
#include <queue>
#include <cstdlib>
#include<cstdio>

using namespace std;

int main(){

    priority_queue<int, vector<int>, greater<int> > q;

    for( int i= 0; i< 10; ++i ) q.push(i);
    while( !q.empty() ){
        printf("%d  ",q.top());
        q.pop();
    }
    printf("\n");
    return 0;
}

 2)5)自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。但此时不能像基本类型这样声明priority_queue<Node, vector<Node>, greater<Node> >;原因是 greater<Node> 没有定义,如果想用这种方法定义则可以按如下方式:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值