一、栈(Stack)是另一种非常常见的线性数据结构,它遵循 后进先出(LIFO, Last In First Out) 的原则。即最后进入栈的元素会最先被移除。栈的操作包括:入栈(push)、出栈(pop)、查看栈顶元素(top)等。
栈的基本操作:
- Push:将一个元素压入栈顶。
- Pop:将栈顶的元素移除。
- Top:查看栈顶的元素,但不移除。
- Empty:检查栈是否为空。
- Size:获取栈中元素的数量。
标准栈的实现:
在 C++ 中,可以使用 std::stack
来实现栈。std::stack
是一个基于容器适配器(container adapter)实现的栈,它默认使用 std::deque
作为底层容器,也可以使用 std::vector
或 std::list
#include <iostream>
#include <stack>
using namespace std;
int main() {
// 创建一个栈,存储整数
stack<int> s;
// 入栈操作
s.push(10); // 将10压入栈中
s.push(20); // 将20压入栈中
s.push(30); // 将30压入栈中
// 查看栈的大小
cout << "Size of stack: " << s.size() << endl;
// 查看栈顶元素
cout << "Top element: " << s.top() << endl;
// 出栈操作
cout << "Popping element: " << s.top() << endl; // 先查看栈顶元素
s.pop(); // 弹出栈顶元素
// 查看栈顶元素(出栈后的新栈顶)
cout << "New Top element: " << s.top() << endl;
// 检查栈是否为空
if (s.empty()) {
cout << "Stack is empty." << endl;
} else {
cout << "Stack is not empty." << endl;
}
// 出栈剩余的元素
s.pop(); // 弹出20
s.pop(); // 弹出10
cout << "Stack size after popping all elements: " << s.size() << endl;
return 0;
}
代码输出
Size of stack: 3
Top element: 30
Popping element: 30
New Top element: 20
Stack is not empty.
Stack size after popping all elements: 0
栈的应用场景:
-
函数调用栈: 在程序的执行过程中,计算机使用栈来管理函数调用。在函数执行时,函数的参数、局部变量和返回地址会被压入栈中,函数执行完毕后,栈会弹出相应的元素。
-
逆序处理: 栈可以用来逆序数据,例如字符串反转,表达式求值等。
-
括号匹配: 在编译器中,栈可以用来检查括号是否匹配,例如括号成对出现的问题(如
()
,[]
,{}
等)。 -
深度优先搜索(DFS): 栈是深度优先搜索(DFS)算法的基础,可以用来实现图的遍历。
栈的优势:
- 后进先出(LIFO)原则:栈可以方便地模拟这种模式,适用于一些需要按顺序处理数据的场景。
- 高效的操作:栈的入栈和出栈操作时间复杂度都是 O(1),这意味着操作非常高效。
- 动态大小:栈的大小可以动态增长,不需要预先指定大小。
总结:
- 栈(Stack) 是一种后进先出(LIFO)的数据结构,适用于需要按相反顺序处理数据的场景。
- C++ 提供了
std::stack
来实现栈,它基于容器适配器提供了栈的基本操作。 - 通过上述示例代码,我们展示了如何使用栈来执行基本的入栈、出栈、查看栈顶元素等操作。
二、队列(Queue)是一个非常常见的数据结构,它遵循 先进先出(FIFO, First In First Out) 的原则,意味着最先进入队列的元素会最先被移除。与栈(Stack)不同,栈遵循后进先出(LIFO)的原则。
队列的基本操作:
- Enqueue(入队):将一个元素添加到队列的末尾。
- Dequeue(出队):将队列头部的元素移除并返回。
- Front:查看队列头部的元素(不移除)。
- Back:查看队列末尾的元素(不移除)。
- Empty:检查队列是否为空。
- Size:获取队列中元素的数量。
标准队列的实现:
在 C++ 中,可以使用 std::queue
来实现队列。std::queue
是一个基于容器适配器(container adapter)实现的队列,它默认使用 std::deque
(双端队列)作为底层容器,也可以使用 std::list
。
示例代码:
#include <iostream>
#include <queue>
using namespace std;
int main() {
// 创建一个队列,存储整数
queue<int> q;
// 入队操作
q.push(10); // 入队 10
q.push(20); // 入队 20
q.push(30); // 入队 30
// 查看队列的大小
cout << "Size of queue: " << q.size() << endl;
// 查看队列的头部元素
cout << "Front element: " << q.front() << endl;
// 查看队列的尾部元素
cout << "Back element: " << q.back() << endl;
// 出队操作
cout << "Dequeuing element: " << q.front() << endl; // 先查看头部元素
q.pop(); // 出队,移除头部元素
// 查看队列的头部元素(出队后的新头部)
cout << "New Front element: " << q.front() << endl;
// 检查队列是否为空
if (q.empty()) {
cout << "Queue is empty." << endl;
} else {
cout << "Queue is not empty." << endl;
}
// 出队剩余的元素
q.pop(); // 出队 20
q.pop(); // 出队 30
cout << "Queue size after popping all elements: " << q.size() << endl;
return 0;
}
输出结果
Size of queue: 3
Front element: 10
Back element: 30
Dequeuing element: 10
New Front element: 20
Queue is not empty.
Queue size after popping all elements: 0
队列的优势:
- 先进先出(FIFO)特性:队列保持元素的插入顺序,适合模拟一些需要按顺序处理的场景,比如任务调度、消息处理等。
- 动态大小:
std::queue
根据需要自动调整大小,适应任意数量的元素。 - 高效的操作:入队和出队操作的时间复杂度为 O(1),即队列的操作效率非常高。
队列的应用场景:
- 任务调度:操作系统使用队列来调度任务,确保按照顺序执行任务。
- 广度优先搜索(BFS):BFS 算法通过队列来实现,它遍历图的节点时,会按照节点的层级顺序进行处理。
- 消息队列:在多线程或分布式系统中,队列常用于存储和传递消息,以确保消息按照发送顺序处理。
- 缓冲区管理:队列常用于数据流的缓冲区,确保数据按顺序处理。
总结:
- 队列(Queue) 是一种先进先出(FIFO)的数据结构,适用于需要按顺序处理数据的场景。
- C++ 提供了
std::queue
作为标准库实现,它支持高效的入队和出队操作。 - 通过上面的示例代码,我们展示了如何使用队列来进行基本的操作(入队、出队、查看元素等)。