C++STL详解(七)——priority_queue的使用和模拟实现
创始人
2024-06-03 20:22:27
0

文章目录

  • priority_queue的使用
      • priority_queue的介绍
      • priority_queue的定义方式
      • priority_queue各个接口的使用
  • priority_queue的模拟实现
      • 堆的向上调整
      • 堆的向下调整
      • 迭代器区间构造
      • 仿函数
      • priority_queue的模拟实现完整代码

priority_queue的使用

priority_queue的介绍

优先级队列默认使用vector作为底层的存储的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priorityda_queue。
注意
默认情况下priority_queue是大堆。

priority_queue的定义方式

方式一
使用的是vector作为底层存储容器,内部为构造为大堆结构。

//大堆
priority_queue, less> q1;

方式二
使用vector作为底层容器,内部构造为小堆结构。

	//小堆
priority_queue, greater> q2;

方式三
不指定底层容器和内部构造的大小堆结构,此时编译器默认使用构造大堆结构。

priority_queue q;

priority_queue各个接口的使用

在这里插入图片描述

例如

int main()
{priority_queue q1;q1.push(3);q1.push(1);q1.push(2);q1.push(4);q1.push(6);q1.push(5);while (!q1.empty()){cout << q1.top() << " ";q1.pop();}q1.push(1);cout << q1.size() << endl;
}

priority_queue的模拟实现

我们知道priority_queue的底层实际上就是堆,所以我们必须先了解一下堆的两种调整。

堆的向上调整

时间复杂度

O(n) = log(n)

基本思路
在大根堆的情况下:
1:传孩子,求父亲。

2: 如果子结点大于父亲结点,就交换子节点与它的父节点的位置,此时子节点就等于原来父亲的结点。

3: 然后又通该子节点向上求得它的父节点,进行循环比较父子结点的大小。

4: 当子节点为0时,就已经与跟结点交换了,循环结束。( 不能使用parent>=0这个条件,当parent = 0,父子结点交换后,此时再计算parent时取整还是等于0,不可能为负数,此时便会无限循环。)

堆的向上调整代码

void AdjustUp( size_t child ) 
{size_t parent = ( child - 1 ) / 2;while ( child > 0 ) {if( _con[parent] < _con[child] ){swap( _con[parent],_con[child]);child = parent;parent = ( child -1 ) / 2;}//如果子节点不大于父节点,就不用交换了。else{ break;}}
}

堆的向下调整

时间复杂度;
log(n)
基本思路
在大根堆的情况下:
1: 传父亲,求孩子。

2:我们先要求父亲中左右孩子最大的那一个。

注意:使用[]比较时最好先判断一下右孩子必须在的情况。

3: 循环两个步骤: 一直循环的最好情况就是孩子没有超过最后一个数的下标。
如果选出的孩子大于父亲,就交换,并且原来孩子的下标等于父亲的下标。

如果左右孩子都不大于父亲,就说明不用交换,向下调整成功。

      void adjust_down ( size_t parent){//求出左孩子下标size_t child = parent* 2 + 1;while( child < _con.size() ) {//有了右孩子才可以左右孩子比较。if( child + 1 < _con.size() && _con[child]< _con[child+1]){child++;} if( _con[parent] < _con[child] ){swap( _con[parent], _con[child]);parent = child;child = parent* 2 + 1;   }else {break;}}}

迭代器区间构造

时间复杂度:
Nlog(N)
先插入对应的迭代器区间,然后从最后一个数据的父节点开始向下建堆。

template< InputIterator >
priority_queue( InputIterator first, InputIterator last )
{while( first != last ){_con.push_back(*first);++first;}         for ( int i = ( _con.size() - 1 - 1 / 2;  i >= 0 ; -- i ) {adjust_down();}
}

仿函数

调用仿函数时,就像调用lsFunc.operator()(1,2)一样。用来比较大小。

         templateclass Less{public:bool operator()( const T& l, const T& r ){return l < r;}};templateclass greater{public:bool operator()( const T& l,const T& r ){return l > r;}};less lsFunc;cout << lsFunc(1, 2) << " ";

priority_queue的模拟实现完整代码

namespace yzh
{ //模板参数代表的类型,根据实参转换为对应的类型。template < class T, Container = vector, class Compare = std:: greater(T) >class priority_queue{public://显示写了,会通过初始化列表在初始化列表内进行初始化,或者调用默认构造。priority_queue(){}  templatepriority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);}for( int i = ( _con.size() -1 -1 ) /2;i >= 0; --i  ){adjust_down();}}void push( const T& x ){_con.push_back(x);adjust_up(_con.size() -1 );}//堆的删除是将第一个数据与最后一个元素进行交换,再将最后一个元素删除。//然后再用向下调整的方式调整堆顶。void pop (){std::swap( _con[0], _con[_con.size() - 1 ] );_con.pop_back();adjust_down();}//堆顶只可读不可以修改。const T top() const{assert(!empty() );return_con[0];}size_t size() const{return _con.size();} bool empty() const {return _con.empty();}
private:Container _con;		}
}

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...