C++和python: priority_queue优先队列

使用

priority_queue包含在头文件queue中,与通常的queue不同的就在于可以自定义其中数据的优先级,让优先级高的排在队列前面,优先出队,插入的效率为logn。
优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的

  • top 访问队头元素
  • empty 队列是否为空
  • size 返回队列内元素个数
  • push 插入元素到队尾 (并排序)
  • emplace 原地构造一个元素并插入队列
  • pop 弹出队头元素
  • swap 交换内容

优先队列的使用

priority_queue< type, container, function > //function后注意有空格,避免>>
  • type:数据类型;
  • container:实现优先队列的底层容器,默认vector,还有deque,不能使用list;
  • function:元素之间的比较方式,使用基本数据类型时传入数据类型,默认大顶堆;
int main(){
    priority_queue<int> pq1;//默认less<> 大顶堆降序
    priority_queue<int, vector<int>, greater<int> > pq2;//小顶堆 升序
    priority_queue<string, vector<string>, less<string>>pq3;
    for(int i=0;i<4;++i){
        pq1.push(i); pq2.push(i); pq3.push(to_string(i));
    }
    cout<<pq1.top()<<endl;
    cout<<pq2.top()<<endl;
    cout<<pq3.top()<<endl;
}

3
0
3

c++优先队列(priority_queue)用法详解

理论

priority_queue 优先级队列之所以总能保证优先级最高的元素位于队头,是因为其底层采用堆数据结构存储结构。

priority_queue 底层采用vectordeque来存储元素的容器,而堆是一种数据结构,其本身无法存储数据,只能依附于某个存储介质,辅助其组织数据存储的先后次序。其次,priority_queue 底层采用 vector 或者 deque 作为基础容器,这毋庸置疑。但由于 vector 或 deque 容器并没有提供实现 priority_queue 容器适配器 “First in,Largest out” 特性的功能,因此 STL 选择使用堆来重新组织 vector 或 deque 容器中存储的数据,从而实现该特性。

简单的理解堆,它在是完全二叉树的基础上,要求树中所有的父节点和子节点之间,都要满足既定的排序规则:

  • 如果排序规则为从大到小排序,则表示堆的完全二叉树中,每个父节点的值都要不小于子节点的值,这种堆通常称为大顶堆;
  • 如果排序规则为从小到大排序,则表示堆的完全二叉树中,每个父节点的值都要不大于子节点的值,这种堆通常称为小顶堆;

我们可以尝试用堆结合基础容器 vector 或 deque 实现 priority_queue。值得庆幸的是,STL 已经为我们封装好了可以使用堆存储结构的方法,它们都位于 头文件中。表 2 中列出了常用的几个和堆存储结构相关的方法。

待续。。。

简单实现

C++

对优先队列做了一个简单的实现,诸多不足欢迎指正~

template <typename T>
class Pqueue{
public:
    Pqueue(){
        data = make_shared<vector<T>>(1);
        sort = false;
    };
    void push(T &t){
        data->push_back(t);
        sort = false;
    }
    void push(T &&t){
        data->emplace_back(t);
        sort = false;
    }
    T& top(){
        if(!sort){
            buildHeap();
            sort = true;
        }
        return (*data)[1];
    }
    void pop(){
        int n = (int)data->size();
        if(!sort){
            buildHeap();
        }
        swap((*data)[1], (*data)[n-1]);
        data->pop_back();
        sort = false;
    }
    bool empty() const {
        return data->size()<=1;
    }
private:
    shared_ptr<vector<T>> data;
    bool sort;
    void buildHeap(){
        int n = data->size();
        for(int i=n/2;i>=1;--i){
            cmp(i, n);
        }
    }
    void cmp(int i,int n){
        int l = 2*i, r = 2*i+1, t=i;
        if(l<n && (*data)[t]<(*data)[l]) t = l;
        if(r<n && (*data)[t]<(*data)[r]) t = r;
        if(t!=i){
            swap((*data)[t], (*data)[i]);
            cmp(t, n);
        }
    }
};

python

class PriorityQueue:
    def __init__(self, func, queue=None):
        self.queue = queue if queue else [0]
        self.func = func
        self.sort = False

    def push(self, item):
        self.queue.append(item)
        self.sort = False

    def pop(self):
        if len(self.queue) <= 1:
            return
        if not self.sort:
            self.build_heap()
        self.queue[1] = self.queue[-1]
        self.queue.pop()
        self.sort = False

    def top(self):
        if len(self.queue) <= 1:
            return None
        if not self.sort:
            self.build_heap()
            self.sort = True
        return self.queue[1]

    def build_heap(self):
        n = len(self.queue)
        if n > 1:
            for i in range(n//2, 0, -1):
                self.cmp_heap(i, n)

    def cmp_heap(self, i, n):
        left, right = i << 1, (i << 1)+1
        t = i
        if left < n and self.func(self.queue[left], self.queue[t]):
            t = left
        if right < n and self.func(self.queue[right], self.queue[t]):
            t = right
        if t != i:
            self.queue[t], self.queue[i] = self.queue[i], self.queue[t]
            self.cmp_heap(t, n)

STL priority_queue底层实现(深度剖析)
自定义比较函数
C++ priority_queue 与 lambda的结合使用
ACM向:关于优先队列priority_queue自定义比较函数用法整理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值