zoukankan      html  css  js  c++  java
  • C++STL priority_queue类

    例子:

    问题:搬水果


    题目描述


            在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过 n‐1 次合并之后,就变成一堆了。小明在合并水果时总共消耗的体力等于每次合并所耗体力之和。

           假定每个水果重量都为 1,并且已知水果的种类数和每种水果的数目,你的任务是设计出合并的次序方案,使小明耗费的体力最少,并输出这个最小的体力耗费值。例如有 3 种水果,数目依次为 1,2,9。可以先将 1,2 堆合并,新堆数目为3,耗费体力为 3。然后将新堆与原先的第三堆合并得到新的堆,耗费体力为 12。所以小明总共耗费体力=3+12=15,可以证明 15 为最小的体力耗费值。


    输入格式

    每组数据输入包括两行,第一行是一个整数 n(1<=n<=10000),表示水果的种类数,如果 n 等于 0 表示输入结束,且不用处理。第二行包含 n 个整数,用空格分隔,第 i 个整数(1<=ai<=1000)是第 i 种水果的数目。

    输出

    对于每组输入,输出一个整数并换行,这个值也就是最小的体力耗费值。输入数据保证这个值小于 2^31。

    样例输入

    3

    42 708 119

    4

    749 522 629 823

    6

    55 323 489 378 618 194

    0

    样例输出

    1030

    5446

    4935


    详解priority_queue类

    priority_queue调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法实现,也算是堆的另外一种形式。先写一个用 STL 里面堆算法实现的与真正的STL里面的 priority_queue用法相似的priority_queue, 以加深对 priority_queue 的理解


    #include <iostream>

    #include <algorithm>

    #include <vector>

    using namespace std;

    class priority_queue

    {

        private:

            vector<int> data;

             

        public:

            void push( int t ){ 

                data.push_back(t); 

                push_heap( data.begin(), data.end()); 

            }

             

            void pop(){

                pop_heap( data.begin(), data.end() );

                data.pop_back();

            }

             

            int top() { return data.front(); }

            int size() { return data.size(); }

            bool empty() { return data.empty(); }

    };

    int main()

    {

        priority_queue test;

        test.push( 3 );

        test.push( 5 );

        test.push( 2 );

        test.push( 4 );

         

        while( !test.empty() ){

            cout << test.top() << endl;

            test.pop(); }

             

        return 0;

    }

    STL里面的 priority_queue 写法与此相似,只是增加了模板及相关的迭代器什么的。 


    priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数:

    priority_queue<Type, Container, Functional>

    其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。

    Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.

    STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,

    优先队列就是大顶堆,队头元素最大。

    #include <iostream>

    #include <queue>

    using namespace std;

    int main(){

        priority_queue<int> q;

         

        for( int i= 0; i< 10; ++i ) q.push( rand() );

        while( !q.empty() ){

            cout << q.top() << endl;

            q.pop();

        }

         

        getchar();

        return 0;

    }

    如果要用到小顶堆,则一般要把模板的三个参数都带进去。

    STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆

    #include <iostream>

    #include <queue>

    #include <functional>                                //greater<>在头文件functional中定义

    using namespace std;

    int main(){

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

         

        for( int i= 0; i< 10; ++i ) q.push( rand() );

        while( !q.empty() ){

            cout << q.top() << endl;

            q.pop();

        }

         

        getchar();

        return 0;

    }


    对于自定义类型,则必须自己重载 operator< 或者自己写仿函数

    #include <iostream>

    #include <queue>

    using namespace std;

    struct Node{

        int x, y;

        Node( int a= 0, int b= 0 ):

            x(a), y(b) {}

    };

    bool operator<( Node a, Node b ){

        if( a.x== b.x ) return a.y> b.y;

        return a.x> b.x; 

    }

    int main(){

        priority_queue<Node> q;

         

        for( int i= 0; i< 10; ++i )

        q.push( Node( rand(), rand() ) );

         

        while( !q.empty() ){

            cout << q.top().x << ' ' << q.top().y << endl;

            q.pop();

        }

         

        getchar();

        return 0;

    }

    自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。

    但此时不能像基本类型这样声明

    priority_queue<Node, vector<Node>, greater<Node> >;

    原因是 greater<Node> 没有定义,如果想用这种方法定义则可以按如下方式:

    #include <iostream>

    #include <queue>

    using namespace std;

    struct Node{

        int x, y;

        Node( int a= 0, int b= 0 ):

            x(a), y(b) {}

    };

    struct cmp{

        bool operator() ( Node a, Node b ){

            if( a.x== b.x ) return a.y> b.y;

             

            return a.x> b.x; }

    };

    int main(){

        priority_queue<Node, vector<Node>, cmp> q;

         

        for( int i= 0; i< 10; ++i )

        q.push( Node( rand(), rand() ) );

         

        while( !q.empty() ){

            cout << q.top().x << ' ' << q.top().y << endl;

            q.pop();

        }

         

        getchar();

        return 0;

    //以上代码实现的是一个小顶堆



    问题解决(我的源代码,代码格式复制上来就这样,请谅解.):

    #include <iostream>

    #include <queue>

    #include <vector>

    #include <functional>

    using namespace std;


    int main()

    {


    int n;

    cin >> n;

    while(n!=0)

    {

    int i;

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


    for(i = 0; i < n; i++)

    {

    int temp;

    cin >> temp;

    q.push(temp);

    }

    int result = 0;


    while(q.size() > 1)

    {

    int a = q.top();

    q.pop();

    int b = q.top();

    q.pop();

    result += a+b;

    q.push(a+b);

    }


    cout << result << endl;


    n = 0;

    cin >> n;

    }


    return 0;

    }




    LOFTER:hgfalgorithm   http://hgfal.lofter.com/post/28eef2_f96f41
  • 相关阅读:
    基础之前ORM的一个框架(在OA系统上已经应用)
    自己创建的一个ORM框架
    spring cloud+docker 简单说一说
    有价值的数据
    Axis2Service客户端访问通用类集合List自定义类型
    java.io.IOException: Cleartext HTTP traffic to e.hiphotos.baidu.com not permitted
    Android Studio 3.x 自动生成多渠道包
    单例模式
    Linux(ubuntu 18.0.4) Java环境安装,环境变量配置
    ImageLoader常用方法注释
  • 原文地址:https://www.cnblogs.com/hgfgood/p/4248316.html
Copyright © 2011-2022 走看看