数据结构第一节:栈

序:在经历了Acwing的“从入门到入土”,终于于今天进入了代码源的学习(心疼我好几百报的课阿T_T)。据y总言——”STL是提高C++编写效率的一个利器。“因此,为了提高我们编写代码的效率,咱今天就来学习——数据结构第一节:栈。


“求木之长者,必先固其根本;欲流之远者,必先浚其泉源。”因此,要想学好stl,首先我们要搞明白它的底层逻辑。而今天学习的栈,我们便可以用数组的形式实现。下面是几个例子:


例题1
代码源-101

img

#include <iostream>
 
using namespace std;
 
int top = 0;
char a[1000010];
int s[1000010];
 
int main()
{
    int m;
    scanf ("%d", &m);
 
    for ( int i = 1; i <= m; i++ ){
        scanf("%s" ,a);
 
        if( a[1] == 'u' ) {
            int x;
            scanf("%d" , &x);
            s[++top] = x;
        }else if ( a[0] == 'p' ) {
            --top;
        }else{
            printf("%d\n", s[top]);
        }
    }
 
    return 0;
}

例题2
代码源-104

#include <bits/stdc++.h>
 
using namespace std;
 
int n,top;
char s[100001];
char str[100001];
 
int main()
{
 
    scanf("%d" , &n);
    scanf("%s" ,str);
 
    top = 0;
    bool ok = true;
 
    for ( int i = 0; i < n && ok; i++ )
 
        //先将所有左括号放入栈中
        if ( str[i] == '(' || str[i] == '[' ) s[++top] = str[i];
 
        else if ( !top ) ok = false;  // “ if ( !x )” 等价于 “ if ( x == 0 )”
 
        else if( str[i] == ')' ) {    // 如果新读入的右括号可以和左括号匹配,则删除栈顶左括号
            if (s[top] == '(') --top;
            else ok = false;
        }
 
        else{
            if ( s[top] == '[' ) --top;
            else ok = false;
        }
                        
    if ( top )
        ok = false;   //如果栈没有被清空,也就是说还有未匹配的左括号存在,不合法 
 
    if ( ok )
        printf("Yes\n");
    else
        printf("No\n");
 
    return 0;
}

例三
代码源-106

img


#include <iostream>
 
using namespace std;
 
int n,top = 0;
char s[100010];
char str[100010];
 
int main()
{
 
    scanf("%d%s", &n, s);
 
    for ( int i = 0; i < n; i++ ) {
 
        if (  (int) s[i] == str[top] - 32 || (int) s[i] == str[top] + 32) {
            top--;
        }
            else {
                str[++top] = (int)s[i];
             }
        }
 
    for ( int i = 1; i <= top ; i++ ) printf("%c", str[i]);
 
    return 0;
}

个人理解:依据上述例题,我们可以看出,栈可以简易的理解成构造了一个自下而上的数组可以继续向上拓展的数组,对于这个数组,每次可以向上存储一个数据,且储存的数据,可以从顶部弹出。


对应的stl函数,则存放在头文件 #include 中;

​ 他们可以很便捷的帮我们实现一些功能,

​ 比如上述用到的几个函数:

#include <stack>
using namespace std;
int main()
{
    int x;
    stack<int> s;
    s.push(x); //在栈s顶插入x;
    s.pop();   //删除栈顶元素;
    s.top();   //返回栈顶元素;
}

另外,该头文件中还有其他一些方便的函数,如:

 s.empty(); //查询栈s是否为空  ps:返回值是布尔值
    s.size();  //查询栈中含有元素个数

利用这些函数,我们可以简化我们的代码:

如例一可以进行如下改写;

#include <bits/stdc++.h>
#include <stack> //栈
using namespace std;

stack<int> s;
int m;
char a[100010];

int main()
{
    scanf("%d", &m);

    for ( int i = 0 ; i < m; i++ ){

        scanf("%s", a);

        if ( a[1] == 'u' ) {
            int x;
            scanf("%d" ,&x);
            s.push(x);
        }else if ( a[0] == 'p' ) {
            s.pop();
        }else{
            printf("%d\n", s.top() );
        }

    }

    return 0;
}

然而,这些函数在便捷的为我们服务的同时,也暴露出他们的些许局限性,

假如说我们想要访问栈中自栈顶而下的第k个元素,只是单单得使用stl函数就无法实现这个功能。

而如果理解其底层逻辑——用数组进行求解,则可以通过s[top + 1 - k]来求解。


总结:stl函数可以极大的便利我们的编码过程,但身为初学者,还是很有必要了解其底层逻辑,以解决一些意料之外的问题。

posted @ 2022-12-20 22:47  筱天丶  阅读(48)  评论(0)    收藏  举报