【STL 堆 】

来源:互联网 发布:雷蛇键盘链接mac 编辑:程序博客网 时间:2024/05/02 01:38

一.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里面默认用的是 vector. 比较方式默认用 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
原创粉丝点击