优先级队列Priority_queue

定义

拥有权值观点的queue,,一个是返回最高优先级对象,一个是在底端添加新的对象。这种数据结构就是优先级队列(Priority Queue) 。

实现

利用max_heap完成,以vector表现的完全二叉堆。max_heap可以满足priority_heap所需要的依照权值高低自动递减的特性。

二叉堆

二叉堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。 有了这一性质,那么二叉堆上最大值就是根节点了。

二叉堆的表现形式:我们可以使用数组的索引来表示元素在二叉堆中的位置。

从二叉堆中,我们可以得出:

· 元素k的父节点所在的位置为[k/2]

· 元素k的子节点所在的位置为2k和2k+1

跟据以上规则,我们可以使用二维数组的索引来表示二叉堆。通过二叉堆,我们可以实现插入和删除最大值都达到O(nlogn)的时间复杂度。

对于堆来说,最大元素已经位于根节点,那么删除操作就是移除并返回根节点元素,这时候二叉堆就需要重新排列;当插入新的元素的时候,也需要重新排列二叉堆以满足二叉堆的定义。现在就来看这两种操作。

从下至上的重新建堆操作: 如果一个节点的值大于其父节点的值,那么该节点就需要上移,一直到满足该节点大于其两个子节点,而小于其根节点为止,从而达到使整个堆实现二叉堆的要求。

由上图可以看到,我们只需要将该元素k和其父元素k/2进行比较,如果比父元素大,则交换,然后迭代,一直到比父元素小为止。

private static void Swim(int k)
{
    //如果元素比其父元素大,则交换
    while (k > 1 && pq[k].CompareTo(pq[k / 2]) > 0)
    {
        Swap(pq, k, k / 2);
        k = k / 2;
    }
}

这样,往堆中插入新元素的操作变成了,将该元素从下往上重新建堆操作:

代码实现如下:

public static void Insert(T s)
{
    //将元素添加到数组末尾
    pq[++N] = s;
    //然后让该元素从下至上重建堆
    Swim(N);
}

动画如下:

由上至下的重新建堆操作:当某一节点比其子节点要小的时候,就违反了二叉堆的定义,需要和其子节点进行交换以重新建堆,直到该节点都大于其子节点为止:

代码实现如下:

private static void Sink(int k)
{
    while (2 * k < N)
    {
        int j = 2 * k;
        //去左右子节点中,稍大的那个元素做比较
        if (pq[j].CompareTo(pq[j + 1]) < 0) j++;
        //如果父节点比这个较大的元素还大,表示满足要求,退出
        if (pq[k].CompareTo(pq[j]) > 0) break;
        //否则,与子节点进行交换
        Swap(pq, k, j);
        k = j;
    }
}

这样,移除并返回最大元素操作DelMax可以变为:

1. 移除二叉堆根节点元素,并返回

2. 将数组中最后一个元素放到根节点位置

3. 然后对新的根节点元素进行Sink操作,直到满足二叉堆要求。

移除最大值并返回的操作如下图所示:

以上操作的实现如下:

public static T DelMax()
{
    //根元素从1开始,0不存放值
    T max = pq[1];
    //将最后一个元素和根节点元素进行交换
    Swap(pq, 1, N--);
    //对根节点从上至下重新建堆
    Sink(1);
    //将最后一个元素置为空
    pq[N + 1] = default(T);
    return max;
}

动画如下:

时间: 2025-01-10 22:56:53

优先级队列Priority_queue的相关文章

STL学习系列七:优先级队列priority_queue容器

1.简介 最大值优先级队列.最小值优先级队列 优先级队列适配器 STL priority_queue 用来开发一些特殊的应用,请对stl的类库,多做扩展性学习 如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了.这样,我们就引入了优先级队列 这种数据结构. 优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一

C++ - 库函数优先级队列(priority_queue)输出最小值 代码

