栈(Stack)是一种线性数据结构,遵循“后进先出”(Last In First Out, LIFO)的原则。这意味着最后一个被添加到栈中的元素将是第一个被移除的元素。
栈的主要特点
-
后进先出(LIFO):
- 最后一个进入栈的元素最先被移除。
- 这种特性使得栈非常适合需要回溯的操作。
-
单端操作:
- 所有的插入和删除操作都发生在栈顶(顶部)。
- 不能直接访问或修改栈底(底部)的元素,除非先移除所有上面的元素。
-
基本操作:
- Push:将一个元素压入栈顶。
- Pop:移除并返回栈顶元素。
- Peek/Top:返回栈顶元素但不移除它。
- IsEmpty:检查栈是否为空。
- Size:返回栈中元素的数量。
栈的应用场景
-
函数调用管理:
- 每当一个函数被调用时,其局部变量和返回地址会被压入栈中。
- 当函数执行完毕时,这些信息会被弹出栈。
-
表达式求值:
- 中缀表达式可以转换为后缀表达式(逆波兰表示法),然后使用栈进行求值。
- 例如,计算
A + B * C
时,可以使用栈来处理运算符的优先级。
-
括号匹配:
- 使用栈可以检查括号是否正确匹配。
- 遇到左括号时压入栈,遇到右括号时弹出栈顶元素并与之匹配。
-
撤销操作:
- 在文本编辑器中,撤销操作可以通过栈实现。
- 每次用户执行一个操作时,将其记录在栈中,撤销时从栈中弹出并恢复之前的版本。
-
深度优先搜索(DFS):
- 在图论中,深度优先搜索可以使用栈来实现。
- 每次访问一个节点时,将其压入栈中,并继续访问其子节点。
栈的实现
栈可以用多种方式实现,最常见的是使用数组或链表。
使用数组实现栈
#include <iostream>
using namespace std;
class Stack {
private:
int* arr;
int top;
int capacity;
public:
Stack(int size) {
arr = new int[size];
capacity = size;
top = -1;
}
~Stack() {
delete[] arr;
}
void push(int x) {
if (isFull()) {
cout << "Stack Overflow" << endl;
return;
}
arr[++top] = x;
}
int pop() {
if (isEmpty()) {
cout << "Stack Underflow" << endl;
return -1;
}
return arr[top--];
}
int peek() {
if (isEmpty()) {
cout << "Stack is empty" << endl;
return -1;
}
return arr[top];
}
bool isEmpty() {
return top == -1;
}
bool isFull() {
return top == capacity - 1;
}
int size() {
return top + 1;
}
};
int main() {
Stack stack(5);
stack.push(1);
stack.push(2);
stack.push(3);
cout << "Top element is: " << stack.peek() << endl;
stack.pop();
stack.pop();
cout << "Stack size is: " << stack.size() << endl;
return 0;
}
使用链表实现栈
#include <iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
class Stack {
private:
Node* top;
public:
Stack() : top(nullptr) {}
~Stack() {
while (!isEmpty()) {
pop();
}
}
void push(int x) {
Node* newNode = new Node;
newNode->data = x;
newNode->next = top;
top = newNode;
}
int pop() {
if (isEmpty()) {
cout << "Stack Underflow" << endl;
return -1;
}
Node* temp = top;
int poppedData = temp->data;
top = top->next;
delete temp;
return poppedData;
}
int peek() {
if (isEmpty()) {
cout << "Stack is empty" << endl;
return -1;
}
return top->data;
}
bool isEmpty() {
return top == nullptr;
}
int size() {
int count = 0;
Node* current = top;
while (current != nullptr) {
count++;
current = current->next;
}
return count;
}
};
int main() {
Stack stack;
stack.push(1);
stack.push(2);
stack.push(3);
cout << "Top element is: " << stack.peek() << endl;
stack.pop();
stack.pop();
cout << "Stack size is: " << stack.size() << endl;
return 0;
}
具体样例
乐乐班上有些同学想入栈或出栈,每次输入学生的学号和姓名,这个同学就入栈,在输入一个数字n, 表示用栈中n个同学出栈。栈初始为空。
输入
每行输入 入栈学生的学号、姓名和出栈学生的人数;
输入EOF结束输入。
输出
出栈学生的信息,包括学号和姓名
结束输入后,输出栈中还有多少学生。
样例输入
10 ou 0
11 yang 0
12 cheng 1
13 tian 1
样例输出
12 cheng
13 tian
There are 2 students in the stack
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
using namespace std;
struct Student {
int id;
string name;
};
int main() {
stack<Student> studentStack;
string line;
while (getline(cin, line)) {
if (line.empty()) continue;
istringstream iss(line);
int id, n;
string name;
// 检查输入是否符合预期格式
if (!(iss >> id >> name >> n)) {
cerr << "Invalid input format: " << line << endl;
continue;
}
studentStack.push({id, name});
for (int i = 0; i < n && !studentStack.empty(); ++i) {
Student s = studentStack.top();
cout << s.id << " " << s.name << endl;
studentStack.pop();
}
}
cout << "There are " << studentStack.size() << " students in the stack" << endl;
return 0;
}
stack<Student> studentStack;
:声明一个stack
对象studentStack
,用于存储学生信息。while (getline(cin, line))
:循环读取每一行输入,直到输入结束(EOF)。if (line.empty()) continue;
:如果当前行为空,则跳过该行。istringstream iss(line);
:创建一个字符串流对象iss
,用于解析当前行的输入。int id, n; string name;
:声明变量id
、name
和n
,分别用于存储学号、姓名和出栈人数。if (!(iss >> id >> name >> n))
:检查输入是否符合预期格式(即能否成功提取id
、name
和n
)。如果不符,则输出错误信息并跳过该行。studentStack.push({id, name});
:将当前学生推入栈顶。for (int i = 0; i < n && !studentStack.empty(); ++i)
:根据n
的值,从栈顶弹出相应数量的学生,并输出他们的信息。Student s = studentStack.top();
:获取栈顶学生的信息。cout << s.id << " " << s.name << endl;
:输出栈顶学生的学号和姓名。studentStack.pop();
:移除栈顶学生。
cout << "There are " << studentStack.size() << " students in the stack" << endl;
:输出栈中剩余的学生数量。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 定义学生结构体
struct Student {
int id; // 学号
string name; // 姓名
};
// 定义栈类
class Stack {
private:
vector<Student> students; // 使用向量存储学生信息
public:
// 将学生推入栈顶
void push(int id, const string& name) {
students.push_back({id, name});
}
// 返回栈顶学生的信息,但不移除栈顶元素
Student peek() {
if (!students.empty()) {
return students.back();
} else {
throw out_of_range("栈为空");
}
}
// 返回并移除栈顶学生的信息
Student pop() {
if (!students.empty()) {
Student student = students.back();
students.pop_back();
return student;
} else {
throw out_of_range("栈为空");
}
}
// 检查栈是否为空
bool isEmpty() {
return students.empty();
}
// 获取栈中学生的数量
int size() {
return students.size();
}
};
int main() {
Stack studentStack; // 创建一个栈对象
int id;
string name;
int popCount;
// 循环读取输入,直到输入结束(EOF)
while (cin >> id >> name >> popCount) {
// 将当前学生推入栈顶
studentStack.push(id, name);
// 根据popCount的值,从栈顶弹出相应数量的学生,并输出他们的信息
for (int i = 0; i < popCount && !studentStack.isEmpty(); ++i) {
Student student = studentStack.pop();
cout << student.id << " " << student.name << endl;
}
}
// 输出栈中剩余的学生数量
cout << "There are " << studentStack.size() << " students in the stack" << endl;
return 0;
}
class Stack
:定义一个栈类,包含以下方法:void push(int id, const string& name)
:将学生推入栈顶。Student peek()
:返回栈顶学生的信息,但不移除栈顶元素。Student pop()
:返回并移除栈顶学生的信息。bool isEmpty()
:检查栈是否为空。int size()
:返回栈中学生的数量。
主函数
cpp
深色版本
int main() {
Stack studentStack; // 创建一个栈对象
int id;
string name;
int popCount;
// 循环读取输入,直到输入结束(EOF)
while (cin >> id >> name >> popCount) {
// 将当前学生推入栈顶
studentStack.push(id, name);
// 根据popCount的值,从栈顶弹出相应数量的学生,并输出他们的信息
for (int i = 0; i < popCount && !studentStack.isEmpty(); ++i) {
Student student = studentStack.pop();
cout << student.id << " " << student.name << endl;
}
}
// 输出栈中剩余的学生数量
cout << "There are " << studentStack.size() << " students in the stack" << endl;
return 0;
}
Stack studentStack;
:声明一个Stack
对象studentStack
。while (cin >> id >> name >> popCount)
:循环读取输入,直到输入结束(EOF)。studentStack.push(id, name);
:将当前学生推入栈顶。for (int i = 0; i < popCount && !studentStack.isEmpty(); ++i)
:根据popCount
的值,从栈顶弹出相应数量的学生,并输出他们的信息。
cout << "There are " << studentStack.size() << " students in the stack" << endl;
:输出栈中剩余的学生数量。