代码随想录算法训练营第八天|232.用栈实现队列、225. 用队列实现栈

理论基础 

了解一下 栈与队列的内部实现机智,文中是以C++为例讲解的。 

文章讲解:代码随想录

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

三个最为普遍的STL版本:

  1. HP STL:其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,而且开放源代码。

  2. P.J.Plauger STL:由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。

  3. SGI STL: 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。

接下来介绍SGI STL的栈和队列——

栈和队列提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以它们不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。

栈和队列是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。

所以STL中栈和队列往往不被归类为容器,而被归类为container adapter(容器适配器)。

栈和队列的底层实现可以是vector,deque,list, 主要就是数组和链表的底层实现。我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque(deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了)为缺省情况下栈和队列的底层结构。

但可以指定——

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

232.用栈实现队列 

大家可以先看视频,了解一下模拟的过程,然后写代码会轻松很多。

题目链接/文章讲解/视频讲解:代码随想录

这里文章使用的是stIn按栈的顺序存储,stOut按队列的顺序存储,这样不需要老是倒腾,注意这两个栈存储的元素总和才是全部元素。

来了一个元素,就让它存储在stIn里面;如果要pop元素,那就先紧着stOut来pop,如果为空,那就把stIn里面的元素倒腾到stOut里面再pop;要取队列头部元素,就先使用之前写的pop得到元素,然后再push回去,注意必须要调用stOut的push,因为你从哪里拿的就要放到什么位置,stOut的栈顶存储的永远是整个队列的第一个元素,空了才考虑stIn的栈底元素;判断为空否因而要判断两个栈都是否为空。

class MyQueue {
public:
    stack stIn;
    stack stOut;
    MyQueue() {
        
    }
    
    void push(int x) {
        stIn.push(x);
    }
    
    int pop() {
        if(stOut.empty()){
            while(!stIn.empty()){
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int tmp=stOut.top();
        stOut.pop();
        return tmp;
    }
    
    int peek() {
        int tmp=this->pop();
        stOut.push(tmp);
        return tmp;
    }
    
    bool empty() {
        return stIn.empty()&&stOut.empty();
    }
};

225. 用队列实现栈 

可以大家惯性思维,以为还要两个队列来模拟栈,其实只用一个队列就可以模拟栈了。 建议大家掌握一个队列的方法,更简单一些,可以先看视频讲解。

题目链接/文章讲解/视频讲解:代码随想录

个人感觉使用一个队列更简单更容易懂,使用两个队列就是以一个队列为主,另一个为辅,只有pop的时候才用得到,主要就是把主队列pop剩一个元素,同时push到辅队列里面,得到top后pop掉,然后直接让主队列等于辅队列,再把辅队列清空即可。

使用两个队列——

class MyStack {
public:
    queue que1;
    queue que2;
    MyStack() {

    }
    
    void push(int x) {
        que1.push(x);
    }
    
    int pop() {
        int size=que1.size();
        while(--size>0){
            que2.push(que1.front());
            que1.pop();
        }
        int tmp=que1.front();
        que1.pop();
        que1=que2;
        while(!que2.empty()){
            que2.pop();
        }
        return tmp;
    }
    
    int top() {
        int tmp=que1.back();
        return tmp;
    }
    
    bool empty() {
        return que1.empty();
    }
};

使用一个队列——

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

    }
    
    void push(int x) {
        que.push(x);
    }
    
    int pop() {
        int size=que.size();
        while(--size>0){
            int tmp=que.front();
            que.pop();
            que.push(tmp);
        }
        int tmp=que.front();
        que.pop();
        return tmp;
    }
    
    int top() {
        int tmp=que.back();
        return tmp;
    }
    
    bool empty() {
        return que.empty();
    }
};

总结

一些常用的库函数——

stack:

stack st;
st.push(1);
st.push(2);
// st: 1 2
st.top(); // 2
st.size(); // 2
st.pop(); // st: 1
st.empty(); // false

queue:

queue que;
que.push(1);
que.push(2);
// que: 1 2
que.front(); // =1
que.back(); // =2
que.size(); // 2
que.pop(); // que: 2
que.empty(); // false

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