STL中的堆操作


堆在我们做算法时应该有映像吧,分为大根堆,小根堆。

STL中的其实是对堆有实现的,使得我们可以直接拿来用。

相关的函数是make_heap();push_heap();pop_heap();sort_heap();


make_heap

make_heap(first,end,cmp);参数有3个,第一个为堆建立堆的第一个元素,第二个为最后一个元素的后面一个位置,第三个为比较函数。

这个函数的第一和第二个参数的形式决定了建立堆必须是连续的内存分配形式,常见的就是vector和数组,别的像dequeue不常用我就不说了。

有start和end指定的区间是[start,end),也就是不包括end。对于vector很容易理解,start就是vector.begin(), end就是vector.end();

第三个函数是比较大小的函数,如果空着,默认建立大根堆。否则需要传入比较函数。

例子:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//上面的声明在后面的例子中自动包含,不重复写
bool mycmp(int a,int b){
    return a > b;
}
int main(){
    vector<int> demo;
    int i=0;
    for(i=0;i<20;i++){
        demo.push_back(i);
    }
    //建大根堆
    make_heap(demo.begin(),demo.end());
    out << "big root:" <<endl;
    for(i=0;i<20;i++){
        cout<<demo[i] << ",";
    }
    cout << endl;
    //建小根堆
    make_heap(demo.begin(),demo.end(),mycmp);
    cout << "small root:" <<endl;
    for(i=0;i<20;i++){
        cout<<demo[i] << ",";
    }
    cout << endl;
}


输出:

big root:
19,18,14,17,10,12,13,16,8,9,1,11,5,2,6,15,7,3,0,4,
small root:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,   //这个怎么是线性有序的??因为这就是一个满足条件的小根堆,所以算法没有出问题的。



push_heap(start,end,cmp);

这个函数是建立在已经make_heap()的基础上,插入一个数据,使形成新堆,新插入的数据必须位于原有序的序列的最后,如果原来的是不成堆的,那么其运算结果也是不能保证成堆的。因为内部实现是只进行一个堆调整,把end之前的最后一个数加入堆。

各参数的意义同make_heap().

pop_heap(start,end,cmp);

这个函数是和push_heap相反的功能,他是把成堆队列的首个元素从队中拎出来,放到end之前的最后一个位置。其余元素从新调整成堆。


例子:

在前面make_heap()基础上:

int main(){
    /*
        ......这一段同make_heap(),后面的在这基础上书写
    */
    //加入一个新元素,重新排列成堆,若要加入两个元素,则要重复{push_back,push_heap}两次,不能全部push_back之后再push_heap.
    //增加新元素
    demo.push_back(3);
    //加入堆
    push_heap(demo.begin(),demo.end(),mycmp);
    cout << "small root with new member:" <<endl;
    for(i=0;i<21;i++){
        cout<<demo[i] << ",";
    }
    cout << endl;
    //弹出堆顶元素:0
    pop_heap(demo.begin(),demo.end(),mycmp);
    cout<<demo.back() << endl;  //弹出的元素放在demo.end()的前面一格
    demo.pop_back();
    cout << "small root after pop a member:" <<endl;
    for(i=0;i<20;i++){
        cout<<demo[i] << ",";
    }
    cout << endl;
}

输出:


small root with new member:
0,1,2,3,3,5,6,7,8,4,10,11,12,13,14,15,16,17,18,19,9,
0
small root after pop a member:
1,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,



sort_heap()

我们知道在已经有序的堆中调一次pop_heap可以得到一个最值。如果不停调用pop_heap(每次的end参数要减掉1)直到全部弹出,那么就得到一个有序的队列。

原始若是大根堆,得到升序。原来若是小根堆,得到降序。

例子:

int main(){
   /*
        ......这一段同push_heap()/pop_heap(),后面的在这基础上书写,0已被弹出。
        ......为什么老是以前面为基础,因为我只为所有函数写了一个例子,这样我就能重用一个打印输出。
    */
    //sort members,big root->raise order
    make_heap(&demo[0],&demo[20]);
    sort_heap(demo.begin(),demo.end());
    cout << "sort heap big root:" <<endl;
    for(i=0;i<20;i++){
       cout<<demo[i] << ",";
    }
    cout << endl;
    //sort members,small root->decrese
    make_heap(demo.begin(),demo.end(),mycmp);
    sort_heap(demo.begin(),demo.end(),mycmp);
    cout << "sort heap small root:" <<endl;
    for(i=0;i<20;i++){
        cout<<demo[i] << ",";
    }
    cout << endl;
}

