基础介绍
- 栈是一种只能在一端进行插入或删除操作的线性表。
- 特点:先进后出
- 分类:顺序栈和链栈
栈
基础
【模板】栈
定义、进栈、出栈
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int st[N];
int top = -1;
int main()
{
int n;
cin>>n;
while(n--)
{
string c;
cin>>c;
if(c == "push")
{
int x;
cin>>x;
st[++top] = x;
}else if(c == "top"){
if(top == -1)
cout<<"error"<<endl;
else{
cout<<st[top]<<endl;
}
}else if(c == "pop"){
if(top == -1)
cout<<"error"<<endl;
else{
cout<<st[top--]<<endl;
}
}
}
return 0;
}
栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
stack<int> data; //构建栈
int j = 0;
for(int i = 0; i < pushV.size(); i++)
{
data.push(pushV[i]); //进栈
while(data.size() > 0 && popV[j] == data.top())
{
data.pop();
j++;
}
}
return data.empty();
}
};
有效括号序列
给出一个仅包含字符’(‘,’)‘,’{‘,’}‘,’[‘和’]',的字符串,判断给出的字符串是否是合法的括号序列
class Solution {
public:
/**
*
* @param s string字符串
* @return bool布尔型
*/
bool isValid(string s) {
// write code here
stack<char> data;
int n = s.length();
if(n%2 != 0)
return false;
for(int i = 0; i<n; i++)
{
if(data.size() == 0)
data.push(s[i]);
else{
if(data.top() == '(' && s[i] == ')')
data.pop();
else if(data.top() == '[' && s[i] == ']')
data.pop();
else if(data.top() == '{' && s[i] == '}')
data.pop();
else
data.push(s[i]);
}
}
if(data.empty())
return true;
else
return false;
}
};
逆波兰表达式求值
给定一个逆波兰表达式,求表达式的值。
逆波兰表达式和日常书写的表达式区别是符号会后置。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param tokens string字符串vector
* @return int整型
*/
int evalRPN(vector<string>& tokens) {
// write code here
stack<int> data;
for(int i = 0; i<tokens.size(); i++)
{
if(tokens[i] != "+" && tokens[i] != "-" && tokens[i] != "*" && tokens[i] != "/"){
int t = atoi(tokens[i].c_str());//string-->int
data.push(t);
}
else{
int num = data.top();
data.pop();
if(tokens[i] == "+")
data.top() += num;
else if(tokens[i] == "-"){
data.top() -= num;
}else if(tokens[i] == "*"){
data.top() *= num;
}else if(tokens[i] == "/"){
data.top() /= num;
}
}
}
return data.top();
}
};
点击消除
牛牛拿到了一个字符串。
他每次“点击”,可以把字符串中相邻两个相同字母消除,例如,字符串"abbc"点击后可以生成"ac"。
但相同而不相邻、不相同的相邻字母都是不可以被消除的。
牛牛想把字符串变得尽可能短。他想知道,当他点击了足够多次之后,字符串的最终形态是什么?
#include <bits/stdc++.h>
using namespace std;
int main()
{
string data;
cin>>data;
stack<char> xc1;
//消除
for(auto& i: data)
{
if(!xc1.empty() && xc1.top() == i){
xc1.pop();
}else
xc1.push(i);
}
//读取
stack<char> xc2;
while(!xc1.empty())
{
xc2.push(xc1.top());
xc1.pop();
}
if(xc2.empty())
{
cout<<0<<endl;
return 0;
}
//输出
while(!xc2.empty())
{
cout<<xc2.top();
xc2.pop();
}
return 0;
}
表达式求解
请写一个整数计算器,支持加减乘三种运算和括号。
空间复杂度: O(n),时间复杂度 O(n)
两个栈、一个存放运算符、一个存放数值
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
int solve(string s) {
// write code here
stack<int> num;//存放数值
stack<char> ops;//存放运算符
int sum = 0;//初始化计算值
for(int i=0; i<s.size(); i++)
{
if(s[i]>='0' && s[i]<='9')
sum = sum*10 +(s[i] - '0');//大于10的数值
else
{
if(sum!=0)
{
num.push(sum);//将数值入栈
sum = 0;
}
if(ops.empty() || ops.top() == '(' || s[i] == '(')
ops.push(s[i]);
else{
if(s[i] == ')'){
while(ops.top() != '('){
int x = num.top();
num.pop();
int y = num.top();
num.pop();
if(ops.top() == '+')
num.push(x+y);
else if(ops.top() == '-')
num.push(y-x);
else if(ops.top() == '*')
num.push(x*y);
ops.pop();
}
ops.pop();
}else{
while(!ops.empty() && judge(s[i], ops.top()) == false)
{
int x = num.top();
num.pop();
int y = num.top();
num.pop();
if(ops.top() == '+')
num.push(x+y);
else if(ops.top() == '-')
num.push(y-x);
else if(ops.top() == '*')
num.push(x*y);
ops.pop();
}
ops.push(s[i]);
}
}
}
}
if(sum!=0)
num.push(sum);
while(!ops.empty())
{
int x = num.top();
num.pop();
int y = num.top();
num.pop();
if(ops.top() == '+')
num.push(x+y);
else if(ops.top() == '-')
num.push(y-x);
else if(ops.top() == '*')
num.push(x*y);
ops.pop();
}
return num.top();
}
bool judge(char c1, char c2)
{
if(c1 == '(')
return true;
else if(c1 == ')')
return false;
else if(c2 == '(')
return true;
else if((c1 == '*' || c1 == '/') && (c2 == '+' || c2=='-') )
return true;
else
return false;
}
};
进阶
队列
基础
【模板】队列
#include <bits/stdc++.h>
using namespace std;
const int maxSize = 1e5 + 5;
int main()
{
//构建队列
int data[maxSize];
int front = 0; //队头
int rear = 0; //队尾
int n;
cin>>n;
while(n--)
{
string c;
cin>>c;
if(c =="push")
{
int x;
cin>>x;
data[rear] = x;
rear = (rear+1) % maxSize;
}else if(c == "pop")
{
if(front == rear)
cout<<"error"<<endl;
else{
cout<<data[front]<<endl;
front = (front+1) % maxSize;
}
}else if(c == "front")
{
if(front == rear)
cout<<"error"<<endl;
else
cout<<data[front]<<endl;
}
}
return 0;
}
【模板】循环队列
#include <bits/stdc++.h>
using namespace std;
int main()
{
//构建队列
int n;
cin>>n;
n = n+1;//多一个空间
int data[n];
int front = 0; //队头
int rear = 0; //队尾
int q;
cin>>q;
while(q--)
{
string c;
cin>>c;
if(c =="push")
{
int x;
cin>>x;
if((rear+1)%n == front)
cout<<"full"<<endl;
else{
data[rear] = x;
rear = (rear+1) % n;
}
}else if(c == "pop")
{
if(front == rear)
cout<<"empty"<<endl;
else{
cout<<data[front]<<endl;
front = (front+1) % n;
}
}else if(c == "front")
{
if(front == rear)
cout<<"empty"<<endl;
else
cout<<data[front]<<endl;
}
}
return 0;
}
进阶
栈和队列
简单
用两个栈实现队列
描述
用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
int t = 0;
if(stack2.size() == 0){
while(stack1.size() > 0){
stack2.push(stack1.top());
stack1.pop();
}
}
t = stack2.top();
stack2.pop();
return t;
}
private:
stack<int> stack1;
stack<int> stack2;
};