【25届秋招备战C++】数据结构篇-栈与队列
栈(Stack)
一、 栈的定义
栈是一种遵循后进先出(LIFO)原则的数据结构,它在内存中以连续的方式存储元素。在栈中,添加和移除元素的操作都发生在栈顶。
特点:
- 栈的下标通常从0开始。
- 栈的内存空间是连续的。
- 栈不支持直接的元素删除操作,只能通过覆盖实现。
- 栈支持随机访问,但通常只访问栈顶元素。
实现:
STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器),栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。C++标准库提供了std::stack模板类
二、算法复杂度
访问Acess:O(1)-栈顶元素
搜索Search:O(N)
插入Insert:O(1)
删除Remove:O(1)-栈顶元素
三、常用操作
创建栈
#include <stack>
// 初始化一个空的栈,底层容器默认为 std::deque
std::stack<int> myStack;
// 初始化一个空的栈,指定底层容器为 std::vector
std::stack<int, std::vector<int>> myStackWithVector;
添加元素
// 使用 push 方法向栈中添加元素
myStack.push(1);
myStack.push(2);
myStack.push(3);
查看栈顶元素-即将出栈的元素
// 使用 top 方法访问栈顶元素
std::cout << "栈顶元素: " << myStack.top() << std::endl;
删除栈顶元素-即将出栈的元素
// 使用 pop 方法移除栈顶元素
myStack.pop();
栈的长度
// 获取栈的长度
size_t stackSize = myStack.size();
栈是否为空
// 检查栈是否为空
if (myStack.empty()) {
std::cout << "栈为空。" << std::endl;
} else {
std::cout << "栈不为空。" << std::endl;
}
遍历栈
// 遍历栈
while (!myStack.empty()) {
int topElement = myStack.top(); // 获取栈顶元素
myStack.pop(); // 弹出栈顶元素
}
链式栈的实现
// 定义栈节点结构
struct StackNode {
int data; // 存储栈中的数据
StackNode* next; // 指向下一个节点的指针
// 构造函数
StackNode(int value) : data(value), next(nullptr) {}
};
// 链式栈类
class LinkedStack {
private:
StackNode* topNode; // 指向栈顶节点的指针
public:
// 构造函数
LinkedStack() : topNode(nullptr) {}
// 压栈操作
void push(int value) {
StackNode* newNode = new StackNode(value);
newNode->next = topNode; // 新节点的下一个指针指向当前栈顶
topNode = newNode; // 更新栈顶指针
}
// 弹栈操作
void pop() {
if (topNode != nullptr) {
StackNode* temp = topNode; // 临时存储栈顶节点
topNode = topNode->next; // 更新栈顶指针
delete temp; // 删除原栈顶节点
} else {
std::cerr << "栈为空,无法弹出元素。" << std::endl;
}
}
// 获取栈顶元素
int top() {
if (topNode != nullptr) {
return topNode->data;
} else {
std::cerr << "栈为空。" << std::endl;
throw std::runtime_error("栈为空。");
}
}
// 检查栈是否为空
bool isEmpty() {
return topNode == nullptr;
}
// 析构函数,释放栈内存
~LinkedStack() {
while (!isEmpty()) {
pop();
}
}
};
四、总结——基本函数
push:在栈顶添加一个元素。
pop:移除栈顶元素。
top:访问栈顶元素,但不移除。
isEmpty:检查栈是否为空。
size:获取栈中元素的数量。
队列(Queue)
一、队列的定义
队列是一种遵循先进先出(FIFO)原则的数据结构。元素从队尾添加,从队首移除。
单端队列:只有一个口可以进,一个口可以出
双端队列:两个口可以进,也都可以出
特点:
队列不支持随机访问,只能访问队首和队尾元素。
队列的内存空间可以是连续的,也可以是不连续的。
实现方式:
使用数组、链表或双端队列(deque)。C++标准库提供了std::queue模板类。
二、算法复杂度
访问Acess:O(N)
搜索Search:O(N)
插入Insert:O(1)
删除Remove:O(1)
三、常用操作
创建队列
#include <queue>
// 创建一个空的队列
std::queue<int> myQueue;
添加元素
// 向队列中添加元素
myQueue.push(1);
myQueue.push(2);
获取即将出队的元素
// 获取即将出队的元素
int frontElement = myQueue.front();
std::cout << "即将出队的元素是: " << frontElement << std::endl;
删除即将出队的元素
myQueue.pop();
判断队列是否为空
// 检查队列是否为空
if (myQueue.empty()) {
std::cout << "队列为空。" << std::endl;
} else {
std::cout << "队列不为空。" << std::endl;
}
队列长度
// 获取队列的长度
size_t queueSize = myQueue.size();
遍历队列
while (!myQueue.empty()) {
int frontElement = myQueue.front(); // 获取队列前端元素
std::cout << frontElement << " ";
myQueue.pop(); // 移除队列前端元素
}
双端队列的常用操作
#include <iostream>
#include <deque>
int main() {
// 创建一个空的双端队列
std::deque<int> myDeque;
// 向双端队列中添加元素
myDeque.push_back(1); // 在队列尾部添加元素
myDeque.push_front(2); // 在队列头部添加元素
// 访问队列头部和尾部的元素
std::cout << "队列头部元素: " << myDeque.front() << std::endl;
std::cout << "队列尾部元素: " << myDeque.back() << std::endl;
// 遍历双端队列
for (int value : myDeque) {
std::cout << value << " ";
}
std::cout << std::endl;
// 移除队列头部的元素
myDeque.pop_front();
return 0;
}
四、总结——基本函数
同栈类似,且除上述函数外,也可以通过调用C语言函数实现即:
enqueue:在队尾添加一个元素。
dequeue:移除队首元素。
front:访问队首元素,但不移除。
isEmpty:检查队列是否为空。
size:获取队列中元素的数量。