栈的使用以及相关练习题

栈Stack

在这里插入图片描述
此处为stack类的模版声明,该模版接受两个类型参数
第一个是class T 代表一个类型,当你实例化stack模版时,可以传一个具体类型,比如int 、double等等。
第二个class Container = deque 是另一个类型,默认值是deque 是一个双端队列容器。如果不给第二个参数传类型,就默认是deque

定义

在这里插入图片描述
此处我们可以看到栈的定义
简单的来说,栈是一种容器适配器 ,元素出栈入栈 遵循后入先出的原则。

栈的实例化

stack<int> s1;
stack<double> s2;
stack<string> s3;

相关功能

入栈 push

在这里插入图片描述

出栈 pop

在这里插入图片描述
将当前的栈顶元素删除 ,不会返回任何数

判空 empty

在这里插入图片描述
代码测试

int main()
{
	//Test1();
	stack<int> s1;
	s1.push(1);
	s1.push(2);
	s1.push(3);
	s1.push(4);
	s1.push(5);
	cout << s1.empty() << endl;
	while (!s1.empty())
	{
		//top()栈顶元素
		cout << s1.top() << " ";
		//出栈
		s1.pop();
	}
	cout << endl;
	cout << s1.empty() << endl;

	return 0;
}

结果在这里插入图片描述

栈顶元素top

在这里插入图片描述
此处top 返回栈顶元素。除了返回一般类型还返回const类型的

交换swap

在这里插入图片描述
交换前在这里插入图片描述
交换后
在这里插入图片描述

返回元素个数 size

在这里插入图片描述

总代码

#include<iostream>
using namespace std;
#include<stack>
#include<string>

//Stack 基本功能  入栈  出栈   栈顶元素  判空  返回元素个数  
void PrintStack( stack<int>& s1)
{
	cout << "Print" << endl;
	//判空
	while (!s1.empty())
	{
		//top()栈顶元素
		cout << s1.top() << " ";
		//出栈
		s1.pop();
	}
	cout << endl;
}

void Test1()
{
	//stack的实例化
	stack<int> s1;
	stack<int> s4;
	stack<double> s2;
	stack<string> s3;
    s1.push(1);
	s1.push(2);
	s1.push(3);
	s1.push(4);
	s1.push(5);
	cout << s1.size() << endl;
	s1.pop();
	s1.push(6);
	s4.push(1);
	s4.push(2);
	s4.push(3);
	//交换	
	s4.swap(s1);
	PrintStack(s1);
	PrintStack(s4);
}
int main()
{
	Test1();
	return 0;
}

练习题

最小栈

https://leetcode.cn/problems/min-stack/
在这里插入图片描述

思路解析:

题目 :实现最小栈。入栈,出栈,返回栈顶元素都好说,关键是如何在常数时间内检索到最小元素的栈?
第一想法可能是用一个变量来存最小值,遇见最小值就改变,但是,我们此次实现的栈具有pop功能。如果我们删去的元素恰好就是当前最小元素,那么答案就不对了。因此不可以采用这种方法。
我们可以使用双栈解决此问题。
入栈:一个栈正常存入,另一个栈则存入当前遇见的最小值。正常栈每次存入一个,最小栈只有遇见小于等于栈顶元素的才存入
出栈,正常栈正常出栈,最小栈,只有正常栈等于最小栈元素时才出栈。
top和getmin 就是各自正常返回栈顶元素即可。

代码实现

如下:

class MinStack {
public:
//构造由于有默认构造函数所以不需要写
    MinStack() {

    }
    
    void push(int val) {
         _st.push(val);
         if(_minst.empty()||val<=_minst.top())
         {
            _minst.push(val);
         }
    }
    
    void pop() {
        if(_minst.top()==_st.top())
        {
            _minst.pop();
        }
        _st.pop();
    }
    
    int top() {
        return _st.top();
    }
    
    int getMin() {

        return _minst.top();
    }

    //实现最小栈  原栈和最小栈
    stack<int> _st;
    stack<int> _minst;
};

栈的压入弹出序列

https://www.nowcoder.com/share/jump/6552689871711623746358
在这里插入图片描述

思路解析:

如何判断出栈序列是否合法??也许第一想法是看看其中有什么规律,符合这个规律的就是合法的序列,但是,由于入栈序列是无序的,出栈和入栈是不确定的,所以是毫无规律可言的。
那么怎么才是合法的呢?
如果我们可以模拟出这个出栈结果,就是合法的了。
下面,我们定义变量栈st,元素为整型。
定义两个下标,分别指向pushV和popV的起始地址
首先,入栈序列的每个元素入栈,入栈后判断,当前栈顶元素等于当前popi指向的popV中的元素吗?不等于就继续入栈,等于,则出栈并且popi++ 指向下一位,再进行判断,直到不等于,或者栈为空
最后结果返回,直接判断popi是否走到出栈序列最后,没有的话就是没有匹配上

代码实现:
 bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
        // write code here
        //双指针遍历两个序列
        //入栈序列 入栈后再判断是否与出栈序列相等 相等就加加 不等就继续入栈
        int pushi = 0,popi = 0;
        stack <int> Judg;
        while(pushi < pushV.size())
        {
            //先插入
            Judg.push(pushV[pushi++]);
            //判断  此处 栈不为空并且 top等于出栈队列的数时 就要执行 不要忘记
           while(!Judg.empty()&&Judg.top()==popV[popi])
           {
            //出栈 popi++
            Judg.pop();
            popi++;
           }

        }

        //最后结果的判断就是出栈队列是否可以走到头 可以的话 就true
        return popi==popV.size();



    }

逆波兰表达式求值

https://leetcode.cn/problems/evaluate-reverse-polish-notation/
在这里插入图片描述
在这里插入图片描述
逆波兰式的算法定义
在这里插入图片描述
我们一般常见的是中缀表达式,例如:
a+b+c
后缀表达式形式为 ab+c+
存在意义:可能有人会奇怪,为什么不使用方便的中缀表达式,反而要使用这样复杂的后缀表达式呢?实际上对于我们而言,简单的中缀表达式,对于计算机而言是相当复杂的。
对于计算机而言逆波兰式,是相对简单的,因为遵循着栈先进后出的原则。
逆波兰表达式的算法实现,有兴趣的可以自己实现看看
在这里插入图片描述

思路解析:

题目给我们逆波兰表达式,让我们返回最终结果
那么整体思路就是利用栈来存数值,遇到数字就入栈,遇到运算符就出两个元素,然后将运算好的数据进行入栈。

代码实现:
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
    //逆波兰表达式  存入栈中 数字照常存放 但是遇见操作符需要按照优先级进行入栈
    //优先级高的就放进去
     stack<int> st;
    for(auto& e:tokens)
    { 
        //判断是符号操作数
        if(e =="+"||e =="-"||e =="*"||e =="/")
        {
            int right = st.top();
            st.pop();
            int left = st.top();
            st.pop();

            switch (e[0])
            {
                 case '+':
                st.push(left+right);
                break;
            case '-':
                st.push(left-right);
                break;
            case '*':
                st.push(left*right);
                break;
            case '/':
                st.push(left/right);
                break;

            }
           

        }
        else
        {
            //以整型的形式将数字存放进去
            st.push(stoi(e));
        }


    }
    return st.top(); 

    }
};
  • 43
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值