C++实现优先级队列模板类

2023-05-16

1. 优先级队列

1.1 基本原理

仿照C++ STL 中的优先级队列priority_queue,主要实现以下功能:

  • 向队列中添加元素后,队列自动调整,保证队列中优先级最高的元素在队列头部(优先级可以定义比较函数,按照大小或者其他条件决定);
  • 每次出队元素是队列中优先级最高的,因此优先级队列不满足先进先出的原则,而是根据每次都是优先级最高的先出。

优先级队列ADT的API如下:

方法名

功能

push()

添加一个元素

pop()

删除一个元素

top()

获取队列顶部元素

size()

获取队列大小

empty()

返回队列是否为空

1.2 上浮和下沉

  • 上浮:由下至上的堆有序化,对大顶堆(堆顶元素是堆中最大的)来说,如果子节点value大于父节点,那么就需要交换子节点和父节点,将子节点上浮,使其处于合适的位置,循环往复,直到父节点大于当前value,或者value达到堆顶,结束。
  • 下沉:由上至下的堆有序化。对大顶堆来说,如果父节点value小于其子节点,需要将其与子节点交换,父节点value下沉,使其处于合适的位置,循环往复,直到value大于其子节点或者到堆的尾部。

2. 代码实现

2.1 push()

template<typename T, typename compare>
void MyPriorityQueue<T, compare>::push(T key)
{
	//key添加到队尾
	_pq.push_back(key);
	_size++;
	//如果只有一个元素,return
	int idx = _size - 1;
	if (idx == 0)return;
	
	//上浮,key大于其父节点,即上浮(将父节点换到下面),idx的父节点是(idx -1) / 2
	while (idx > 0 && _cmp(_pq[(idx -1) / 2], key)) {
		_pq[idx] = _pq[(idx - 1) / 2];//将父节点换到下面
		idx = (idx - 1) / 2;//更新idx,直到idx的父节点大于key,停止
	}
	_pq[idx] = key;//将key放到正确的位置
}

2.2 pop()

//将顶部元素删除,将尾部元素替换到顶部,然后下沉该元素
template<typename T, typename compare>
void MyPriorityQueue<T, compare>::pop()
{
	if (_size == 0)return;
	if (_size == 1) {
		_pq.clear();
		_size = 0;
		return;
	}
	//将末尾的元素换到头部,末尾的pop出去
	_pq[0] = _pq[_size-1];
	_pq.pop_back();
	//然后下沉新换到头部的元素
	_size--;
	int idx = 0;
	T tmp = _pq[0];
	int leftChild = 2 * (idx + 1) - 1;
	int rightChild = 2 * (idx + 1);
	while (leftChild < _size) {
		//child,记录下沉到左子节点还是右子节点,还是不动
		int child = idx;
		if (_cmp(tmp, _pq[leftChild]))child = leftChild;
		if (rightChild < _size && _cmp(_pq[child], _pq[rightChild]))child = rightChild;
		if (idx == child)break;
		_pq[idx] = _pq[child];//将child浮上去,child的位置暂时给tmp
		idx = child;
		leftChild = 2 * (idx + 1) - 1;//如果idx还存在左右子节点,继续;否则退出
		rightChild = 2 * (idx + 1);
	}
	_pq[idx] = tmp;
}

2.3 完整代码

PriorityQueue.h

#pragma once
#include <vector>
using std::vector;
//vector做容器,函数对象compare用于比较,less对应大顶堆,greater对应小顶堆
template<typename T, typename compare = std::less<T>>
class MyPriorityQueue {

private:
	size_t _size = 0;
	vector<T> _pq;
	compare _cmp;
public:
	MyPriorityQueue() {}
	~MyPriorityQueue() {};

	void push(T key);
	void pop();
	T top();
	void clear();
	size_t size() { return _size; }
	bool empty() { return _size == 0 ? true : false; }
};

