『C++ - STL』之优先级队列( priority_queue )

这篇具有很好参考价值的文章主要介绍了『C++ - STL』之优先级队列( priority_queue )。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

什么是优先级队列,从该名中可以知道他一定有队列的一定属性,即先入先出(LILO),而这里的优先级则可以判断出它的另一个特点就是可以按照一定的条件将符合该条件的先进行出队,这就是优先级队列;
而在数据结构中有一个支持该操作的结构 - 堆( heap );
而在STL中,这个优先级队列( priority_queue )也正是堆;


优先级队列的结构

既然优先级队列的结构是堆,那想必结构上也不难;
堆的结构是以顺序表为基础,从而实现完全二叉树的结构;
『C++ - STL』之优先级队列( priority_queue ),C++,数据结构,c++,开发语言,stl

从该容器的接函数接口中也可以知道实际上它就是个堆;『C++ - STL』之优先级队列( priority_queue ),C++,数据结构,c++,开发语言,stl


优先级队列的模拟实现

优先级队列priority_queue为一个类模板容器;
且同STL中的栈stack与队列queue一样都为适配器模式的容器,即以某个容器为基础;

template <class T, class Container = vector<T>,class Compare = less<typename Container::value_type> > class priority_queue;
其模板参数有三个分别为:

  • class T
    容器所存储的数据类型 T ;

  • class Container = vector<T>
    容器适配器且定缺省参数默认为 vector< T >;

  • class Compare = less<typename Container::value_type>
    一个用来比较大小的仿函数,给定缺省参数默认为 less ,该仿函数在标准库std中;

根据文档中的信息来看,优先级队列主要的几个接口也正是数据结构中堆应有的结构;

#pragma once 

#include<iostream>

#include<vector>

#include<assert.h>

using namespace std;

namespace my_priority{//命名空间


  template<class T,class Container = std::vector<T>>//暂未设置仿函数

    class priority_queue{//总体框架
 public:
        void push(const T& val){//增
          _con.push_back(val);
          adjust_up(_con.size()-1);
        }

        void pop(){
          
          std::swap( _con[_con.size()-1],_con[0]);//删
          _con.pop_back();
          adjust_down(0);

        }

        bool empty(){//判空

          return _con.empty();
        }

        size_t size(){//返回大小

          return _con.size();
        }

        const T& top()const{//返回堆顶

          assert(!_con.empty());
          return _con[0];
 }

        void swap(priority_queue& con){//交换
          if(_con!=con._con)
          _con.swap(con._con);
        }

      private:

	//必要函数 - 向上调整&&向下调整

        void adjust_up(size_t child){
          size_t parent = child;
          while(parent>0){
            parent = (child-1)/2;
            if(_con[parent]<_con[child]){
              std::swap(_con[parent],_con[child]);
            }
            child = parent;
          }

        }

        void adjust_down(size_t parent){
          Compare comfunc;
          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]){
              std::swap(_con[parent],_con[child]);
            }
            parent = child;
            child = parent*2+1;
          }
        }

        Container _con; //容器适配器所实例化的对象,当前代码为vector<int>
    };

但是在库中,模板参数共有三个,具体的第三个仿函数到底是什么?


仿函数

仿函数,也被称为函数对象;
即一个可以使用函数功能的类,本质上就是在类中重载了operator();
举个简单的例子,当我们想要写一个能将两个数进行相加的仿函数即可以这么写;

struct Add{
	int operator()(int a,int b){
		return a+b;
	} 
}
int main()
{
	Add addfunc;
	int ret = addfunc(1,2);//仿函数的调用;
	ret = Add() (1,2);//利用匿名对象;
	return 0;
}

同理,也可以根据该方法写一个比较两个对象大小的仿函数;
为了能接受多种类型的数据进行比较也可以将其设置为类模板;

template<class T>
struct less{
	bool operator()(const T& a,const T& b){
		return a<b;
	} 

这也就是在实现当中缺失的模板参数,仿函数;
由于优先级队列priority_queue的大小根堆属性是由其中的向上调整算法adjust_up与向下调整算法adjust_down来决定的(建堆以及堆的调整);所以只要将对应的比较大小><换成仿函数即可;
文章来源地址https://www.toymoban.com/news/detail-723189.html


最终代码

#pragma once 

#include<iostream>

#include<vector>

#include<assert.h>

using namespace std;

namespace my_priority{

  template<class T>
    struct less{
      bool operator()(const T& v1,const T& v2){
        return v1<v2;
      }
    };

  template<class T>
    struct greater{
      bool operator()(const T& v1,const T& v2){
        return v1>v2;
      }
    };

  template<class T,class Container = std::vector<T> ,class Compare = less<T>>

    class priority_queue{
 public:
        void push(const T& val){
          _con.push_back(val);
          adjust_up(_con.size()-1);
        }

        void pop(){
          
          std::swap( _con[_con.size()-1],_con[0]);
          _con.pop_back();
          adjust_down(0);

        }

        bool empty(){

          return _con.empty();
        }

        size_t size(){

          return _con.size();
        }

        const T& top()const{

          assert(!_con.empty());
          return _con[0];
 }

        void swap(priority_queue& con){
          if(_con!=con._con)
          _con.swap(con._con);
        }

      private:

