iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++如何实现优先队列
  • 172
分享到

C++如何实现优先队列

2023-07-02 11:07:50 172人浏览 八月长安
摘要

这篇文章主要介绍“c++如何实现优先队列”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++如何实现优先队列”文章能帮助大家解决问题。前言首先,啊,先简单介绍一下优先队列的概念,学数据结构以及出入算

这篇文章主要介绍“c++如何实现优先队列”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++如何实现优先队列”文章能帮助大家解决问题。

前言

首先,啊,先简单介绍一下优先队列的概念,学数据结构以及出入算法竞赛的相信都对队列这一数据结构十分熟悉,这是一个线性的数据结构.

针对队列这一特殊数据结构,有时需考虑队列元素的优先级的关系,即根据用户自定义的优先级排序,出队时优先弹出优先级更高(低)的元素,优先队列能更好地满足实际问题中的需求,而在优先队列的各种实现中,是一种最高效的数据结构。

什么是堆

堆是一颗具有特定性质的二叉树,堆的基本要求就是堆中所有结点的值必须大于或等于(或小于或等于)其孩子结点的值,这也称为堆的性质,我们也叫堆序性;堆还有另一个性质,就是当 h > 0 时,所有叶子结点都处于第 h 或 h - 1 层(其中 h 为树的高度,完全二叉树),也就是说,堆应该是一颗完全二叉树;

如下:

C++如何实现优先队列

根据两种堆序性,我们将堆分为两类,即根节点权值≥子节点权值的我们叫大根堆根节点权值≤子节点权值的我们叫小根堆。道理简单,就不做图演示了。

上文所述,优先队列是由一个堆维护的,堆序性正对应了优先队列的优先级。由此,优先队列就并不是一个线性的数据结构,其所有操作都是logn的时间复杂度。

了解完堆与优先队列的关系,我们就可以开始讨论如何实现优先对列了。

堆的存储方式

我们将一个堆从上到下从左到右(实际上这个顺序也是堆一般的讨论模式),从0开始给每个节点编号。如下图:

C++如何实现优先队列

然后按照顺序存储进一个线性的数组之中,那么这就算存储好了~

简不简单?意不意外?是不是最开始想到的是递归生成树?但实际上因为堆序性的存在,我们并不需要那么复杂的存储方式~

同样的道理,我们反过来用一个数组建堆,也就是如上操作的逆操作而已。

问题就来了,如何用一个无序的数组来建堆呢?这就要谈到维护堆序性的两种操作——上浮,下沉。

维护堆的方法

1、上浮操作

首先将一个无序的数组按下标标号,然后开始进行前方所说的建堆操作,我们建堆的过程便是主要用到上浮操作,每操作一步就要与父节点比较,如果大于(此处以大根堆为例子)父节点,则与父节点进行交换,然后跳转到交换后的位置,继续与父节点进行比较,直到不大于父节点后,就算完成了一次调整。光说肯定有些童鞋无法想象得那么明白,下面放图!

这里用数组a[6] = {3,5,8,9,1,2}做模板,别多想,很随机的数字罢了。

第一步,将下标为0的节点做根节点,就是3啦~

C++如何实现优先队列

第二步,将下标为1的节点也就是5作为3的左孩子~

C++如何实现优先队列

很明显啊,5要比它的父节点3要大,那么,交换位置~

再看5并没有比它小的根节点了,那么继续下一步~

第三步,将下标为2的节点也就是8,放在5的下边作为右孩子~

C++如何实现优先队列

很明显哦,8比它的父节点大,那么~,交换位置~ 

C++如何实现优先队列

很明显,8并没有比它更小的父节点了,那么继续下一步~

再接下去我就不讲了,很简单,序号从上到下从左到右。

那么任一的一个节点如果它足够大(小),就一定会最底下一层爬到最大的根节点,是不是上浮呢,生动而形象,在建堆的时候每插入一个元素,就要对该元素进行一次上浮调整,将其放在正确的地方。 

