当前位置: 首页 > news >正文

优先级队列的实现

什么是优先级队列

优先级队列是一种特殊的数据结构,它类似于队列或栈,但是每个元素都关联有一个优先级或权重。在优先级队列中,元素的出队顺序不是简单地按照它们进入队列的先后顺序(先进先出,FIFO),而是根据元素的优先级来决定。具有最高优先级的元素最先出队,如果两个元素具有相同的优先级,则按照它们在队列中的顺序出队。
通俗来说,假设我们传入队列的是整形数据,那么他会按照数据的从小到大还是从大到小的出队顺序存放在队列中这就是优先级队列

仿函数

这里要提到一个概念叫仿函数
仿函数是一个可以像函数一样调用的对象。简单来说,仿函数是一种具有operator()成员函数的对象,使得该对象可以像普通函数一样使用调用操作符(),他是重载operator()括号实现的,我们来举个例子
下面是个比较大小的仿函数例子

 template<class type>class less{public:bool operator()(const type& x, const type& y){return x < y;}
};

这里我们利用这个比较大小的仿函数,就可以像函数那样调用,就像这样

int main()
{less li;if(li(1,2)){cout<<"y比x大"<<endl;}else{cout<<"x比y大"<<endl;}return 0;}

在举个形象的例子

# include<iostream>
# include<string>
using namespace std;
template<class type>
class _cout
{
public:void operator()(const type& input){cout << input << endl;}
};
int main()
{_cout<string> print;print("hello,word");return 0;
}

有了以上仿函数的介绍之后,就可以开始说我们的优先级队列了

优先级队列的实现

优先级队列的实质上就是用堆来创建队列,按照堆排序的思想来对输入到队列里面的数据进行处理,按照升序建大堆,降序建小堆的思想进行创建,所以这里需要两个堆排序里面关键的函数**adjustdown(向下调整)adjustup(向上调整)**还需要我们上面提到的仿函数,这里仿函数的作用就是我们不用去改代码中的大于还是小于,直接在创建对象的时候提供模板参数就来作为创建大堆还是小堆的依据,非常方便
下面是仿函数

 template<class type>class less{public:bool operator()(const type& x, const type& y){return x < y;}
};template<class type>
class grator
{
public:bool operator()(const type& x, const type& y){return x > y;}
};

接下来是建堆算法

	template<class type,class contier = vector<type>,class compre = less<type>>class priorityqueue{public:void adjustup(size_t child){compre com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent],_con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjustdown(size_t parent){compre com;size_t child = parent * 2 + 1;while (child < _con.size()){//        x        <        y if (child + 1 < _con.size() && com(_con[child], _con[child+1])){child++;}//        x        <        y if (com(_con[parent], _con[child])){ swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}
void push(const type& input)
{_con.push_back(input);adjustup(_con.size() - 1);
}
void pop()
{swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjustdown(0);
}

这里需要结合这4个函数一起看,push就是插入数据,插入完之后,我们这里的默认容器是vector,然后我们调用向上建堆算法,从数组最后一位开始(所以这里的size()-1)vector下标是从零开始的存放10个数就是占用0-9个位置,假设我们插入1,9,2,10,3我们来画图看看是怎么调堆的
在这里插入图片描述这就是向上建堆的过程,也是我们push数据的过程
接下来说一说pop,出队列
这里需先出对顶数据在把第一个数据和最后一个数据进行交换
在这里插入图片描述
在向下调整堆
因为是建的大堆,把最大的数据给pop掉了之后,采用向下调整算法,第二大的数据就会出现在堆顶
在一直执行这个操作,最后的出队顺序就是从大到小的顺序
t1是创建的对象
出队列代码

	void test(){priorityqueue<int,vector<int>,less<int>> t1;t1.push(1);t1.push(9);t1.push(2);t1.push(10);t1.push(3);while (!t1.is_empty()){cout << t1.top() << " ";t1.pop();}}

在这里插入图片描述最后还有剩下的这些小函数关于返回大小,容器空没有,取到堆顶的数据

		size_t size(){return _con.size();}bool is_empty(){return _con.empty();}const type& top(){return _con[0];}

源码

#pragma once
# include<vector>
# include<iostream>
using namespace std;
namespace thr
{ template<class type>class less{public:bool operator()(const type& x, const type& y){return x < y;}
};template<class type>
class grator
{
public:bool operator()(const type& x, const type& y){return x > y;}
};template<class type,class contier = vector<type>,class compre = less<type>>class priorityqueue{public:void adjustup(size_t child){compre com;int parent = (child - 1) / 2;while (child > 0){//        x        <        y if (com(_con[parent],_con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjustdown(size_t parent){compre com;size_t child = parent * 2 + 1;while (child < _con.size()){//        x        <        y if (child + 1 < _con.size() && com(_con[child], _con[child+1])){child++;}//        x        <        y if (com(_con[parent], _con[child])){ swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const type& input){_con.push_back(input);adjustup(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjustdown(0);}size_t size(){return _con.size();}bool is_empty(){return _con.empty();}const type& top(){return _con[0];}private:contier _con;};void test(){priorityqueue<int,vector<int>,less<int>> t1;t1.push(1);t1.push(9);t1.push(2);t1.push(10);t1.push(3);while (!t1.is_empty()){cout << t1.top() << " ";t1.pop();}}
}

http://www.mrgr.cn/news/1819.html

相关文章:

  • 个人理解—MKCONFIG的常用配置参数与链接脚本
  • 動態PPTP代理IP是什麼?
  • k8s之HPA
  • catvod、TVBox源的格式解析及合并多个源的内容(Python脚本)
  • 【springboot】自定义starter
  • 在 Vue.js 中使用 Ant Design 实现表格开关功能:详细教程
  • 深度学习------------------卷积神经网络(LeNet)
  • 单例模式下的自动内存释放和模板
  • 国际校企合作|深信服、常州信息职业技术学院、马来西亚汽车工业大学三方国际化人才培养合作签约仪式圆满成功
  • 后端开发刷题 | 寻找峰值【二分法】
  • 第N7周:调用Gensim库训练Word2Vec模型
  • 08结构型设计模式——适配器模式
  • 证书|“机器学习工程师”来了,由工业和信息化部教育与考试中心颁发,含金量高
  • 1.微服务发展阶段
  • 【Android】Android AOP 编程框架
  • ActiveMQ、RabbitMQ、Kafka、RocketMQ在优先级队列、延迟队列、死信队列、重试队列、消费模式、广播模式的区别
  • CentOS主机名修改
  • 【区块链+金融服务】供应链金融平台 | FISCO BCOS应用案例
  • 动态规划-下降路径最小和
  • Chromium编译指南2024 - Android篇:从Linux版切换到Android版(六)