原文地址:https://blog.csdn.net/qq_42837885/article/details/99566524
priority_queue
优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
注意:
-
默认情况下priority_queue是大堆。
-
如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供> 或者< 的重载。
-
有些情况下,用户可能需要提供比较器规则
class Less
{
public:
bool operator()(const Date* pLeft, const Date* pRight)
{
return *pLeft < *pRight;
}
};
void TestPriorityQueue()
{
priority_queue<Date, vector<Date>, Less> q;
q.push(&Date(2019, 8, 14));
q.push(&Date(2019, 8, 15));
q.push(&Date(2019, 8, 16));
cout << *q.top() << endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
为什么将stack、queue和priority_queue称作为容器适配器?
- 虽然stack、queue、priority_queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将 其称为容器适配器,这是因为每个容器在底层都有自己的实现方式,而stack、queue、priority_queue只是 在底层将其他容器进行了封装。
什么是适配器?
- 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该中模式是将一个类的接口转换成客户希望的另外一个接口。
priority_queue的模拟实现
template<class T,class Sequence=vector<T>,class Compare=less<T>>
class priority_queue
{
public:
priority_queue()
:_seq()
{}
template<class InputIt>
priority_queue(InputIt start, InputIt last)
:_seq(start,last)
{
int parent = (_seq.size() - 2) >> 1;
while (parent >= 0)
{
makeDown(parent);
parent--;
}
}
void push(const T& x)
{
_seq.push_back(x);
makeUp(_seq.size() - 1);
}
void pop()
{
if (empty())
return;
swap(_seq.front(),_seq.back());
_seq.pop_back();
makeDown(0);
}
bool empty()const
{
return _seq.empty();
}
const T& top()const
{
return _seq.front();
}
size_t size()const
{
return _seq.size();
}
private:
void makeUp(int child)
{
int parent = (child - 1) >> 1;
while (child)
{
if (_com(_seq[parent], _seq[child]))
{
swap(_seq[parent], _seq[child]);
child = parent;
parent = (child - 1) >> 1;
}
else
return;
}
}
void makeDown(int parent)
{
int child = parent * 2 + 1;
while (child < _seq.size())
{
if (child + 1 < _seq.size() && _com(_seq[child], _seq[child + 1]))
++child;
if (_com(_seq[parent], _seq[child]))
{
swap(_seq[parent], _seq[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
Sequence _seq;
Compare _com;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
为什么选择deque作为stack和queue的底层默认容器
stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有 push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和 queue默认选择deque作为其底层容器,主要是因为:
- stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
- 在stack中元素增长时,deque比vector的效率高;queue中的元素增长时,deque不仅效率高,而且内存使用率高。