        void adjust_up(size_t child){
          Compare comfunc;
          size_t parent = child;
          while(parent>0){
            parent = (child-1)/2;
            if(comfunc(_con[parent],_con[child])){
              std::swap(_con[parent],_con[child]);
            }
            child = parent;
          }

        }

        void adjust_down(size_t parent){
          Compare comfunc;
          size_t child = parent*2+1;
          while(child<_con.size()){
            if(child+1<_con.size()&&comfunc(_con[child],_con[child+1])){
              ++child;
            }if(comfunc(_con[parent],_con[child])){
              std::swap(_con[parent],_con[child]);
            }
            parent = child;
            child = parent*2+1;
          }

        }

        Container _con;
    };

到了这里,关于『C++ - STL』之优先级队列( priority_queue )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】模拟实现优先级队列priority_queue

    👦个人主页:@Weraphael ✍🏻作者简介:目前学习C++和算法 ✈️专栏:C++航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨ 优先级队列顾名思义就是 按优先级出队列 priority_queue 是一个容器适配器,默认使用

    2024年02月10日
    浏览(29)
  • 【C++】详解priority_queue(优先级队列)与函数对象

    目录 一、priority_queue 的介绍和使用 1.1priority_queue 的介绍 2.2priority_queue 的使用 二、仿函数 2.1什么是仿函数 2.2仿函数的作用 三、函数对象的特点(知识点多) 3.1分析特点5(比较普通函数与函数对象) 3.1.1利用普通函数传递参数 拓展之:深度剖析函数利用模板的本质 3.1.2利用

    2024年02月08日
    浏览(29)
  • C++——优先级队列(priority_queue)的使用及实现

    目录 一.priority_queue的使用 1.1、基本介绍 1.2、优先级队列的定义 1.3、基本操作(常见接口的使用) 1.4、重写仿函数支持自定义数据类型 二.priority_queue的模拟实现 2.1、构造重要的调整算法 2.2、常见接口的实现 push() pop() top() empty()、size()  三.利用仿函数改进调整算法 我们之前

    2024年02月02日
    浏览(29)
  • 优先级队列priority_queue

    关于less建大根堆,输出降序序列,greater建小根堆,输出升序序列,这点和sort()函数相反,参考我的这篇博客 底层原理 priority_queue底层维护着一个对应类型的,vector物理结构,但相当于堆排序的结构,这个vector逻辑结构是一个二叉堆; 每次 插入数据 ,我们插在堆尾(vector尾),

    2024年02月16日
    浏览(30)
  • 优先级队列priority_queue模拟实现

    🌟🌟hello,各位读者大大们你们好呀🌟🌟 🚀🚀系列专栏:【C++的学习】 📝📝本篇内容:C++容器优先级队列priority_queue模拟实现 ⬆⬆⬆⬆上一篇:string模拟实现 💖💖作者简介:轩情吖,请多多指教( •̀֊•́ ) ̖́- ①优先级队列是一种容器适配器,它的第一个元素总是

    2024年02月02日
    浏览(26)
  • [C++] STL_priority_queue(优先级队列) 的使用及底层的模拟实现,容器适配器,deque的原理介绍

    priority_queue文档介绍 翻译: 1. 优先队列是一种 容器适配器 ,根据严格的弱排序标准, 它的第一个元素总是它所包含的元素中最大的。 2. 此上下文类似于 堆 , 在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。 3. 优先队列被实现为容器适配

    2024年02月04日
    浏览(35)
  • 从C语言到C++_20(仿函数+优先级队列priority_queue的模拟实现+反向迭代器)

    目录 1. priority_queue的模拟实现 1.1 未完全的priority_queue 1.2 迭代器区间构造和无参构造 1.3 仿函数的介绍和使用 1.4 完整priority_queue代码: 1.5 相关笔试选择题 答案: 2. 反向迭代器 2.1 反向迭代器的普通实现 reverse_iterator.h(不对称版) 2.2 反向迭代器的对称实现 reverse_iterator.

    2024年02月10日
    浏览(38)
  • 【C++入门到精通】C++入门 —— priority_queue(STL)优先队列

    ⭕文章绑定了VS平台下std::priority_queue的源码,大家可以下载了解一下😍 前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的命名空间的一些知识点以及关于C++的缺省参数、函数重载,引用 和 内联函数也认识了什么是类和对象以及怎么去new一个 ‘对象

    2024年02月12日
    浏览(32)
  • C++基础(三)——STL优先级队列

    模板输入 1、元素类型 2、容器类型 3、函数对象类型 priority_queueint name; priority_queue默认为大顶堆 故定义也可以写作: priority_queueint, vectorint, lessint ay; 如果需要构建一个小顶堆,可以改变定义方式为: priority_queueint, vectorint, greaterint ay; 使用std::greater模板无需自定义比较函数。

    2024年02月09日
    浏览(43)
  • C++ STL学习之【优先级队列】

    ✨个人主页: 北 海 🎉所属专栏: C++修行之路 🎃操作环境: Visual Studio 2019 版本 16.11.17 优先级队列 priority_queue 是容器适配器中的一种,常用来进行对数据进行优先级处理,比如优先级高的值在前面,这其实就是初阶数据结构中的 堆 ,它俩本质上是一样东西,底层都是以数

    2024年02月05日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包