priority queue(优先队列)
是一种特殊的队列,其中每个元素都有一个与之关联的优先级。在优先队列中,元素按照优先级的顺序进行插入和删除操作,优先级高的元素先被处理。
以下是关于priority queue的一些重要知识点:
-
特点:
- 每个元素都有一个与之关联的优先级,优先级高的元素先被处理。
- 元素的插入和删除操作是基于优先级的,而不是按照元素的插入顺序。
- 元素的访问是有限制的,通常只能访问最高优先级的元素。
-
实现方式:
- 二叉堆:使用完全二叉树来实现优先队列,其中每个节点的值都大于等于(或小于等于)其子节点的值。二叉堆可以通过数组来表示,具有快速的插入和删除操作。
- 斐波那契堆:一种更高效的实现方式,通过使用多个二叉堆来实现优先队列,具有更快的插入和删除操作。
-
常见操作:
- 插入:将一个元素插入到优先队列中,根据元素的优先级进行排序。
- 删除:从优先队列中删除最高优先级的元素。
- 访问:获取最高优先级的元素,通常不会修改队列的内容。
-
时间复杂度:
- 插入操作的时间复杂度通常为O(log n),其中n是优先队列中元素的数量。
- 删除操作的时间复杂度通常为O(log n)。
- 访问操作的时间复杂度为O(1)。
-
应用场景:
- 任务调度:优先队列可以用于按照优先级调度任务的执行顺序。
- 模拟系统:优先队列可以用于模拟系统中的事件处理顺序。
- 哈夫曼编码:优先队列可以用于构建哈夫曼树,用于数据压缩。
总结起来,priority queue是一种按照优先级进行插入和删除操作的特殊队列。它可以使用二叉堆或斐波那契堆来实现,具有快速的插入和删除操作。优先队列在任务调度、模拟系统和数据压缩等场景中有广泛的应用。
实现方式
用箭头和横线以及数字表示priority queue的实现方法和数据存储方式如下:
-
实现方法:
- 二叉堆:使用完全二叉树来实现优先队列。每个节点都有一个值,满足父节点的值大于等于(或小于等于)其子节点的值的条件。箭头表示节点之间的关系,指向父节点的箭头表示较小(或较大)的值。
- 斐波那契堆:使用多个二叉堆来实现优先队列。每个二叉堆都是一个子堆,通过指向其他子堆的箭头来组成斐波那契堆。横线表示子堆之间的关系。
-
数据存储方式:
- 二叉堆:可以使用数组来表示二叉堆。数组中的每个元素对应一个节点,按照层次遍历的顺序存储。通过计算数组索引之间的关系,可以实现快速的插入和删除操作。
- 斐波那契堆:斐波那契堆通常使用多个二叉堆来存储数据。每个二叉堆使用数组来表示,数组中的每个元素对应一个节点。通过指向其他二叉堆的箭头,可以将多个二叉堆连接起来形成斐波那契堆。
下面是用箭头和横线以及数字表示二叉堆和斐波那契堆的实现方法和数据存储方式的示例:
二叉堆:
1
/ \
3 2
/ \ / \
5 4 7 6
斐波那契堆:
1 3 5 7 9
| | | | |
2 4 6 8 10
\ / \ /
11 12
| |
13 14
在斐波那契堆中,数字表示节点的值,箭头表示节点之间的关系,横线表示子堆之间的关系。例如,节点13指向节点11,节点11和节点12之间有一条横线连接。
模拟实现
#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace YJ
{
//仿函数 -- 函数对象 这个类的对象可以像函数一样去使用
template<class T>
struct less
{
bool operator()(const T& l, const T& r)
{
return l < r;
}
};
template<class T>
struct greater
{
bool operator()(const T& l, const T& r)
{
return l > r;
}
};
template<class T, class Container = vector<T>, class Compare = greater<T>>
class priority_queue
{
public:
//typedef typename Container::value_type VT;
void AdjustUp(size_t child)
{
Compare com;
size_t 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 push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size()-1);
}
void AdjustDwon(size_t parent)
{
Compare com;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child],_con[child + 1]))
{
++child;
}
if (com(_con[parent],_con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDwon(0);
}
T top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}