//添加新元素到队尾,然后上浮该元素
template<typename T, typename compare>
void MyPriorityQueue<T, compare>::push(T key)
{
	//key添加到队尾
	_pq.push_back(key);
	_size++;
	//如果只有一个元素,return
	int idx = _size - 1;
	if (idx == 0)return;
	
	//上浮,key大于其父节点,即上浮(将父节点换到下面),idx的父节点是(idx -1) / 2
	while (idx > 0 && _cmp(_pq[(idx -1) / 2], key)) {
		_pq[idx] = _pq[(idx - 1) / 2];//将父节点换到下面
		idx = (idx - 1) / 2;//更新idx,直到idx的父节点大于key,停止
	}
	_pq[idx] = key;//将key放到正确的位置
}
//将顶部元素删除,将尾部元素替换到顶部,然后下沉该元素
template<typename T, typename compare>
void MyPriorityQueue<T, compare>::pop()
{
	if (_size == 0)return;
	if (_size == 1) {
		_pq.clear();
		_size = 0;
		return;
	}
	//将末尾的元素换到头部,末尾的pop出去
	_pq[0] = _pq[_size-1];
	_pq.pop_back();
	//然后下沉新换到头部的元素
	_size--;
	int idx = 0;
	T tmp = _pq[0];
	int leftChild = 2 * (idx + 1) - 1;
	int rightChild = 2 * (idx + 1);
	while (leftChild < _size) {
		//child,记录下沉到左子节点还是右子节点,还是不动
		int child = idx;
		if (_cmp(tmp, _pq[leftChild]))child = leftChild;
		if (rightChild < _size && _cmp(_pq[child], _pq[rightChild]))child = rightChild;
		if (idx == child)break;
		_pq[idx] = _pq[child];//将child浮上去,child的位置暂时给tmp
		idx = child;
		leftChild = 2 * (idx + 1) - 1;//如果idx还存在左右子节点,继续;否则退出
		rightChild = 2 * (idx + 1);
	}
	_pq[idx] = tmp;
}
//返回堆顶元素
template<typename T, typename compare>
inline T MyPriorityQueue<T, compare>::top()
{
	if (empty()) throw("Priority queue is empty!");
	return _pq[0];
}
//清空堆
template<typename T, typename compare>
inline void MyPriorityQueue<T, compare>::clear()
{
	_pq.clear();
	_size = 0;
}

PriorityQueue.cpp