相信聪明的童鞋已经发现了,同层的节点不存在任何的关系!!!甚至不同根节点的同层节点也不存在任何关系,每一个节点仅仅只是在其子堆中的最大值,即局部最大值

2、下沉操作

该操作在队列的基本操作,也就是弹出队顶操作时所用,即删除最大(小)根节点的操作。

原理也很简单,将编号为0的节点与编号最大的节点权值互换,然后弹出编号最大的节点(此时即前一步的队顶元素),此时再对队顶节点进行下沉操作:

先与左子树进行比较,按照堆序性交换,直到换回它应在的位置,此时所有局部均为优先队列,其也维护完成。

上图:

这里还是前面那个数组,顺便也给大家看看建堆后的亚子~

a[6] = {3,5,8,9,1,2}

C++如何实现优先队列

第一步, 将编号为0的节点与编号最大的节点权值互换

即将9与2进行互换。

C++如何实现优先队列

第二步, 弹出编号最大的节点(此时即前一步的队顶元素)

即9

C++如何实现优先队列

第三步, 对队顶节点进行下沉操作

即先和8,5进行顺序比较,按照优先级,明显与8互换,换完后如下

C++如何实现优先队列

再与3先比较,无法交换再与1比较~最后应该是这个样子的。

C++如何实现优先队列

两种操作方式也已经说完,这里就会有童鞋问道,那么如何在数组中进行所谓的上浮下沉,操作呢? 

这里就有一个很重要的知识了,就是父节点和子节点在数组编号中的关系!

其实也并不难发现,根据堆的性质,有如下的关系:

设某个节点编号为i:

其父节点:dad = (i - 1) / 2

左/右子节点:left = 2 * i + 1

right = 2 * i + 2

这样大家就可以将上浮、下沉操作的每一步在数组中实现了!

附上代码

#include<iOStream>#include<cmath>#include<stdlib.h>#define bug cout<<"nug is here"<<endl;#include<vector>using namespace std;typedef size_t ull;  //堆 template<typename P>class Heap{private:vector<int> heap_elem;//堆容器 ull heap_depth;//深度bool Priority; //优先级ull heap_size; //容量void Up_adjust(int now);//上浮调整void Down_adjust(int now);//下沉调整 //now指代下标 public://构造堆 enum{max_heap = true, min_heap = false};Heap(vector<P> &l, bool priority = max_heap){heap_size = l.size();heap_depth = log2(heap_size);Priority = priority;//设置优先级 for(int i = 0;i < heap_size;i++){heap_elem.push_back(l[i]); Up_adjust(i);//上浮调整} }Heap(int a[], ull n, bool priority = max_heap){heap_size = n;heap_depth = log2(heap_size);Priority = priority;//设置优先级 for(int i = 0;i < n;i++){heap_elem.push_back(a[i]);Up_adjust(i);//上浮调整}}Heap(){heap_size = 0;heap_depth = 0;Priority = max_heap;};//堆的成员函数ull Depth(){return heap_depth;}ull Size(){return heap_size;}void Push(P x){heap_elem.push_back(x);++heap_size;heap_depth = log2(heap_size);swap(heap_elem[heap_elem.size() - 1], heap_elem[heap_size - 1]);//将加入的元素放入有效位 Up_adjust(heap_size - 1);} void Pop(){heap_depth = log2(heap_size);swap(heap_elem[--heap_size], heap_elem[0]);//将第一个元素与最后一个元素交换,并且缩短有效位数 //其实这里可以用vector的函数pop_back(),相应的上面的Push函数也不用换位置,但是这样更快 Down_adjust(0);}P &Top(){return heap_elem[0];}void show_as_tree(){//以树的形式输出 int _size = max(log10(heap_elem[0]),log10(heap_elem[heap_size - 1])) + 1;ull max_size = (pow(2, heap_depth) * 2) * _size;ull _max_size = _size * pow(2, heap_depth + 1);int start = -1;for(int i = 0;i <= heap_depth;i++){max_size >>= 1;max_size++;if(i == heap_depth) cout<<heap_elem[++start];else printf("%*d",max_size,heap_elem[++start]);int w = pow(2, i);for(int j = 1;j < w && start < heap_size - 1;j++) printf("%*d",_max_size,heap_elem[++start]);_max_size >>= 1;_max_size++;printf("\n");}}void show_as_array(){//数组方式输出 for(int i = 0;i < heap_size;i++) cout<<heap_elem[i]<<" ";cout<<endl; } };  //上浮调整 template<typename P>void Heap<P>::Up_adjust(int now){if(Priority)while(now > 0 && heap_elem[now] > heap_elem[(now - 1) / 2]){//如果当前节点的权值比父亲大 swap(heap_elem[now], heap_elem[(now - 1) / 2]);//交换 now =  (now - 1) / 2;}elsewhile(now > 0 && heap_elem[now] < heap_elem[(now - 1) / 2]){swap(heap_elem[now], heap_elem[(now - 1) / 2]);now = (now - 1) / 2;}} //下沉调整 template<typename P>void Heap<P>::Down_adjust(int now){ull left = now * 2 + 1;ull right;while(left < heap_size){//能换的时候 left = now * 2 + 1;right = now * 2 + 2;if(Priority){if(heap_elem[now] < heap_elem[left]){//比左孩子小,下沉 swap(heap_elem[now], heap_elem[left]);now = left;}else if(right < heap_size){//比右孩子小,下沉 if(heap_elem[now] > heap_elem[right]){swap(heap_elem[now], heap_elem[right]);now = right;}}}else{if(heap_elem[now] > heap_elem[left]){//比左孩子大,下沉 swap(heap_elem[now], heap_elem[left]);now = left;}else if(right > heap_size){//比右孩子大,下沉 if(heap_elem[now] < heap_elem[right]){swap(heap_elem[now], heap_elem[right]);now = right;}}}} } int main(){int a[6] = {3,5,8,9,1,2}; Heap<int> h(a, 6, true);//输出堆 h.show_as_tree();//h.Push(12);//h.show_as_tree();////h.Pop();//h.show_as_tree();////cout<<h.Top()<<endl; //vector<int> a;//Heap<int> h(a, Heap<int>::max_heap);//for(int i=0;i < 10;++i)//h.Push(rand()%100);////h.show_as_tree();return 0;}

