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

news2024/11/13 9:18:55

文章目录

  • 前言
    • 优先级队列的结构
    • 优先级队列的模拟实现
      • 仿函数
    • 最终代码

前言

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


优先级队列的结构

既然优先级队列的结构是堆,那想必结构上也不难;
堆的结构是以顺序表为基础,从而实现完全二叉树的结构;
在这里插入图片描述

从该容器的接函数接口中也可以知道实际上它就是个堆;在这里插入图片描述


优先级队列的模拟实现

优先级队列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来决定的(建堆以及堆的调整);所以只要将对应的比较大小><换成仿函数即可;


最终代码

#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;
    };

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1100740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Debian衍生桌面项目SpiralLinux12.231001发布

导读SpiralLinux 是一个从 Debian 衍生出来的桌面项目&#xff0c;其重点是在所有主要桌面环境中实现简洁性和开箱即用的可用性。 spiral Linux 是为刚接触 Linux 世界的人们量身定制的发行版。这是 GeckoLinux 开发人员的创意&#xff0c;他更喜欢保持匿名。尽管他不愿透露姓…

图文详解!带你认识 ancert:硬件兼容性标准实现工具!| 龙蜥技术

编者按&#xff1a;大家都知道 OS 其实是硬件设备资源利用的抽象&#xff0c;所以 OS 和各个硬件设备之间是否兼容&#xff0c;对 OS 的稳定性是非常关键。今天&#xff0c;龙蜥社区硬件兼容性 SIG Maintainer 吴朝峰为大家介绍龙蜥社区硬件兼容性认证的步骤和流程&#xff0c…

python项目之大学生就业信息管理系统设计与实现

项目简介 大学生就业信息管理系统实现了以下功能&#xff1a; 管理员功能&#xff1a;权限认证&#xff0c;职位管理&#xff0c;企业管理&#xff0c;留言管理&#xff0c;用户管理&#xff0c;投递管理。用户功能&#xff1a;首页&#xff0c;招聘会&#xff0c;留言板&…

5.Vue-在Vue框架中实现Vue的增删改查

题记 在vue框架中实现vue的增删改查&#xff0c;以下是具体操作流程和代码 编写TestView.vue文件 TestView.vue文件如下&#xff1a; <template> <div id"app"> <h1>学生列表</h1> <input type"text" v-model"searchQue…

Nodejs原型链污染学习

文章目录 前置知识JavaScript数据类型prototype原型同步和异步child_process模块 原型链污染利用条件 前置知识 JavaScript数据类型 let和var关键字的区别 使用var或let关键字可以定义变量 let和var的区别如下&#xff1a; var是全局作用域&#xff0c;let 只在当前代码块内…

掌握Go编程中的错误处理和日志记录

构建稳健可靠应用的全面指南 错误处理是编写可靠和稳健软件应用的重要方面。在任何编程语言中&#xff0c;错误是不可避免的&#xff0c;如何处理错误会极大地影响代码的质量和稳定性。在本文中&#xff0c;我们将探索Go中的错误处理世界&#xff0c;理解其重要性&#xff0c;…

修炼k8s+flink+hdfs+dlink(五:安装dockers,cri-docker,harbor仓库)

一&#xff1a;安装docker。&#xff08;所有服务器都要安装&#xff09; 安装必要的一些系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2添加软件源信息 sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/cent…

通过商品链接查询淘宝商品详情数据,可以拿到商品标题,商品价格,商品库存,商品销量,商品sku数据等,淘宝API接口

通过商品链接查询淘宝商品详情数据可以参考以下步骤&#xff1a; 打开手机淘宝或者PC端&#xff0c;复制需要查询的商品链接。打开浏览器&#xff0c;输入商品链接&#xff0c;点击搜索。点击搜索结果中的商品链接&#xff0c;进入商品详情页面。点击鼠标右键&#xff0c;选择…

【前段基础入门之】=>CSS3新特性 3D 变换

导语 在上一章节中&#xff0c;我们分享了2D 变换的效果&#xff0c;也分享了一些案例&#xff0c;同时&#xff0c;既然有2D 变换&#xff0c;那么也就肯定有 3D 变换 那么本章节&#xff0c;就为大家带来有关3D 变换的分享. 文章目录 开启3D空间设置景深透视点位置3D 位移3D …

职场中,如何更高效地分析和解决问题(一)

