训练营day11(1001) | 第五章 栈与队列

今日内容: 理论基础232.用栈实现队列225. 用队列实现栈20. 有效的括号1047. 删除字符串中的所有相邻重复项

理论基础

栈和队列是STL(C++标准库)中的两个数据结构

栈stack-先进后出;队列queue-先进先出

训练营day11(1001) | 第五章 栈与队列_第1张图片

数据结构问题

1. C++中stack 是容器么?

答:不是。栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可选择的,如vector, deque, list。STL栈和队列不是容器,而被归为容器适配器(container adapter)

stack要求其底层容器需满足如下操作:empty:判空操作;back:获取尾部元素操作; push_back:尾部插入元素操作; pop_back:尾部删除元素操作   (这里的尾部相当于stack的顶部)

2. 我们使用的stack是属于哪个版本的STL?

答:常用SGI STL,该版本下如果没有指定底层实现的话,默认是以deque为栈的底层结构。

3. 我们使用的STL中stack是如何实现的?(队列也是如此

答:栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可选择的,如vector, deque, list,默认使用deque为底层容器。(deque是双向队列,只要封住一端就可实现栈的逻辑)

4. stack 提供迭代器来遍历stack空间么?

答:stack没有迭代器。stack的所有元素进出都必须符合“先进后出”的条件,只有stack顶端的元素,才有机会被外界取用。stack不提供随机访问功能,也不提供迭代器。

初始化栈和队列

std::stack > third;  // 使用vector为底层容器的栈
std::queue> third; // 定义以list为底层容器的队列

232.用栈实现队列

训练营day11(1001) | 第五章 栈与队列_第2张图片

思路

用两个栈,即可模拟队列的功能。队列是输入1-2-3,输出1-2-3;而第一个栈输入1-2-3,输出3-2-1给第二栈,故第二个栈可以输出1-2-3

进队列和进in栈是一样的,所以问题关键是出队列时,要先把in栈数据拿到out栈,再从out栈出

stack基本用法

训练营day11(1001) | 第五章 栈与队列_第3张图片

 代码

class MyQueue {
public:
    stack inStack;
    stack outStack;
    MyQueue() {

    }
    
    void push(int x) {
        inStack.push(x);
    }
    
    int pop() {
        if(outStack.empty()){
            while(!inStack.empty()){
                outStack.push(inStack.top());
                inStack.pop();
            }
        }
        int result = outStack.top();
        outStack.pop();
        return result;
    }
    
    // 与pop()类似,只是查询第一个进入的元素,而不用删除
    int peek() {
        int result = this->pop();
        outStack.push(result);  //因为pop()把元素弹了出去,所以要加回来
        return result;
    }
    
    bool empty() {
        return inStack.empty() && outStack.empty();
    }
};

top()是获取栈的顶头元素,pop()才是把它弹出

peek()与pop()类似,所以尽量采用代码复用的方式而不是粘贴代码,提高美观度

225. 用队列实现栈

思路:用一个队列来实现顺序的颠倒

队列的基本用法

q.push(item)           //将item压入队列尾部
q.pop()                //删除队首元素,但不返回
q.front()              //返回队首元素,但不删除
q.back()               //返回队尾元素,但不删除
q.size()               //返回队列中元素的个数
q.empty()              //检查队列是否为空,如果为空返回true,否则返回false

代码

class MyStack {
public:
    queue q; 
    MyStack() {

    }
    
    void push(int x) {
        q.push(x);
    }
    
    int pop() {
        // 除最后一个元素外,把每个头部元素添加到尾部
        int size = q.size();
        while(--size){
            q.push(q.front());
            q.pop();
        }
        int result = q.front();
        q.pop();
        return result;
    }
    
    int top() {
        return q.back();

    }
    
    bool empty() {
        return q.empty();
    }
};

20. 有效的括号

栈的经典应用(匹配问题都是栈的强项)

思路

其实只有3种不匹配的情况

1-左括号有多余的情况

训练营day11(1001) | 第五章 栈与队列_第4张图片

解决:当遍历到左括号时,把对应的右括号放到栈中(为了方便对比匹配),如果遇到右括号,就把栈中的右括号弹出,当遍历结束后,栈中还有元素的话,则说明情况1成立,左括号有多余的情况

 2-括号没有多余,但括号类型没有匹配上

训练营day11(1001) | 第五章 栈与队列_第5张图片

解决:当遍历到左括号时,把对应的右括号放到栈中(这一点与情况一相同),但当遇到右括号时,要和顶元素去比较是否一样,若不一样,说明情况2成立

3-右括号有多余的情况

训练营day11(1001) | 第五章 栈与队列_第6张图片

解决:当遍历到左括号时,把对应的右括号放到栈中(这一点与情况一相同),但若还未遍历完,栈就空了,则说明情况3成立

代码

class Solution {
public:
    bool isValid(string s) {
        // 剪枝操作 如果长度为奇数,则一定失败
        if(s.size()%2) return false;

        stack sta;
        for(int i=0; i

若长度为奇数,则一定不匹配,可以做剪枝操作

1047. 删除字符串中的所有相邻重复项

栈的经典应用(匹配问题都是栈的强项)

class Solution {
public:
    string removeDuplicates(string s) {
        stack sta;
        for(int i=0; i

你可能感兴趣的:(代码随想录算法训练营,数据结构,算法,leetcode)