#include <iostream>
#include"PriorityQueue.h"
using namespace std;
int main()
{
	MyPriorityQueue<int> pq1;
	pq1.push(1);
	pq1.push(3);
	pq1.push(5);
	pq1.push(7);
	pq1.pop();
	pq1.pop();
	pq1.pop();
	pq1.pop();
	try {
		bool a = pq1.empty();
		int top = pq1.top();
	}
	catch (const char* e) {
		cerr << e << endl;
	}
	
	return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++实现优先级队列模板类 的相关文章

  • 原生大数据|elasticSearch|低版本kibana组件的汉化

    前言 xff1a 大数据的范畴里包括EFK ELK xff0c 这些套件安装部署是非常的成熟 xff0c 因此是比较好部署安装的 xff0c 一般的 xff0c 困难出现在部署完成后的运营和维护 kibana这个组件的版本低于7我们就应该认
  • JAVA继承-注意事项

    JAVA继承 1 子类所有构造器 xff0c 会隐式调用父类的无参构造器 原理 xff1a 子类所有构造器 xff0c 都会在第一行隐式调用super 问题 xff1a 如果父类没有无参构造器 xff0c 编译报错 解决 xff1a 在子类
  • mac上安装brew出错curl: Failed to connect to raw.githubusercontent.com port 443解决方法

    问题描述 由于最近重做了电脑系统 xff0c 重新下载安装brew 就报错了 xff0c raw githubusercontent com 在国内由于不可描述的原因就无法访问 解决方法一 参考网上的解决方法 首先是访问这个网址 https
  • Hexo + gitHub pages

    网址 xff1a https oldmee github io hexo的写作流程就是会按照日期自动帮你归类 xff0c 你new了一个page会生成一个markdown文件 xff0c 你就可以愉快的写作了 xff0c 边写边看效果 xf
  • 使用策略模式优化过多的if else语句

    此处的过多是指if else超过三层 xff0c 如下面的代码 xff1a public class MainStart public static void main String args String message 61 34 se
  • 在基于图像的深度学习中如何做数据的自动标注以及自动标注的等级介绍

    作者 xff1a Tobias Schaffrath Rosario 编译 xff1a ronghuaiyang 原文 xff1a 在基于图像的深度学习中如何做数据的自动标注以及自动标注的等级介绍 ronghuaiyang的博客 CSDN博
  • 【Java】 牛客网华为机试108题汇总

    文章目录 目录 目录 1 求字符串最后一个单词长度 2 计算字符串个数 3 明明的随机数 4 字符串分割 5 进制转换 6 质数因子 7 HJ19 简单错误记录 8 HJ25 数据分类处理 9 HJ30 字符串合并处理 1 求字符串最后一个
  • OpenCV的简单使用教程与基本函数(C++版本)

    OpenCV的简单使用教程 xff08 C 43 43 xff09 OpenCV简介OpenCV的使用基础打开 显示和保存图像图像存储变量 Mat类图像元素的存储读入图像文件创建Mat类复制Mat类图像元素的访问OpenCV画图命令行交互界
  • 【实用技巧】知网文献不限量免费下载方法,亲测可用

    众所周知 xff0c 知网可以查看和下载相关的文献资料 xff0c 只要用校园网就能免费的下载和查阅 xff0c 但是也有不少学校并没有和知网合作 xff0c 这样就没办法下载 xff0c 只能充钱才能享受 那么有没有白嫖的办法呢 xff1
  • git rm 删除 以及清空暂存区

    一 使用linux命令rm删除 xff1a 在当前工作区有文件readme txt xff0c 并被git跟踪 xff0c 且有提交历史 运行如下命令 xff1a rm readme txt 分析如下 xff1a xff08 1 xff09
  • centOS开启和关闭防火墙

    CentOS 7 0默认使用的是firewall作为防火墙 xff0c 在安装某些软件的时候就需要关闭防火墙 一 查看防火墙的状态 开启显示 running xff0c 关闭后显示 not running 执行命令 firewall cmd
  • postgresql|数据库|pg数据库的文件系统详解---最全面的解析

    前言 xff1a postgresql是一个非常成熟的开源的功能强大的关系型数据库 xff0c 总体来说 xff0c 该数据库安装简单 xff0c 使用复杂 xff0c 复杂度在多个维度都会有所体现 xff0c 比如 xff0c SQL语法
  • k8s部署ingress-nginx的方法步骤

    1 ingress概述 我们知道service的表现形式为IP PORT xff0c 即工作在第四层传输层 xff08 TCP IP层 xff09 xff0c 那么对于不同的URL地址经常对应用不同的后端服务或者虚拟服务器 xff0c 这些
  • 计算机软技术,如何画好一张架构图?

    什么是架构图 xff1f 如何画好一张架构图 xff0c 要做好这件事情首先要回答的就是什么是架构图 我们日常工作中经常能看到各种各样的架构图 xff0c 而且经常会发现大家对架构图的理解各有侧重 深入追究到这个问题 xff0c 可能一下子
  • yum与apt

    linux系统分类 一般来说著名的linux系统基本上分两大类 xff1a 1 RedHat系列 xff1a Redhat Centos Fedora等 2 Debian系列 xff1a Debian Ubuntu等 RedHat 系列 1
  • netstat常用场景记录

    参数说明 netstat命令各个参数说明如下 xff1a a 显示所有连线中的端口 不加此参数默认不显示处于监听状态的端口 n 不进行DNS轮询 xff0c 显示IP 可以加速操作 r 显示路由表信息 t 显示TCP传输协议的端口连线状况
  • log4j动态加载配置文件

    应用场景与问题 当项目在运行时 xff0c 我们如果需要修改log4j 1 X或者log4j2的配置文件 xff0c 一般来说我们是不能直接将项目停止运行再来修改文件重新部署的 于是就有这样一个问题 xff1a 如何在不停止当前项目的运行的
  • vm options、program arguments、environment property

    系统变量 system property 是java应用程序自身指定的变量 xff0c 通常我们可以在启动应用的时候指定 xff0c 指定方式可以有以下两种 输入java jar help 回顾一下java启动jar文件的命令 java o
  • 解决IntelliJ IDEA各种中文乱码问题

    1 修改文件编码方式 打开IntelliJ IDEA gt File gt Setting gt Editor gt File Encodings xff0c 将Global Encoding Project Encoding Defaul
  • 解析IDEA中的Artifacts配置

    1 Artifact 2 Artifact名称 3 Artifact类型 4 输出路径 xff08 也就是Deployment root部署根目录 xff09 xff0c 项目运行后的输出根目录 5 输出根目录 xff0c 即4指定的地址

随机推荐

  • IDEA代码以及注释格式化,行宽设置,以及自动换行

    一 设置代码最大行宽 xff0c 以及自动换行 勾选wrap on typing xff0c 即在编码时 xff0c 超出最大行宽 xff0c 则自动换行 xff0c 或者采用下面这种方式 xff0c 在手动格式化的时候 xff0c 进行自
  • IDEA设置代码规范,代码格式化设置,以及ALIBABA编码规约

    阿里巴巴格式化模板文件下载地址 https github com alibaba p3c 第一个文件是 代码格式化时用的模板 第二个文件是 注释模板 一 eclipse 格式化设置 格式化模板导入 依次点击 xff1a Window gt
  • 数组的初始化 array initializer is not allowed here

    此处不允许使用数组初始值设定项 array initializer is not allowed here 数组的使用分声明和初始化两部分 xff0c 两者可同时进行 xff0c 也可分开进行 int array 声明 array 61 n
  • Maven打包所有依赖到一个可执行jar中,将外部依赖加入到classPath中

    首先说一下比较常用的两种打包方式 xff1a 前提 xff1a maven构建可执行jar包时 xff0c 如果项目依赖了pom中定义的dependency之外的外部jar包 xff0c maven jar plugin默认是不会把这 些额
  • postgresql数据库|数据库实操----表复制详解

    前言 xff1a 通常情况下 xff0c 我们对数据库的增删改查的时候 xff0c 为了确保数据的安全 xff0c 需要备份表 xff0c 那么 xff0c 一种方法是通过pg dump 这个工具做SQL转储操作 xff0c 此方法比较复杂
  • Centos7 配置防火墙 firewall

    一 firewall 1 从CentOS7开始 xff0c 默认使用firewall来配置防火墙 xff0c 没有安装iptables xff08 旧版默认安装 xff09 2 firewall的配置文件是以xml的格式 xff0c 存储在
  • Windows多媒体开发框架介绍

    Windows 多媒体开发框架介绍 欢迎来到 Windows 的多媒体开发世界2D 绘图 API1 GDI2 GDI 43 3 Direct2D 音频 API1 MME2 DirectSound3 Windows Core AudioCor
  • 【Ubuntu】在QT运行程序后无结果显示,只有终端运行的解决办法

    转自 http stackoverflow com questions 3255035 qt creator run in terminal https bugs launchpad net ubuntu 43 source qtcreat
  • 【蓝桥杯嵌入式】关于CT117E下载程序出问题解决方案(含keil mdk4和keil mdk5移植)

    废话 万事开头难 xff0c 然后中间难 xff0c 最后难 寒假刚开始 xff0c 我看到了蓝桥杯嵌入式 很快啊 xff01 报名 买板一气呵成 没想到这块CT117E板子它不讲武德 xff0c 来骗 xff0c 来偷袭我这个二十岁的小伙
  • c语言冒泡排序详解(分析每一步,附代码)

    冒泡排序 xff08 Bubble Sort xff09 xff0c 是一种计算机科学领域的较简单的排序算法 它重复地走访过要排序的元素列 xff0c 依次比较两个相邻的元素 xff0c 如果顺序 xff08 如从大到小 首字母从Z到A x
  • 解决maven update project 后项目jdk变成1.5

    一 问题描述 在Eclipse中新建了一个Maven工程 然后更改JDK版本为1 7 结果每次使用Maven gt Update project的时候JDK版本都恢复成1 5 二 原因分析 Maven官方文档有如下描述 xff1a 编译器插
  • C语言——整型和浮点型混合运算

    1 int和double混合运算 C语言int和double混合运算时 xff0c 会自动将int类型的数据转换为double类型的数据 xff0c 最后得到的结果也是double类型 如下例 xff1a double a 61 4 0 9
  • C语言——函数指针

    目录 1 函数指针概念 1 1 函数指针的声明 1 2 函数指针的定义 1 3 使用typedef定义函数指针的别名 1 4 将常数转换为函数指针 1 5 函数指针的调用 1 6 将函数指针作为函数的传入参数 2 简单的例子 1 函数指针概
  • C语言——多线程基础(pthread)

    目录 1 线程的定义以及线程的创建 1 1 线程和进程的概念 1 2 使用pthread create 函数创建进程 2 使用pthread join 等待线程结束 2 1 使用pthread join 等待线程结束 2 1 使用pthre
  • C++——双端队列(deque)

    1 双端队列 xff08 deque xff09 双端队列 xff08 deque xff09 是队列的一种变形 xff0c 一般队列只能在队尾添加元素 xff08 push xff09 xff0c 在队首删除元素 xff08 pop xf
  • Linux|集群初始化脚本--osiniit.sh简介

    前言 xff1a 不管是什么部署 xff0c 前期的准备工作通常都是比较繁琐的 xff0c 但同时这些工作又具有程式化的特征 xff0c 也就是说都是有一定的流程的 xff0c 固定的步骤的 OK xff0c shell脚本处理这样的程式问
  • C++——优先级队列(priority_queue)

    目录 1 优先级队列 xff08 priority queue xff09 1 1 基本概念 1 2 优先级队列的定义 1 3 通过重写仿函数来支持自定义数据类型 1 4 通过运算符重载来支持自定义比较函数 1 5 优先级队列的基本操作 2
  • 操作系统——进程状态

    进程从创建到执行 xff0c 再到执行完毕销毁的过程中 xff0c 经历了不同的进程状态 xff0c 进程状态部分取决于进程当前的活动 xff0c 可以将进程状态分为 xff08 1 xff09 三状态模型 xff1b xff08 2 xf
  • 操作系统——进程调度

    目录 1 基本概念 1 1 CPU I O执行周期 1 2 CPU调度程序 xff08 CPU scheduler xff09 1 3 进程状态模型 1 4 抢占调度 1 5 调度程序 xff08 dispatcher xff09 1 6
  • C++实现优先级队列模板类

    1 优先级队列 1 1 基本原理 仿照C 43 43 STL 中的优先级队列priority queue xff0c 主要实现以下功能 xff1a 向队列中添加元素后 xff0c 队列自动调整 xff0c 保证队列中优先级最高的元素在队列头