按照前面那个数组运行,结果如下:

C++如何实现优先队列

关于“C++如何实现优先队列”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网其他教程频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: C++如何实现优先队列

本文链接: https://www.lsjlt.com/news/341425.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++如何实现优先队列
    这篇文章主要介绍“C++如何实现优先队列”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++如何实现优先队列”文章能帮助大家解决问题。前言首先,啊,先简单介绍一下优先队列的概念,学数据结构以及出入算...
    99+
    2023-07-02
  • JavaScript如何实现优先级队列
    这篇文章主要讲解了“JavaScript如何实现优先级队列”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript如何实现优先级队列”吧!一、优先级队列介绍我们知道,普通的队列插入...
    99+
    2023-06-21
  • C#实现优先队列和堆排序
    目录优先队列1.API2.初级实现3.堆的定义二叉堆表示法4.堆的算法上浮(由下至上的堆的有序化)下沉(由上至下的堆的有序化)改进堆排序1.堆的构造2.下沉排序先下沉后上浮优先队列 ...
    99+
    2024-04-02
  • JavaScript实现优先级队列
    目录一、优先级队列介绍二、优先级队列封装一、优先级队列介绍 我们知道,普通的队列插入一个元素,数据会被放在后端,并且需要前面所有的元素都处理完成后才会处理前面的数据。但是优先级队列,...
    99+
    2024-04-02
  • C++实现优先队列的示例详解
    目录前言堆的存储方式维护堆的方法1、上浮操作2、下沉操作附上代码前言 首先,啊,先简单介绍一下优先队列的概念,学数据结构以及出入算法竞赛的相信都对队列这一数据结构十分熟悉,这是一个线...
    99+
    2024-04-02
  • redis如何实现先进先出队列
    Redis可以使用List数据结构来实现先进先出(FIFO)队列。具体实现步骤如下:1. 使用`LPUSH`命令将元素插入到列表的头...
    99+
    2023-09-11
    redis
  • C#中实现PriorityQueue优先级队列的代码
    前言 前段时间看到有大佬对.net 6.0新出的PriorityQueue(优先级队列)数据结构做了解析,但是没有源码分析,所以本着探究源码的心态,看了看并分享出来。它不像普通队列先...
    99+
    2024-04-02
  • Python中的堆和优先队列是如何实现的?
    Python中的堆和优先队列是如何实现的?堆和优先队列是在计算机科学中常用的数据结构。在Python中,我们可以使用heapq模块来实现堆和优先队列。堆是一种特殊的完全二叉树,在堆中,每个父节点的值都比它的子节点的值要小(或大),这样的堆被...
    99+
    2023-10-22
    实现 优先队列
  • JS如何实现队列的先进先出功能
    这篇文章主要为大家展示了“JS如何实现队列的先进先出功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JS如何实现队列的先进先出功能”这篇文章吧。本文实例讲述了...
    99+
    2024-04-02
  • Go 实战单队列到优先级队列实现图文示例
    目录优先级队列概述为什么需要优先级队列优先级队列实现原理01 四个角色02 队列-消费者模式03 单队列-单消费者模式实现3.1 队列的实现3.2 工作单元--Job的实现3.3 消...
    99+
    2024-04-02
  • java利用Heap堆实现PriorityQueue优先队列
    本篇内容介绍了“java利用Heap堆实现PriorityQueue优先队列”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!首先做一个优先队列...
    99+
    2023-06-03
  • java数据结构-堆实现优先队列
    目录一、二叉树的顺序存储1.堆的存储方式 2.下标关系 二、堆(heap)1.概念 2.大/小 根堆2.1小根堆2.2大根堆3.建堆操作 3.1向下调整 4.入队操作 4...
    99+
    2024-04-02
  • 详解c++优先队列priority_queue的用法
    既然是队列那么先要包含头文件#include <queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队 优先队列具...
    99+
    2024-04-02
  • C++优先队列用法案例详解
    c++优先队列(priority_queue)用法详解 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。 在优先队列中,元素被赋予优先级。当访问元素时,具有最高...
    99+
    2024-04-02
  • Python - 优先队列(queue.PriorityQueue & heapq)
    目录 什么是优先队列 为什么需要优先队列? 优先队列是个啥? 优先队列的工作原理 Python实现一个优先队列 Python内置库中的queue.PriorityQueue的使用 基本操作 多条件优先级实现 Python内置库中的heapq...
    99+
    2023-09-08
    Python 优先队列
  • 【Java】PriorityQueue--优先级队列
    目录  一、优先级队列  (1)概念 二、优先级队列的模拟实现 (1)堆的概念  (2)堆的存储方式   (3)堆的创建 堆向下调整 (4)堆的插入与删除 堆的插入  堆的删除 三、常用接口介绍 1、PriorityQueue的特性 2...
    99+
    2023-08-31
    数据结构 java idea 算法 面试
  • Java优先级队列-堆
    Java优先级队列-堆 💐1. 二叉树的顺序存储💐🎃 1.1 存储方式🎃👻1.2 下标关系👻 ...
    99+
    2023-09-04
    java 算法 数据结构
  • Java优先队列 priority queue
    目录1.优先队列概念2.二叉堆(Heap)完全二叉树和满二叉树堆的重要操作1.优先队列概念 优先队列(priority queue)是一种特殊的数据结构。队列中每一个元素都被分配到一...
    99+
    2024-04-02
  • C++高级数据结构之优先队列
    目录前言高级数据结构(Ⅱ)优先队列(Priority Queue)API实现堆的定义二叉堆表示法堆的算法插入元素删除最大元素基于堆的优先队列堆排序前言 高级数据结构(Ⅱ)优先队列(P...
    99+
    2024-04-02
  • MySQL优先队列是什么
    本篇内容介绍了“MySQL优先队列是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 0.先抛...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作