【STL学习】优先级队列Priority Queue详解与C++编程实现
优先级队列Priority Queue介绍
优先级队列是一个拥有权值观念的queue。它允许在底端添加元素、在顶端去除元素、删除元素。
优先级队列内部的元素并不是按照添加的顺序排列,而是自动依照元素的权值排列。权值最高者排在最前面。
缺省情况下,优先级队列利用一个大顶堆完成。关于堆可以参考:STL堆详解与编程实现
优先级队列以底部容器完成其所有工作,具有这种“修改某物接口,形成另一种风貌”这种性质者,成为配接器(adapter)。在STL中优先级队列不被归类为容器,而被归类为容器配接器(container adapter)。
SGI STL中优先级队列定义
定义完整代码:
template <class T, class Sequence = vector<T>, class Compare = less<typename Sequence::value_type> >
class priority_queue {
public: typedef typename Sequence::value_type value_type; typedef typename Sequence::size_type size_type; typedef typename Sequence::reference reference; typedef typename Sequence::const_referenceconst_reference;
protected:
Sequence c; //底层容器 Compare comp;//元素大小比较标准
public:
priority_queue() : c() {} explicit priority_queue(const Compare& x) : c(), comp(x) {} //以下用到的 make_heap(), push_heap(), pop_heap()都是泛型算法
//注意,任一个建构式都立刻于底层容器内产生一个 implicit representation heap。 template <class InputIterator>
priority_queue(InputIterator first, InputIterator last, const Compare& x) : c(first, last), comp(x) {make_heap(c.begin(), c.end(), comp); } template <class InputIterator>
priority_queue(InputIterator first, InputIterator last) : c(first, last) { make_heap(c.begin(), c.end(), comp); } bool empty() const { return c.empty(); } size_typesize() const { return c.size(); } const_referencetop() const { return c.front(); } void push(const value_type& x) { __STL_TRY {
// push_heap是泛型算法,先利用底层容器的 push_back() 将新元素 // 推入端,再重排 heap。见 C++ Primer p.1195。
c.push_back(x);
push_heap(c.begin(), c.end(), comp);// push_heap是泛型算法 } __STL_UNWIND(c.clear()); } void pop() { __STL_TRY {
// pop_heap 是泛型算法,从 heap 内取出一个元素。它并不是真正将元素 // 弹出,而是重排 heap,然后再以底层容器的 pop_back() 取得被弹出 // 的元素。见 C++ Primer p.1195。
pop_heap(c.begin(), c.end(), comp);
c.pop_back(); } __STL_UNWIND(c.clear()); }
};
优先级队列编程实现(C Plus Plus)
在这里自己用C++编程实现了简易版的优先级队列。其中用到了前一篇博客里面的堆heap.h:
//STL堆算法实现(大顶堆)//包含容器vector的头文件:Heap用vector来存储元素
#include <vector>
#include <iostream>
#include <functional>#define MAX_VALUE 999999 //某个很大的值,存放在vector的第一个位置(最大堆)const int StartIndex = 1;//容器中堆元素起始索引using namespace std;//堆类定义
//默认比较规则less
template <class ElemType,class Compare = less<ElemType> >
class MyHeap{
private:vector<ElemType> heapDataVec;//存放元素的容器int numCounts;//堆中元素个数Compare comp;//比较规则public:MyHeap();vector<ElemType>& getVec();void initHeap(ElemType *data,const int n);//初始化操作void printfHeap();//输出堆元素void makeHeap();//建堆void sortHeap();//堆排序算法void pushHeap(ElemType elem);//向堆中插入元素void popHeap();//从堆中取出堆顶的元素void adjustHeap(int childTree,ElemType adjustValue);//调整子树void percolateUp(int holeIndex,ElemType adjustValue);//上溯操作void setNumCounts(int val);//设置当前所要构建的堆中元素个数
};template <class ElemType,class Compare>
MyHeap<ElemType,Compare>::MyHeap()
:numCounts(0)
{heapDataVec.push_back(MAX_VALUE);
}template <class ElemType,class Compare>
vector<ElemType>& MyHeap<ElemType,Compare>::getVec()
{return heapDataVec;
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::initHeap(ElemType *data,const int n)
{//拷贝元素数据到vector中for (int i = 0;i < n;++i){heapDataVec.push_back(*(data + i));++numCounts;}
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::printfHeap()
{cout << "Heap : ";for (int i = 1;i <= numCounts;++i){cout << heapDataVec[i] << " ";}cout << endl;
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::makeHeap()
{//建堆的过程就是一个不断调整堆的过程,循环调用函数adjustHeap依次调整子树if (numCounts < 2)return;//第一个需要调整的子树的根节点多音int parent = numCounts / 2;while(1){adjustHeap(parent,heapDataVec[parent]);if (StartIndex == parent)//到达根节点return;--parent;}
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::sortHeap()
{//堆排序思路//每执行一次popHeap操作,堆顶的元素被放置在尾端,然后针对前面的一次再执行popHeap操作//依次下去,最后即得到排序结果while(numCounts > 0)popHeap();
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::pushHeap(ElemType elem)
{//将新元素添加到vector中heapDataVec.push_back(elem);++numCounts;//执行一次上溯操作,调整堆,以使其满足最大堆的性质percolateUp(numCounts,heapDataVec[numCounts]);
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::popHeap()
{//将堆顶的元素放在容器的最尾部,然后将尾部的原元素作为调整值,重新生成堆ElemType adjustValue = heapDataVec[numCounts];//堆顶元素为容器的首元素heapDataVec[numCounts] = heapDataVec[StartIndex];//堆中元素数目减一--numCounts;adjustHeap(StartIndex,adjustValue);
}//调整以childTree为根的子树为堆
template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::adjustHeap(int childTree,ElemType adjustValue)
{//洞节点索引int holeIndex = childTree;int secondChid = 2 * holeIndex + 1;//洞节点的右子节点(注意:起始索引从1开始)while(secondChid <= numCounts){if (comp(heapDataVec[secondChid],heapDataVec[secondChid - 1])){--secondChid;//表示两个子节点中值较大的那个}//上溯heapDataVec[holeIndex] = heapDataVec[secondChid];//令较大值为洞值holeIndex = secondChid;//洞节点索引下移secondChid = 2 * secondChid + 1;//重新计算洞节点右子节点}//如果洞节点只有左子节点if (secondChid == numCounts + 1){//令左子节点值为洞值heapDataVec[holeIndex] = heapDataVec[secondChid - 1];holeIndex = secondChid - 1;}//将调整值赋予洞节点heapDataVec[holeIndex] = adjustValue;//此时可能尚未满足堆的特性,需要再执行一次上溯操作percolateUp(holeIndex,adjustValue);
}//上溯操作
template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::percolateUp(int holeIndex,ElemType adjustValue)
{//将新节点与其父节点进行比较,如果键值比其父节点大,就父子交换位置。//如此,知道不需要对换或直到根节点为止int parentIndex = holeIndex / 2;while(holeIndex > StartIndex && comp(heapDataVec[parentIndex],adjustValue)){heapDataVec[holeIndex] = heapDataVec[parentIndex];holeIndex = parentIndex;parentIndex /= 2;}heapDataVec[holeIndex] = adjustValue;//将新值放置在正确的位置
}template <class ElemType,class Compare>
void MyHeap<ElemType,Compare>::setNumCounts(int val)
{numCounts = val;
}
PriorityQueue.h:
#include "Heap.h"//优先级队列类定义
//默认:值最小的权值最大
template <class ElemType,class Compare = less<ElemType> >
class MyPriorityQueue{
private:MyHeap<ElemType,Compare> heap;//底层用堆实现public://构造函数MyPriorityQueue(ElemType *data,int n);//判断优先级队列是否为空int empty(){return heap.getVec().size() - 1;}//返回优先级队列大小long size(){return heap.getVec().size() - 1;}//注意底层容器第一个元素是无效元素//取得优先级队列头元素ElemType top(){return heap.getVec()[StartIndex];}//添加元素void push(const ElemType &val);//弹出队首元素void pop();MyHeap<ElemType,Compare>& getHeap(){return heap;};
};template <class ElemType,class Compare>
MyPriorityQueue<ElemType,Compare>::MyPriorityQueue(ElemType *data, int n)
{heap.initHeap(data,n);heap.makeHeap();heap.sortHeap();
}template <class ElemType,class Compare>
void MyPriorityQueue<ElemType,Compare>::push(const ElemType &val)
{heap.setNumCounts(heap.getVec().size() - 1);//排除容器首部的哨兵元素heap.makeHeap();heap.pushHeap(val);heap.sortHeap();
}template <class ElemType,class Compare>
void MyPriorityQueue<ElemType,Compare>::pop()
{heap.getVec().erase(heap.getVec().begin() + 1);//删除队列首部的元素heap.setNumCounts(heap.getVec().size() - 1);//排除容器首部的哨兵元素heap.makeHeap();heap.sortHeap();
}
PriorityQueueTest.cpp:
#include "PriorityQueue.h"#include <iostream>
#include <string>using namespace std;int main()
{const int n = 9;int data[n] = {0,1,2,3,4,8,9,3,5};MyPriorityQueue<int> *priorityObj1 = new MyPriorityQueue<int>(data,n);cout << "Current Heap: " << endl;for (int i = 1;i <= priorityObj1->size();++i){cout << priorityObj1->getHeap().getVec()[i] << " ";}cout << endl;cout << "Size = " << priorityObj1->size() << endl;cout << "Top element = " << priorityObj1->top() << endl;priorityObj1->pop();cout << "After pop one element:" << endl;cout << "Size = " << priorityObj1->size() << endl;cout << "Top element = " << priorityObj1->top() << endl;cout << "Current Heap: " << endl;for (int i = 1;i <= priorityObj1->size();++i){cout << priorityObj1->getHeap().getVec()[i] << " ";}cout << endl;priorityObj1->pop();cout << "After pop one element:" << endl;cout << "Size = " << priorityObj1->size() << endl;cout << "Top element = " << priorityObj1->top() << endl;cout << "Current Heap: " << endl;for (int i = 1;i <= priorityObj1->size();++i){cout << priorityObj1->getHeap().getVec()[i] << " ";}cout << endl;priorityObj1->push(7);cout << "After push one element 7:" << endl;cout << "Size = " << priorityObj1->size() << endl;cout << "Top element = " << priorityObj1->top() << endl;cout << "Current Heap: " << endl;for (int i = 1;i <= priorityObj1->size();++i){cout << priorityObj1->getHeap().getVec()[i] << " ";}cout << endl;delete priorityObj1;
}
运行结果(Win7 + VS2008):
【STL学习】优先级队列Priority Queue详解与C++编程实现相关推荐
- 【STL学习】堆相关算法详解与C++编程实现(Heap)
堆简介 堆并不是STL的组件,但是经常充当着底层实现结构.比如优先级队列(Priority Queue)等等. 堆是一种完全二叉树,因此我们可以用数组来存储所有节点.在这里的实现中,采用了一个技巧:将 ...
- 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority Queue)
堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...
- 优先级队列(Priority Queue)
优先级队列(Priority Queue) 注:队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素.但是,许多应用需要另一种队列,每次从队列中取出的应是具有最高优先权的元素, ...
- C++ STL 之队列(先进先出) queue 详解
文章目录 Part.I Attention Part.II Funciton Chap.I queue Chap.II priority_queue Part.III Code Chap.I queu ...
- 什么是java优先级队列_什么是Java优先级队列(Priority Queue)?
39 优先级队列中的元素可以按照任意的顺序插入,却总是按照排序的顺序进行检索.无论何时调用remove方法,总会获得当前优先级队列中的最小元素,但并不是对所有元素都排序.它是采用了堆(一个可以自我调整 ...
- JAVA队列( Queue ) 详解
什么是队列? 队列是一种特殊的线性表,遵循先入先出.后入后出的基本原则,一般来说,它只允许在表的前端进行删除操作,而在表的后端进行插入操作,但是java的某些队列运行在任何地方插入删除:比如我们常用的 ...
- codeforces 贪心+优先队列_算法与数据结构基础 - 堆(Heap)和优先级队列(Priority Queue)...
堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值:
- C++STL之优先级队列详解
priority_queue 文章目录 priority_queue priority_queue的使用 priority_queue在OJ中的使用 数组中第k个最大元素 priority_queue ...
- 好程序员Java学习路线分享finalize()方法详解
好程序员Java学习路线分享finalize()方法详解,前言,finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法.. fi ...
最新文章
- 政、企、学三方视角下的智慧城市发展 | 2020中关村论坛“人工智能与城市可持续发展论坛”成功举办...
- OKEx比特币现金震荡 巴西央行公布新区块链项目
- c#中邮件收发处理(POP3,IMAP,SMTP)的实现方法
- docker容器的构建
- Integer的==问题
- MySQL编程技巧_MySQL学习笔记---MySQL开发技巧
- [文摘20110527] 小故事 : 大有 和 天成 都是一辈子
- ftk学习记(进度条篇)
- 揭开 Python 内存分配时的小秘密!
- leetcode刷题(32)——88. 合并两个有序数组
- STM8S003F3 开发环境搭建
- 我的Windows初始安装软件(技术型办公用电脑)
- gp3688 uhf2扩频_摩托罗拉GP3688_GP3188写频软件
- 如何在网页中插入视频
- synchronized锁升级之轻量级锁
- 最新vx红包封面小程序源码 附教程
- 学生一族必备热门手机应用软件大汇集
- 标准日本语第二十三课
- S32DS中.ld(链接)文件学习
- 【计算机体系结构】计算机系统结构的基本概念——基本知识要点汇总
热门文章
- Protobuf介绍及简单使用(下)之文件读写
- 用于故障诊断的残差收缩网络
- for _ in range(10)中 _ 的作用
- 互站卖的分发美化版可以封装双端APP
- APP论坛社区软件源码 APP封装
- 某易游戏经典吃豆豆动画404页面源码
- linux查看缓存的文件,linux – 如何查看缓冲和缓存的数据
- html5背景图片设置大小_web前端学习之HTML5前端开发的特点
- 电脑硬盘数据线_这40种电脑故障的排除技巧你都掌握了吗?
- php 取前一天时间戳,php获取时间今日明天昨天时间戳