zoukankan      html  css  js  c++  java
  • C++之priority_queue

    前言

    最近越来越觉得自己总结的事情越来越流水账,因此,我需要提高我总结内容的精度。所以可能会导致写博客的时间会延长一些。

    之前从没用过优先队列,刷算法题目的时候才开始了解的,所以做个总结。什么情况下使用呢?比如当你需要获取到最大最小值元素,而又不想用最大最小堆的原生实现,STL提供给你更加简单的库,就是priority_queue,其时间复杂度也只有o(nlogn)。

    说明

    根据元素的优先级被读取,这个优先级取决于你设置的排序函数,如果你没设置,缺省的排序法则则是利用operator<形成降序排列,也就是从大到小排列的大顶堆,第一个自然就是最大的元素。还有如果你没设置保存数据的容器Container的话,默认用的是vector。

    namespace std {
        template < class T ,
               class Container = vector<T> ,
               class Compare = less <typename Container::value_type> >
        class priority_queue ;
    }
    

    priority_queue提供了三个基本函数,分别是:

    1. top()
    2. push()
    3. pop()

    注意,pop并不会返回元素,top才会返回堆顶的元素。

    STL提供了仿函数greater<>,less<>,简化了自己再定义排序函数的过程。如果你想使用自己定义的结构,而不想使用基本数据类型,也是ok的,不过你需要在你自定义的类中重载运算符,比如:

    class Student
    {
        int id;
        char name[20];
        bool gender;
        bool operator < (Student &a) const
        {
            return id > a.id;
        }
    };
    
    

    使用

    这是一个找输入流的中间值的题目,用最大最小堆实现。

    
    priority_queue<int, vector<int>, less<int>> maxHeap; //存储小的值,值越大,优先级越高
    priority_queue<int, vector<int>, greater<int>> minHeap; //存储大的值,值越小,优先级越高
    
    /**
     *  完全不需要判断各种判断
     *  不过一定要注意minHeap和maxHeap的优先级顺序,避免弄反了
     */
    void addNum3(int num) {
        minHeap.push(num);
        maxHeap.push(minHeap.top());
        minHeap.pop();
        // 平衡
        if (minHeap.size() < maxHeap.size()) {
            minHeap.push(maxHeap.top());
            maxHeap.pop();
        }
    }
        
    double findMedian3() {
        return maxHeap.size() == minHeap.size() ? (double)(maxHeap.top() + minHeap.top())/2.0 : (double)minHeap.top()/1.0;
    }
        
    void test() {
        this->addNum3(1);
        this->addNum3(2);
        
        cout << this->findMedian3() << endl;
        
        this->addNum2(3);
        
        cout << this->findMedian3() << endl;
    }
    
    

    底层实现

    显然,我们可以看出priority_queue的底层实现是堆实现的。里面的c就是你自己提供的容器Container。

    void push(value_type&& _Val)
        {    // insert element at beginning
        c.push_back(_STD move(_Val));
        push_heap(c.begin(), c.end(), comp);
        }
    
    template<class... _Valty>
        void emplace(_Valty&&... _Val)
        {    // insert element at beginning
        c.emplace_back(_STD forward<_Valty>(_Val)...);
        push_heap(c.begin(), c.end(), comp);
        }
    
    
    bool empty() const
        {    // test if queue is empty
        return (c.empty());
        }
    
    size_type size() const
        {    // return length of queue
        return (c.size());
        }
    
    const_reference top() const
        {    // return highest-priority element
        return (c.front());
        }
    
    void push(const value_type& _Val)
        {    // insert value in priority order
        c.push_back(_Val);
        push_heap(c.begin(), c.end(), comp);
        }
    
    void pop()
        {    // erase highest-priority element
        pop_heap(c.begin(), c.end(), comp);
        c.pop_back();
        }
    
  • 相关阅读:
    JSON、JSONObject、JavaBean三者的相互转换
    Redis下载安装及设置密码
    Git撤销已经提交的 commit
    SpringBoot文件上传、删除及下载
    JavaScript 获取当前系统时间(精确到天)
    Python搭建简易HTTP服务(3.x版本和2.x版本的)
    20151017第一天
    js知识点: 数组
    jQuery事件委托方法 bind live delegate on
    数组去重的方法
  • 原文地址:https://www.cnblogs.com/George1994/p/6477198.html
Copyright © 2011-2022 走看看