栈的性质(进栈,出栈,访问)

C++ stack 栈

头文件:#include<stack>

栈:后进先出 LIFO,后压入栈的元素,最先拿出来。

常用成员汇总

函数 作用
st.push(x) 将x压入栈顶
st.top() 获取栈顶元素,不删除
st.pop() 删除栈顶,void无返回
st.empty() 栈空返回true
st.size() 返回栈中元素数量

注意:栈不能遍历,不能随机访问sti,只能操作栈顶。

2.可以存什么类型

cpp 复制代码
stack<int> st1;
stack<pair<int,int>> st2;
stack<string> st3;

//pair入栈
st2.push({1,2});
auto p = st2.top();
st2.pop();

3.栈使用场景

  1. ** 括号匹配**(经典)
    . P1739 表达式括号匹配 - 洛谷

​**32. 最长有效括号 - 力扣(LeetCode)**

一键直达​ P1739 32

​ 2.模拟进出栈

吐泡泡

Rails

​一键直达 吐泡泡 Rails

4.栈的例题

P1739 表达式括号匹配 - 洛谷

复制代码
#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<char> st;
    char c;
    while (cin >> c) {
        if (c == '#') break; 
        if (c == '(') {
            st.push(c);
        } else if (c == ')') {
            if (st.empty()) {
                cout << "NO" << endl;
                return 0;
            }
            st.pop();
        }
    }
    if (st.empty()) {
        cout << "YES" << endl;
    } else {
        cout << "NO" << endl;
    }
    return 0;
}

题目:判断括号是否匹配。

思路:

遇到左括号 '(' 入栈;

遇到右括号 ')'

  • 如果栈为空,直接不匹配;
  • 否则弹出栈顶(抵消一对括号)。
    遍历结束,栈必须为空才算全部匹配。
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main(){
    string s;
    cin>>s;
    stack<char> st;
    bool ok=true;
    for(auto ch:s){
        if(ch=='('){
            st.push(ch);
        }else if(ch==')'){
            if(st.empty()){
                ok=false;
                break;
            }
            st.pop();
        }
    }
    if(ok && st.empty()) cout<<"YES";
    else cout<<"NO";
    return 0;
}

32. 最长有效括号 - 力扣(LeetCode)

题目大意:可以匹配的括号中,所有括号共有多少

