栈和队列总结

一 基础知识

1.

均为线性表,可以由数组或链表实现

栈:先进后出,操作均在栈顶进行

队列:先进先出,队尾进,队首出

2.  STL stack & queue

stack 常见操作:

s.push(x):入栈 (void类型)

s.pop(): 出栈 (void类型,只删除,不返回元素)

s.top(): 返回栈顶元素

s.size():返回栈元素个数

s.empty() :判断栈是否为空

queue 常见操作:

q.push(x): 入队

q.pop(): 出队 (void类型,只删除,不返回队首元素)

q.front(): 访问返回对首元素

q.back(): 访问返回队尾元素

q.size():返回队列元素个数

q.empty(): 判断队列是否为空

3.概念理解相关题型

3.1 Implement Stack using Queues (leetcode 225 https://leetcode.com/problems/implement-stack-using-queues/)

思路:使用两个队列实现,其中一个队列为空,用来进行颠倒顺序和输出队尾元素。

入栈操作: 向非空队列内入队即可

出栈操作:将非空队列除队尾元素外的所有元素导入另一个空队列,剩余队尾元素即为待应该待出栈元素

top()操作: 同出栈,注意只需访问返回,不需要让其出队,即仍需将其导入另一队列

注意:两队列地位平等,均可能用作储存和转移工作

class Stack {
private:
    queue<int> q1,q2;
public:
    // Push element x onto stack.
    void push(int x) {
        if(!q1.empty()){
            q1.push(x);
        }
        else{
            q2.push(x);
        }
    }

    // Removes the element on top of the stack.
    void pop() {
        if(!q1.empty()){
            while(q1.size() > 1){
                q2.push(q1.front());
                q1.pop();
            }
            q1.pop();
        }else{
            while(q2.size() > 1){
                q1.push(q2.front());
                q2.pop();
            }
            q2.pop();
        }
    }

    // Get the top element.
    int top() {
        if(!q1.empty()){
            while(q1.size() > 1){
                q2.push(q1.front());
                q1.pop();
            }
            int ans = q1.front();
            q2.push(q1.front());
            q1.pop();
            return ans;
        }else{
            while(q2.size() > 1){
                q1.push(q2.front());
                q2.pop();
            }
            int ans = q2.front();
            q1.push(q2.front());
            q2.pop();
            return ans;
        }
    }

    // Return whether the stack is empty.
    bool empty() {
        if(q1.empty() && q2.empty()){
            return true;
        }
        return false;
    }
};

3.2 Implement Queue using Stacks (leetcode 232 https://leetcode.com/problems/implement-queue-using-stacks/)

思路:

两个堆栈,s1负责入队,s2负责反向并出队

每次入队直接进入s1,出队操作先将s1所有元素压入s2,则栈顶元素即为待出队元素,出队后压回s1,恢复原状。

class Queue {
private:
    stack<int> s1,s2;
public:
    // Push element x to the back of queue.
    void push(int x) {
        s1.push(x);
    }

    // Removes the element from in front of queue.
    void pop(void) {
        while(!s1.empty()){
            s2.push(s1.top());  // 注意STL栈中,top只返回不出栈,pop只出栈不返回
            s1.pop();
        }
        s2.pop();
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
    }

    // Get the front element.
    int peek(void) {
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        int ans = s2.top();
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
        return ans;
    }

    // Return whether the queue is empty.
    bool empty(void) {
        if(s1.empty() && s2.empty()){
            return true;
        }
        return false;
    }
};

3.3 Min Stack (leetcode 155 https://leetcode.com/problems/min-stack/)

要求:实现可以返回最小元素的栈

思路:使用两个栈,一个栈s1正常出入,另一个储s2存最小值信息,当当前元素比s2栈顶元素小,入当前元素,否则再入一份栈顶元素

注意:由于s1,s2元素一样多,出栈时也应一起出栈。

class MinStack {
private:
    stack<int> s1,s2;
public:
    void push(int x) {
        s1.push(x);
        if(!s2.empty() && x > s2.top()){
            s2.push(s2.top());
        }else{
            s2.push(x);
        }
    }

    void pop() {
        s1.pop();
        s2.pop();
    }

    int top() {
        return s1.top();
    }

    int getMin() {
        return s2.top();
    }
};

二. 栈与队列应用 (结合数据结构教材中的应用)

1. 典型应用场合

典型应用栈的场合有: 逆序输出 (进制转换),递归嵌套(栈混洗,括号匹配),延迟缓冲(表达式计算),栈式计算(逆波兰表达式)

举例如下:

1.1 十进制数向n进制转换的栈实现

思路:除以n取余数,以此存放在栈中,输出时由栈的特点反向输出得解

void convert(stack <char>& S, int n,int base) {
    static char digit[] =
    {‘0‘,‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘,‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘};
    while(n > 0){
        int remainder = (int)(n % base);
        S.push(digit[remainder]);
        n /= base;
    }
}

1.2 栈混洗(元素出入栈合法顺序判断)

思路:使用栈模拟,对于s,如果当前要出栈元素正好在栈顶,则必须出栈;否则入栈,出现矛盾则说明不合法

bool isPossible(vector<int>& in, vector<int>& out){
    stack<int> s;
    for(int i = 0,j = 0;j<out.size();j++){
        while(s.empty() || s.top!= out[j]){
            if(i > in.size()){
                return false;
            }
            s.push(in[++]);
        }
        s.pop();
    }
    return true;
}

补充: n个元素的合法出入栈个数为卡特兰数  (2n!)/ n! /(n+1)!

1.3 括号匹配 (leetcode 20 https://leetcode.com/problems/valid-parentheses/)

思路:遍历序列,遇到所有类型左括号,入栈;遇到右括号,判定栈顶元素与之是否匹配,匹配则出栈,不匹配则说明整体不匹配

class Solution {
public:
    bool isValid(string s) {
        stack<char> S;
        for(int i = 0; i < s.length(); i++){
            if(s[i] == ‘(‘ || s[i] == ‘[‘ || s[i] == ‘{‘){
                S.push(s[i]);
                continue;
            }
            if(s[i] == ‘)‘){
                if(S.empty() || S.top() != ‘(‘){
                    return false;
                }
                S.pop();
                continue;
            }
            if(s[i] == ‘]‘){
                if(S.empty() || S.top() != ‘[‘){
                    return false;
                }
                S.pop();
                continue;
            }
            if(s[i] == ‘}‘){
                if(S.empty() || S.top() != ‘{‘){
                    return false;
                }
                S.pop();
                continue;
            }
        }
        return S.empty();
    }

};

1.4 逆波兰表达式求解 (leetcode 150 https://leetcode.com/problems/evaluate-reverse-polish-notation/)

思路:根据逆波兰表达式定义,建立栈

遍历字符串,遇到数字,入栈,遇到运算符,取出栈顶两元素执行相应计算后将结果入栈

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> s;
        for(int i = 0;i < tokens.size();i++){
            if(tokens[i] == "+" || tokens[i] == "-" || tokens[i]== "*" || tokens[i] == "/"){
                int num1 = s.top();
                s.pop();
                int num2 = s.top();
                s.pop();
                if(tokens[i] == "+"){
                    int num = num1 + num2;
                    s.push(num);
                }
                if(tokens[i] == "-"){
                    int num = num2 - num1;
                    s.push(num);
                }
                if(tokens[i] == "*"){
                    int num = num2 * num1;
                    s.push(num);
                }
                if(tokens[i] == "/"){
                    int num = num2 / num1;
                    s.push(num);
                }
            }
            else{
                s.push(atoi(tokens[i].c_str()));
            }
        }
        int ans = s.top();
        return ans;
    }
};
时间: 2024-10-05 08:03:31

栈和队列总结的相关文章

快速记忆数组栈和队列函数push()和shift()

在js中,对数组的操作是比较常见的,有时候,我们需要模拟栈和队列的特性才能实现需求,今天来给大家用通俗易懂.简洁明了的几行文字,来告诉大家栈和队列的几个函数,如何快速记住. 首先,概念还是要知道的: 栈(stack)又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素:从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻

3-3-行编辑程序-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第3章  栈和队列 - 行编辑程序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? SequenceStack.c        相关测试数据下载  链接? 无数据

用栈实现队列的效果

用两个栈实现队列的效果,可以入栈,出栈,判空等... 实现的栈基本功能 lstack.h #ifndef _LSTACK_H #define _LSTACK_H #include <stdexcept> using namespace std; // 基于链式表的堆栈 class Stack { public: // 构造过程中初始化为空堆栈 Stack (void) : m_top (NULL) {} // 析构过程中销毁剩余的节点 ~Stack (void) { for (Node* ne

javascript中的栈、队列。

                       javascript中的栈.队列 栈方法     栈是一种LIFO(后进先出)的数据结构,在js中实现只需用到2个函数 push()  接受参数并将其放置数组尾,并返回修改后的数组长度. pop()  移除数组尾的最后一项,并返回移除项的值. 事例: var colors = new Array();var count = colors.push("red","green"); count = colors.push(&

数据结构之栈和队列

数据结构学习继续向前推进,之前对线性表进行了学习,现在我们进入栈和队列的学习.同样我们先学习一些基本概念以及堆栈的ADT. 栈和队列是两种中重要的线性结构.从数据结构角度看,栈和队列也是线性表,只不过是受限的线性表.因此可以称为限定性数据结构.但从数据类型来看,他们是和线性表大不相同的两类重要的抽象数据类型. 栈:(stack)是限定仅在表尾进行相应插入和删除操作的线性表.因此,对栈来说,表尾有其特殊含义,称为栈顶,表头称为栈底,不含元素的空表称为空栈.栈一个重要特性就是后进先出.OK,我们来看

图解堆算法、链表、栈与队列(Mark)

原文地址: 图解堆算法.链表.栈与队列(多图预警) 堆(heap),是一类特殊的数据结构的统称.它通常被看作一棵树的数组对象.在队列中,调度程序反复提取队列中的第一个作业并运行,因为实际情况中某些时间较短的任务却可能需要等待很长时间才能开始执行,或者某些不短小.但很重要的作业,同样应当拥有优先权.而堆就是为了解决此类问题而设计的数据结构.--

第三章:1.栈和队列 -- 栈的表示及实现

前言: 栈和队列 是两种重要的线性结构.从数据结构角度来看,栈和队列也是线性表,它的特殊性在于其操作是线性表的子集,是操作受限的线性表,因此可以称作限定性的数据结构. (限定性:如.人为的规定线性表只能从表尾插入和删除结点数据元素,那么这样的线性表就是栈) 目录: 1.栈 2.栈的应用举例 3.栈与递归的实现 4.队列 5.离散事件模型 正文: 栈的定义 栈(stack) 如上所说,就是限定只能在表尾进行插入和删除的线性表.表尾 称为 栈顶(top), 表头 称为 栈底 (bottom),没有数

数据结构和算法分析(9)表栈和队列的实际应用(一)

    在接下来的几篇博文中,将介绍表.栈.队列在编程实践中的应用.     (1)表达式求值:     输入一个中缀表达式,操作符包括(+ - * / ^).转化为后缀表达式之后并计算表达式的值: 要求: 1.输入的中缀表达式必须是一个完整的字符串: 2.不限制数字的位数和正负,负数用()括起来: 代码如下: 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 #define EmptyT

用两个栈实现队列-剑指Offer

用两个栈实现队列 题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路 一个栈的顺序是“后进先出”,再用一个栈把顺序颠倒过来就满足队列的“先进先出”规则了 用两个stack实现,stack1负责进队列,然后从stack2弹栈出队列,若stack2为空,再从stack1弹出到stack2 代码 import java.util.Stack; public class Solution { Stack<Integer> stack1 = new St

(hdu step 8.1.1)ACboy needs your help again!(STL中栈和队列的基本使用)

题目: ACboy needs your help again! Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 73 Accepted Submission(s): 57   Problem Description ACboy was kidnapped!! he miss his mother very much and is very