输出:

sort heap big root:
1,2,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort heap small root:
19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,3,2,1,

==========

前面3个例子的合并的log(因为3个例子其实只有一份代码例子):

big root:
19,18,14,17,10,12,13,16,8,9,1,11,5,2,6,15,7,3,0,4,
small root:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
small root with new member:
0,1,2,3,3,5,6,7,8,4,10,11,12,13,14,15,16,17,18,19,9,
0
small root after pop a member:
1,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort heap big root:
1,2,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort heap small root:
19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,3,2,1,

==================================================

下面再记下priority_queue这个基于heap的STL模版。

头文件 #include <queue>

priority_queue<int>  test;
test.push(2);
test.push(3);
test.push(1); 
while(!test.empty()){
    cout << test.top()<<endl;
    test.pop();
}

输出

3

2

1

同样的脾气,默认是大的先出来

======

如果要小的先出来这么用:

priority_queue<int,vector<int>,greater<int> >  test2;
test2.push(2);
test2.push(3);
test2.push(1); 
while(!test2.empty()){
    cout << test2.top()<<endl;
    test2.pop();
}  

输出:

1

2

3

=================

那么如果是自定义的类型呢,这么用:

struct Node 
{
    int x,y;
    Node(int a = 0):x(a){}
    //或者实现成成员函数
    //bool operator< (const Node& node) const{
    //    return x < node.x;
    //}


};




bool operator < (const Node& a,const Node& b){
    return a.x < b.x;
}
priority_queue<Node> nodes;
nodes.push(Node(1));
nodes.push(Node(3));
nodes.push(Node(2));
while(!nodes.empty()){
    cout << nodes.top().x<<endl;
    nodes.pop();
}


输出:

3

2

1

或者这么用:

struct Node 
{
    int x,y;
    Node(int a = 0):x(a){}


};
struct nodecmp
{
    bool operator()(Node a,Node b){
        return a.x > b.x ;
    }
};

priority_queue<Node,vector<Node>,nodecmp> nodes2;
nodes2.push(Node(1));
nodes2.push(Node(3));
nodes2.push(Node(2));
while(!nodes2.empty()){
    cout << nodes2.top().x<<endl;
    nodes2.pop();
}

输出:

1

2

3

=====================

priority_queue还可以参考这个哥们的页面:

http://blog.csdn.net/sraing/article/details/6256302

=====================


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STL(Standard Template Library)是C++标准库的一个重要组成部分,它提供了一系列的模板类和函数,用于实现常见的数据结构和算法。STL在实际项目有广泛的应用,以下是一些常见的应用场景: 1. 列表(List):STL的列表是一个双向链表,可以用于存储和操作一系列的元素。在实际项目,列表常用于实现队列、栈和链表等数据结构。 2. 向量(Vector):STL的向量是一个动态数组,可以自动调整大小。向量在实际项目常用于存储和操作一系列的元素,特别适用于需要频繁访问和修改元素的场景。 3. Heap):STL是一个优先队列,可以用于实现排序和优先级队列等算法。在实际项目常用于任务调度、事件处理和资源管理等场景。 4. 排序(Sort):STL提供了多种排序算法,如快速排序、归并排序和排序等。排序算法在实际项目常用于对数据进行排序和查找。 5. 搜索(Search):STL提供了多种搜索算法,如二分查找和线性查找等。搜索算法在实际项目常用于在有序数组或列表查找特定元素。 6. 字符串匹配(String Matching):STL提供了多种字符串匹配算法,如Boyer-Moore和Knuth-Morris-Pratt等。字符串匹配算法在实际项目常用于文本搜索和模式匹配等场景。 STL的应用不仅限于上述场景,它还可以用于图算法、数值计算、图形处理和网络编程等领域。通过使用STL,开发人员可以更高效地实现各种数据结构和算法,提高代码的可读性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值