stack是一种容器适配器,它专门用于实现后进先出(LIFO)的数据结构。stack是通过封装底层容器的方式实现的,它提供了一组特定的成员函数来访问其元素,将元素作为其底层容器的尾部(即栈顶)被压入和弹出。
stack的底层容器可以是任何标准的容器类模板或其他特定的容器类,这些容器类应该支持以下操作:
- empty:判空操作
- back:获取尾部元素操作
- push_back:尾部插入元素操作
- pop_back:尾部删除元素操作
标准容器vector、deque、list均符合这些需求。如果没有为stack指定特定的底层容器,默认情况下将使用deque作为底层容器。
栈是一种常见的数据结构,它是一种后进先出(LIFO)的数据结构,即最后进入的元素最先被访问。栈通常用于函数调用、表达式求值、括号匹配、迷宫问题等场景中。
stack给我们提供了以下几个函数:
函数说明 | 接口说明 |
---|---|
stack() | 构造空的栈 |
empty() | 检测stack是否为空 |
size() | 返回stack中元素的个数 |
top() | 返回栈顶元素的引用 |
push() | 将元素val压入stack中 |
pop() | 将stack中尾部的元素弹出 |
示例代码:
#include
#include
using namespace std;
int main()
{
// 创建一个空的栈
stack<int> s;
// 检查栈是否为空
if (s.empty())
{
cout << "栈为空" << endl;
}
// 将元素压入栈中
s.push(1);
s.push(2);
s.push(3);
// 获取栈中元素的数量
cout << "栈中元素的数量为:" << s.size() << endl;
// 获取栈顶元素的引用
cout << "栈顶元素为:" << s.top() << endl;
// 弹出栈顶元素
s.pop();
cout << "弹出栈顶元素" << endl;
// 获取栈中元素的数量
cout << "栈中元素的数量为:" << s.size() << endl;
// 再次获取栈顶元素的引用
cout << "栈顶元素为:" << s.top() << endl;
return 0;
}
运行结果:
在使用stack时,需要注意以下几点:
- 栈是一种后进先出(LIFO)的数据结构。
- 在使用栈之前,需要包含头文件。
- stack模板类只能存储相同类型的元素。
- 当栈为空时,调用top()函数会导致未定义的行为。
队列(Queue)是一种常用的数据结构,它遵循先进先出(First In First Out,FIFO)的原则,即先进入队列的元素先出队列。队列可以用于实现很多算法和数据结构,例如广度优先搜索和缓存等。在C++中,可以使用STL中的queue容器适配器来实现队列。
queue作为容器适配器实现,可以将其底层容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
底层容器可以是标准容器类模板之一,例如deque和list,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:
- empty():检测队列是否为空。
- size():返回队列中有效元素的个数。
- front():返回队头元素的引用。
- back():返回队尾元素的引用。
- push_back(const T& obj):在队列尾部插入元素obj。
- pop_front():在队列头部弹出元素。
默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。
使用queue非常简单,只需要先创建一个queue对象,然后使用push()方法向队列中添加元素,使用pop()方法从队列中删除元素,使用front()和back()方法获取队头和队尾元素的引用。以下是queue提供给我们的一些函数方法。
函数声明 | 接口说明 |
---|---|
queue() | 构造空的队列 |
empty() | 检测队列是否为空,是返回true,否则返回false |
size() | 返回队列中有效元素的个数 |
front() | 返回队头元素的引用 |
back() | 返回队尾元素的引用 |
push() | 在队尾将元素val入队列 |
pop() | 将队头元素出队列 |
示例代码:
#include
#include
using namespace std;
int main() {
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
cout << "队列大小:" << q.size() << endl;
cout << "队头元素:" << q.front() << endl;
cout << "队尾元素:" << q.back() << endl;
q.pop();
cout << "删除队头元素后,队列大小:" << q.size() << endl;
cout << "新的队头元素:" << q.front() << endl;
return 0;
}
运行代码:
queue使用的注意事项:
- 使用前需要包含头文件。
- queue是一种FIFO(先进先出)的数据结构,只能在队列的末尾添加元素,在队列的头部删除元素。
- queue的底层实现可以是deque或list,因此可以根据需要选择适合的底层实现。默认情况下,使用deque作为底层实现。
- queue的成员函数empty()、size()、front()、back()、push()、pop()的时间复杂度均为O(1)。
- 使用front()和back()方法获取队头和队尾元素的引用时,需要先判断队列是否为空,否则会导致程序崩溃。
- 在使用自定义类型作为queue的元素时,需要重载运算符<,以便queue可以比较元素大小,从而实现排序。
优先队列(Priority Queue)是一种容器适配器,它根据严格的弱排序标准,使得优先队列的第一个元素总是它所包含的元素中最大的。在优先队列中,可以随时插入元素,但只能检索最大元素(优先队列中位于顶部的元素)。
在C++中,优先队列被实现为容器适配器,它可以将特定容器类封装作为其底层容器类,并提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。
底层容器可以是任何标准容器类模板,例如vector和deque,也可以是其他特定设计的容器类。该容器应该可以通过随机访问迭代器访问,并支持以下操作:
- empty():检测容器是否为空。
- size():返回容器中有效元素的个数。
- front():返回容器中第一个元素的引用。
- push_back(const T& obj):在容器尾部插入元素obj。
- pop_back():删除容器尾部元素。
需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap和pop_heap来自动完成此操作。
默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。
优先队列(Priority Queue)默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构。因此,priority_queue本质上就是一个堆,可以用于需要使用堆的位置。
默认情况下,priority_queue是大堆(即最大堆),即优先队列中的第一个元素总是最大的。如果需要使用最小堆,可以通过指定比较函数来实现。
priority_queue提供了以下常用操作:
函数 | 说明 |
---|---|
priority_queue() | 构造一个空的优先级队列。 |
priority_queue(first, last) | 构造一个空的优先级队列。 |
empty() | 检测优先级队列是否为空,是返回true,否则返回false。 |
top() | 返回优先级队列中最大(最小)元素,即堆顶元素。 |
push(x) | 在优先级队列中插入元素x。 |
pop() | 删除优先级队列中最大(最小)元素,即堆顶元素。 |
示例代码:
#include
#include
using namespace std;
int main() {
priority_queue<int> pq;
pq.push(3);
pq.push(1);
pq.push(4);
pq.push(1);
cout << "堆顶元素:" << pq.top() << endl;
pq.pop();
cout << "删除堆顶元素后,新的堆顶元素:" << pq.top() << endl;
return 0;
}
运行结果:
如果需要使用最小堆,可以通过指定比较函数来实现。例如,以下代码演示了如何创建一个最小堆:
#include
#include
using namespace std;
int main()
{
priority_queue<int, vector<int>, greater<int>> minHeap;
minHeap.push(3);
minHeap.push(1);
minHeap.push(4);
minHeap.push(1);
cout << "堆顶元素:" << minHeap.top() << endl;
minHeap.pop();
cout << "删除堆顶元素后,新的堆顶元素:" << minHeap.top() << endl;
return 0;
}
以下是使用priority_queue时需要注意的事项:
- 使用前需要包含头文件
。
- 默认情况下,priority_queue是最大堆,即最大的元素总是位于队列的最前面。如果需要使用最小堆,可以通过指定比较函数来实现。
- priority_queue的底层实现是堆,因此可以用于实现最大堆或最小堆。堆是一种特殊的二叉树,具有以下性质:
- 堆是一棵完全二叉树。
- 堆中每个节点的值都大于等于(或小于等于)其子节点的值。
本篇博客对c++的stack,queue和priority_queue的介绍和使用进行了阐述,以上三种容器的使用都十分简单,只需要调用相应的方法即可。需要注意的是,使用这些容器时,需要注意线程安全问题、内存管理问题和异常处理问题。
此外,C++还提供了其他的容器,如vector、list、map等,不同的容器适用于不同的场景,开发者需要根据具体的需求选择合适的容器。
到此为止,如果觉得本篇文章对你有帮助的话就请点一个小小的吧,你的鼓励就是我的动力。