思路:遇到左括号,把他的下标进栈,遇到右括号,弹出栈顶,()))像这种尽管前面有2个有效括号,但有个右括号后就不匹配了,更改新的有效长度起点,一直出现右括号,就会进入栈空条件,让当前下标进入栈里,也就更新了有效括号的起始位置,栈里首先要要进一个数字-1,)()或())像这种防止栈里没有左括号时栈空(((()像这种一直出现左括号,栈顶会是出现有效括号最后一次左括号的位置

复制代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s;
	cin>>s;
	stack<int>st;
	st.push(-1);
	int max1=0; 
	for(int i=0;i<s.size();i++)
	{
		if(s[i]=='(')
		st.push(i);
		else
		{
			st.pop();
			//不再有效 ,招到新的栈顶元素 
			if(st.empty())
			st.push(i);
			//在每段有效中找到最长的那段 
			else
			max1=max(max1,i-st.top());
		}
	}
	cout<<max1<<endl;
}

吐泡泡

题目大意:oo==O,OO=空,按照这个规则把字符串压缩

思路:栈空时直接把此元素入栈,并且退出循环,遍历下一个字符,遇到oo时,变为O后要循环有没有和O能消的,遇到OO时,消完后退出此次循环,读取下一个字符,不是这两种情况的,记录当前字符退出循环,读取下一个字符

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
const int N=101;

void slove(){
    string s;
    cin>>s;
    stack<char>st; 
    for(auto c:s){
        char now = c;
        // 必须while循环,如果为空的话,只会把当前字符入栈,
		//不能产生两种字符对比,要退出循环 
        while(true)
        {
            if(st.empty()){
                st.push(now);
                break;
            }
            char tp = st.top();
            //这里还要进行循环,这里结合成的O可能会和前面O抵消
			//或者栈空把·O入栈
			//或者o,把O入栈 
            if(tp == 'o' && now == 'o')
            {
                st.pop();
                now = 'O';
            }
            //每次进入一个字符时,都会进行oo,OO这样的结合
			//再不能进行这两种的结合后,就是进入下面两个条件之一
			//退出循环,读入下一个字符 
            else if(tp == 'O' && now == 'O')
            {
                st.pop();
                break;//进行到这,之前能结合的都结合过了,退出去就行 
            }
            //
            else
            {
                st.push(now);//没有可结合的 
                break;
            }
        }
    }
    string s1;
    while(!st.empty()){
        s1.push_back(st.top());
        st.pop();
    }
    reverse(s1.begin(),s1.end());
    cout<<s1<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _;
    cin>>_;
    while(_--)
        slove();
    return 0;
}

Rails

题目大意:模拟这列数字能不能按照给出的出栈方式出栈

思路:当进栈的那个元素与给出的序列前端的那个元素相等时,弹出栈顶,让下一个字符与栈顶元素比较

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
//把一组从1-n的数字按照入栈和出栈的性质,看能否操作出出栈后是给出的这段序列,
//5 4 1 2 3,5个数字全部入栈了,5 4 弹出后,还没弹出 3 2就先弹出1了
//3 2 1 4 5 
//3 2 4 1 5
//5 4 3 2 1 
void slove(){
    int n;
    while(cin >> n && n != 0) // 读到n=0整体结束
    {
        int target;
        while(cin >> target)
        {
            if(target == 0) break; // 当前n的所有查询结束
            vector<int> seq;
            seq.push_back(target);
            // 读取本行剩余数字
            for(int i=2;i<=n;i++)
            {
                cin >> target;
                seq.push_back(target);
            }
            stack<int> st;
            int now = 1; // 下一个要进站的车厢
            bool ok = true;
            for(int x : seq)
            {
                // 不断入栈直到栈顶等于x
                //再入栈的元素不是栈顶或栈空时,这些元素都进栈 
                while(now <= n && (st.empty() || st.top() != x))
                {
                    st.push(now++);
                }
                //这个数字也要出栈的一样,去掉栈顶,等到下一次循环
				//要出栈的元素X可能就是新的栈顶,如果不出栈,就会进入while进栈 
                if(st.top() == x)
                {
                    st.pop();
                }
                else
                {
                    ok = false;
                    break;
                }
            }
            if(ok) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
        cout << endl; // 每组n处理完输出空行,题目要求
    }
}

signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    slove();
    return 0;
}
相关推荐
库玛西18 分钟前
深入浅出Linux select网络模型:从底层位图原理到C++面向对象高级封装
linux·服务器·网络·c++·ubuntu
2402_8828938626 分钟前
深入浅出 unordered_map 与 unordered_set——从使用到底层差异
c++·哈希·unordered_map·unordered_set
洋不写bug44 分钟前
链表补充练习,双链表的模拟实现
java·数据结构·链表·双链表·底层实现
今天要早睡_1 小时前
C++ 核心语法速过:命名空间、引用、函数重载与 nullptr 深度解析
android·java·c++
白狐_7981 小时前
408 数据结构|外部排序:流程与 k 路归并
数据结构·算法
汉克老师1 小时前
CSP-J 初赛(以满分为目标):第二十七课 《图的遍历——BFS广度优先搜索——像“水波纹”一样,一层一层地搜索》
c++·csp-j·小学生·学c++编程
闻缺陷则喜何志丹1 小时前
【动态规划】P3609 [USACO17JAN] Hoof, Paper, Scissor G
c++·算法·动态规划·洛谷
汉克老师2 小时前
CSP-J 初赛(以满分为目标):第二十六课 《图的遍历——DFS深度优先搜索——从“树的先序遍历”走进真正的图世界》
c++·csp-j·小学生·学c++编程
程序猿编码2 小时前
基于GGML的C++17轻量化语音推理引擎:说话人识别与语音分析技术全解析
开发语言·c++·pytorch·深度学习·神经网络·大模型
影视飓风TIM2 小时前
C++哈希表深度剖析:冲突处理、rehash、迭代器与unordered容器封装
c++·哈希算法·散列表