库函数优先级队列(priority_queue)输出最小值 代码 本文地址: http://blog.csdn.net/caroline_wendy 库函数优先级队列(priority_queue)的实现方式是堆(heap), 默认是输出最大值. 输出最小值, 须要指定參数, priority_queue<int, vector<int>, greater<int> > 代码: /* * main.cpp * * Created on: 2014.7.20 * Auth

c++ 优先级队列(priority_queue)

从网上搜优先级队列用法,都是有些乱七八糟的,有几种用法都没说,直接贴代码.实在郁闷,于是自己在此归纳归纳. 废话不多说,直入主题. 优先级队列的核心是比较函数的实现. 比较函数有两种实现方法: 1.在结构体或类外面定义一个比较结构体.  //假如有个Point结构体.则new对象的时候:priority_queue<Point,vector<Point>,cmp> pg;其中cmp是自定义比较函数 2.在结构体或类中自己重载<操作符.   //假如有个Point结构体.这种方

STL之优先级队列priority_queue

摘要: priority_queue,自适应容器(即容器适配器):不能由list来组建: 最大值优先级队列(最大值始终在对首,push进去时候) 最小值优先级队列: 优先级队列适配器 STL  priority_queue priority_queue<int, deque<int> > pg; priority_queue<int, vector<int> > pg; STL中实现的方法: pg.empty(); pg.size(); pg.top();

STL中的优先级队列priority_queue

priority_queue(queue类似)完全以底部容器为根据,再加上二叉堆(大根堆或者小根堆)的实现原理,所以其实现非常简单,缺省情况下priority_queue以vector作为底部容器.另外priority_queue缺省比较规则是less: class Compare = less<typename Sequence::value_type> less对应的是按照大根堆来实现优先级队列,当然也可以将比较规则设置为greater,这时候是按照小根堆来实现的优先级队列. priori

priority_queue 优先级队列

priority_queue 优先级队列是一个拥有权值概念的单向队列queue,在这个队列中,所有元素是按优先级排列的(也可以认为queue是个按进入队列的先后做为优先级的优先级队列——先进入队列的元素优先权要高于后进入队列的元素).在计算机操作系统中,优先级队列的使用是相当频繁的,进线程调度都会用到.在STL的具体实现中,priority_queue也是以别的容器作为底部结构,再根据堆的处理规则来调整元素之间的位置.下面给出priority_queue的函数列表和VS2008中priority

经典白话算法之优先级队列

<1>概念 优先级队列,顾名思义,就是一种根据一定优先级存储和取出数据的队列.它可以说是队列和排序的完美结合体,不仅可以存储数据,还可以将这些数据按照我们设定的规则进行排序.优先级队列是堆的一种常见应用.有最大优先级队列(最大堆)和最小优先级队列(最小堆).优先级队列是一种维护有一组元素构成的集合S的数据结构. <2>优先队列支持的基本运算 [cpp] view plaincopy //建立一个保存元素为int的优先级队列,其实是建了一个小顶堆 //但是请特别注意这样的建的堆默认是

STL源码笔记(14)—堆和优先级队列(一)

STL源码笔记(14)-堆和优先级队列 priority_queue是拥有权值观念的queue,跟queue类似,其只能在一端push,一端pop,不同的是,每次push元素之后再容器内部元素将按照一定次序排列,使得pop得到的元素始终是当前权值的极大值. 很显然,满足这个条件就需要某些机制了,缺省情况下使用max-heap大顶堆来实现,联想堆排序的实现,使用大顶完成序列从小到大的排序,过程大概是: 把堆的根元素(堆中极大值)交换到最后 堆的长度减1 这样每次取出堆中的极大值完成排序,刚好与优先

STL-优先级队列-priority_queue

头文件是<queue> 操作很简单 #include <iostream> #include <cstdio> #include <queue> using namespace std; int main() { // 默认定义最大值优先级队列 priority_queue<int> p1; p1.push(12); p1.push(44); p1.push(4); cout<<p1.top()<<endl; p1.pop