要在职场取得成功&#xff0c;必须掌握多种技能。这些技能大致可分为三类&#xff1a; 一是职能性技能&#xff0c;二是分析和解决问题的技能&#xff0c;三是处理人际关系的技能。 无论在生活中还是工作中&#xff0c;我们都会面临各种问题&#xff0c;有些问题可能简单易处…

Avalonia 实现跨平台的视频聊天、屏幕分享(源码,支持Win、银河麒麟、统信UOS)

现在最火的.NET跨平台UI框架莫过于Avalonia了。Avalonia 基于.NET Core&#xff0c;因此它可以运行在任何支持.NET Core的平台上。之前基于CPF跨平台UI框架写过一个视频聊天的demo&#xff0c;而现在看来Avalonia是大势所趋&#xff0c;于是&#xff0c;我再写一个Avalonia版本…

TP5.1 导出excel文件

在 ThinkPHP 5.1 中引入 PHPExcel&#xff08;现在已被官方弃用&#xff0c;推荐使用 PhpSpreadsheet&#xff09;时&#xff0c;可以按照以下步骤进行操作&#xff1a; 在 composer.json 文件中添加 PHPExcel&#xff08;PhpSpreadsheet&#xff09;的依赖项。找到 require 部…

告别单调的列表页,探索JVS低代码列表页设计的新思路

列表页是什么&#xff1f; 列表页是管理平台中的基础页面&#xff0c;核心的逻辑是实现数据的增删改查&#xff08;CRUD&#xff09;&#xff0c;列表页核心的几个要素&#xff1a;页面内容的数据展示、查询条件、页面按钮及按钮触发的逻辑。 列表页配置 具备应用配置权限的…

利用Python turtle绘制中国结附源码

一、中国结 01 平安喜乐 1&#xff09;效果图 import turtle turtle.screensize(600,800) turtle.pensize(10) turtle.pencolor("red") turtle.seth(-45) turtle.fd(102) turtle.circle(-6,180) turtle.fd(102) turtle.circle(6,180) turtle.fd(102) turtle.circle(…

5、函数式编程--方法引用

目录 6. 方法引用6.1 推荐用法6.2 基本格式6.3 语法详解(了解)6.3.1 引用类的静态方法格式使用前提 6.3.2 引用对象的实例方法格式使用前提 6.3.4 引用类的实例方法格式使用前提 6.3.5 构造器引用格式使用前提 6. 方法引用 ​ 我们在使用lambda时&#xff0c;如果方法体中只有…

如何加入开源项目维护并提交代码?本地搭建源码阅读开发构建环境示例: kafka

如何加入开源项目维护并提交代码?本地搭建源码阅读开发构建环境示例: kafka。 大家对开源项目有兴趣、想成为committer,或者工作需要,会从github上获取最新的开源项目源码。本文做一个示例,怎样搭建本地的源码阅读、开发、构建环境。 首先,在github上找到项目的链接,…

OS 进程的描述与控制

目录 前趋图 程序执行 程序顺序执行 程序并发执行 进程 定义 进程控制块 PCB 进程实体 进程 特征 动态性 并发性 独立性 异步性 状态 3 种基本状态 就绪状态 执行状态 阻塞状态 3 种基本状态间的转换 其他状态 创建状态 终止状态 进程 5 种状态及其转换…

创建JUnit4 的TestBase类

Slf4j RunWith(SpringRunner.class) SpringBootTest(classes {TestApplication.class},webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT) public class TestBase { } 如图&#xff1a;

基于Bert模型的中文语义相似度匹配算法(离线模式)

1、准备中文离线模型 配置文件夹 文件获取方法&#xff1a; 访问官网&#xff1a;https://huggingface.co/bert-base-chinese/tree/main 下载以下文件 2、测试代码 # -*- coding: utf-8 -*- #pip install transformers -i https://mirrors.aliyun.com/pypi/simple/ #pip …

2023年中国机场建设标准、机场数量及机场系统投资完成情况分析[图]

机场&#xff0c;亦称飞机场、空港&#xff0c;较正式的名称是航空站。机场有不同的大小&#xff0c;除了跑道之外&#xff0c;机场通常还设有塔台、停机坪、航空客运站、维修厂等设施&#xff0c;并提供机场管制服务、空中交通管制等其他服务。 机场建设资质等级标准 资料来源…