基础算法--栈和队列

0 阅读2分钟

栈和队列


栈和队列是两个经典的数据结构,在算法讲解中,我们不会像数据结构中那样去剖析怎么写一个栈或者队列,而是调用STL库中的stack和queue帮助我们解决题目。 关于栈,主要是利用其先进后出的特性,最为经典的题目就是括号匹配。 关于队列,主要用于辅助,例如图的BFS就需要队列的辅助实现。

我们来一起看几道题目~

栈和队列.png

分析: 我们按入栈顺序入栈,如果栈顶元素与出栈元素相同,就将其弹出。如果不相同,就继续将元素压入栈,最后如果stack为空就输出Yes,否则输出No。

下面是代码示例:

#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
int q, n;
int a[100005], b[100005];
stack<int> s;

int main(){
    cin >> q;
    for(int k = 1; k <= q; ++k){
        //每次循环之前,先把数组和栈清空
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        while(!s.empty()){
            s.pop();
        }
        
        cin >> n;
        for(int i = 1; i <= n; ++i){
            cin >> a[i];
        }
        for(int i = 1; i <= n; ++i){
            cin >> b[i];
        }

        int i, j = 1;
        for(i = 1; i <= n; ++i){
            s.push(a[i]);//第i个数入栈
            while(!s.empty() && s.top() == b[j]){//栈非空 并且栈顶元素是预期出栈的数据 出栈
                s.pop();
                ++j;
            }
        }
        if(s.empty())cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

下一道~

栈和队列-1.png

分析: 给了我们小行星的数组,我们首先分析下什么情况下会撞:+向右飞,-向左飞,那么显然只有+ -的组合才会导致相撞。那么其实在匹配问题上,这道题目和括号匹配是一样的,只是左括号对应+,右括号对应-。 那么这道题我们就可以用栈来模拟: 以下情况不会发生碰撞,可把当前行星压入栈:

  • 栈为空,不管当前行星是正是负都要压入栈;
  • 当前行星和栈顶行星同号说明同向移动,不会相碰;
  • 当前行星向右移动(+),栈顶行星向左移动(-),不会相撞; 只有一种情况会发生碰撞:当前行星向左,栈顶行星向右,做判断:
  • 栈顶元素大于abs(当前元素),当前元素被撞毁;
  • 栈顶元素等于abs(当前元素),栈顶弹出和当前元素抵消;
  • 栈顶元素小于abs(当前元素),栈顶弹出,并于新栈顶完成上述判断; 最终返回栈即可。

下面是代码示例:

#include <iostream>
#include <vector>
using namespace std;

vector<int> asteroidCollision(vector<int>& asteroids) {
    int n = asteroids.size();
    vector<int> s;  //数组模拟栈
    for(int i = 0; i < n; ++i){
        if(s.empty() || asteroids[i] > 0){
            s.push_back(asteroids[i]);
        }
        else{
            while(s.size() && s.back() > 0 && s.back() < -asteroids[i]){
                //栈顶是+,要入栈的数是-,栈顶的绝对值小,栈顶被撞没
                s.pop_back();
            }
            if(s.empty() || s.back() < 0){//不撞
                s.push_back(asteroids[i]);
            }
            else if(s.back() == -asteroids[i]){//两个全撞没
                s.pop_back();
            }
        }
    }

    return s;
}

int main(){
    int n, x;
    vector<int> a;
    vector<int> ans;
    cin >> n;
    for(int i = 1; i <= n; ++i){
        cin >> x;
        a.push_back(x);
    }
    ans = asteroidCollision(a);
    int l = ans.size();
    for(int i = 0; i < l; ++i){
        cout << ans[i] << " ";
    }

    return 0;
}