栈及其简单应用

栈是什么

栈就是一个先进先出的线性表,若能够更加方便地去理解栈,我们可以跟剧具体的图来进行理解.

相信这个图十分的生动形象,可以看出栈就像是一个桶,若每一个元素进栈的时候,便会存储在最底下,后来的会在上面;而如果需要取出元素,那么必须从最上面开始取,先放的便只能后来取,后放的便只能先取,因此栈的特点便是:先进后出,后进先出.


如何模拟并存储栈的操作

为了方便,我们需要用数组去模拟栈的序列.即:

我们定义数组和变量来表示栈,即:

Stack表示栈的序列,top代表栈的元素个数,那么自然:

Stack[1]表示栈的底部,stack[top]表示栈顶.那么,如图(c),a,b,c,d,e分别表示Stack[1,2,3,4,5].


添加与删除栈内的元素

添加元素

我们只需要用在顶端放上元素即可,设需要存储的元素为k,即:

top++;
Stack[++top]=k;

删除元素

去掉栈顶元素,其实只需要将元素个数减去1就可以,并不需要要去掉的元素重新赋值为0,因为若要重新插入元素,那么必然新的值会覆盖原来的值.因此只要一句简单的话就可以完成栈的操作:

top--;

栈的实际操作与运用

学习好栈并不只是学会简单的模拟和运用,还要更多地知道一道题为什么需要栈,需要栈来维护什么,这也是需要栈的原因.接下来会有一些实际的例题,可以更好地去理解栈的操作


火车进站

有一个车站,每天都会有N辆车进站,进站按从1到N的顺序进站。现在车站的站长想让这些火车按照特定的顺序出站,问可以做到吗?

当N为5时,出站顺序若为1 2 3 4 5,可以做到,但是顺序若为5 4 1 2 3,则不行。

输入格式

一个N,在1000之内,下接一些出站序列,当读到一个0时,则这个测试数据结束。

输出格式

对每个序列输出一行“Yes”或“No”。

input

5

1 2 3 4 5

5 4 1 2 3

0

output

Yes

No

数据规模与约定

时间限制:1s

空间限制:256MB

这道题目其实难度并非很大,最主要的是模拟,需要用数据结构栈来模拟:

给定一个数列,和栈进行以此配对,即:用1,2,3,4,5进栈,若栈顶元素等于a[first],first表示未被匹配过的初始序列的开头,若匹配成功,则出栈,而匹配的序列也转移到下一个.最后便只要去判断栈是否为空即可.为空没说明匹配完,否则则说明没有匹配完,即该序列不成立.代码很好实现.

代码如下:

#include<bits/stdc++.h>
using namespace std;
int a[1000000]={},st[10000000]={};
int main()
{
    int n,cnt_st,cnt_a;
    cin>>n;
    for (;;)
    {
        cnt_st=0;cnt_a=1;
        for (int i=1;i<=n;i++)
        {
            cin>>a[i];
            if (a[i]==0&&i==1) return 0;
        }
        for (int i=1;i<=n;i++)
        {
            st[++cnt_st]=i;
            if (st[cnt_st]==a[cnt_a])
            while (st[cnt_st]==a[cnt_a]&&cnt_st>0)
            {
                cnt_st--;
                cnt_a++;
            }
        }
        if (cnt_st==0)cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
    }
    return 0;
}

计算表达式的值

题目描述

小明在你的帮助下,破译了Ferrari设的密码门,正要往前走,突然又出现了一个密码门。

门上有一个算式,其中只有“(”、“)”、“0-9”、“+”、“-”、“”、“/”、“^”,求出的值就是密码。小明的数学学得不好,还需你帮他的忙。(“/”用整数除法)

输入格式

只有一行是一个算式(算式长度<=30)。

输出格式

对于每组数据,输出算式的值(所有数据在2^31-1内)。

样例数据input

1+(3+2)(7^2+6*9)/(2)

output

258

数据规模与约定

时间限制:1s

1s

空间限制:256MB

256MB

方法1:

这是一道大模拟,需要用栈进行维护.一个栈储存数字,一个栈储存符号.

这道题目有一个难点,那就是优先级的处理,这个时候我们就需要用栈维护,即:

如果当前符号的优先级大于或等于栈顶,那么直接进栈,否则将栈顶进行计算,以此来处理复杂的优先级的问题,以1+2×4-3为例.我们设数字和字符的栈分别是stc1和stc2,栈顶是top1和top2

1.数字1进栈 stc1={1}

2.符号+进栈 stc1={1} stc2={+}

3.数字2进栈 stc1={1,2} stc2={+}

4.符号×进栈,stc1={1,2} stc2={+,×}

5.数字4进栈,stc1={1.2.4} stc2={+,×}

6.现在我们判断到了-,比符号栈顶×的优先级要小,要进行计算,因此将2,4与符号×进行计算,那么栈的序列为,然后重新入栈:stc1={1,8,3} stc2={+,-}

因此最后答案是:(1+8)-3=6

然后最后留下+和-,顺序地做一遍即可.

处理括号:

1.左括号:直接进栈.

2.右括号:强制计算,知道向左计算的时候枚举到了第一个左括号为止

倒序处理加法或减法的BUG:

例如在做1-2+1,栈是这样的:

stc1={1,2,1} stc2={-,+}

那么下一步,便是:stc1={1,3} stc2={-}

那么最后的答案是:1-3=-2而显然这个算式的答案是0因此我们需要在最后一步进行顺序的处理

但是有一个问题就是:最有会留下乘除号怎么办:补0

即,如果原式是2+5(4+69)^2 那么,我们就可以修改成:2+5(4+69+0)^2+0

代码如下:

#include<bits/stdc++.h>
using namespace std;
int stc1[1000],top1=0;
char stc2[1000];int top2=0;
inline int Math(int x)
{
    if (x==‘+‘||x==‘-‘) return 1;
    if (x==‘*‘||x==‘/‘) return 2;
    if (x==‘^‘) return 3;
    return 0;
}//千万不要忘记加上“int"
int main()
{
    string s,s2;
    cin>>s2;
    for (int i=0;i<s2.length();i++)
        if (s2[i]==‘)‘) s=s+"+0"+s2[i];
        else s+=s2[i];
    s+="+0";//补0
    for (int i=0;i<s.length();i++)
    {
        if (s[i]>=‘0‘&&s[i]<=‘9‘)
        {
            if (i==0) stc1[++top1]=s[i]-‘0‘;
            else if (s[i-1]<‘0‘||s[i-1]>‘9‘)stc1[++top1]=s[i]-‘0‘;
            else if (s[i-1]>=‘0‘&&s[i-1]<=‘9‘)stc1[top1]=stc1[top1]*10+s[i]-‘0‘;
            continue;
        }//处理数字
        if (Math(s[i])>0)
        {
            int math1=Math(s[i]);
            int math2=Math(stc2[top2]);
            if (top2==0)
            {
                stc2[++top2]=s[i];
                continue;
            }//如果没有存放字母
            if (math2>0&&math1<math2)
            {
                char ch=stc2[top2];
                if (ch==‘+‘) stc1[top1-1]+=stc1[top1];
                if (ch==‘-‘) stc1[top1-1]-=stc1[top1];
                if (ch==‘*‘) stc1[top1-1]*=stc1[top1];
                if (ch==‘/‘) stc1[top1-1]/=stc1[top1];
                if (ch==‘^‘) stc1[top1-1]=pow(stc1[top1-1],stc1[top1]);
                top1--;stc2[top2]=s[i];
            }//如果优先级比原来大
            if (math2>0&&math1>+math2)
                stc2[++top2]=s[i];//如果优先级比原来小
            if (stc2[top2]==‘(‘)
                stc2[++top2]=s[i];//如果上一个字符是左括号
        }
        if (s[i]==‘(‘||s[i]==‘)‘)
        {
            if (s[i]==‘)‘&&stc2[top2]==‘(‘)
            {
                top2--;
                continue;
            }//如果左右括号内只有数子
            if (s[i]==‘(‘)
                stc2[++top2]=s[i];//如果是左括号
            if (s[i]==‘)‘)
            {
                while (stc2[top2]!=‘(‘)
                {
                    char ch=stc2[top2];
                    if (ch==‘+‘) stc1[top1-1]+=stc1[top1];
                    if (ch==‘-‘) stc1[top1-1]-=stc1[top1];
                    if (ch==‘*‘) stc1[top1-1]*=stc1[top1];
                    if (ch==‘/‘) stc1[top1-1]/=stc1[top1];
                    if (ch==‘^‘) stc1[top1-1]=pow(stc1[top1-1],stc1[top1]);
                    top1--;top2--;
                }
                top2--;
            }//如果是右括号就进行强制处理
        }
    }
    for (int i=1;i<=top2;i++)
    {
        int ch=stc2[i];
        if (ch==‘+‘) stc1[i+1]=stc1[i]+stc1[i+1];
        if (ch==‘-‘) stc1[i+1]=stc1[i]-stc1[i+1];
    }//正序处理结果
    cout<<stc1[top1];
    return 0;
}


栈及其简单应用

原文地址:https://www.cnblogs.com/pigzhouyb/p/10119836.html

时间: 2024-07-30 23:44:14

栈及其简单应用的相关文章

C#栈的简单介绍

概 栈(Stack)代表了一个只有一个出口的后进先出的对象集合.在列表中添加一项,称为推入元素,从列表中移除一项时,称为弹出元素. Stack<T> 类 public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable 属性 Count 获取 Stack 中包含的元素个数 方法 Pop  移除并返回在 Stack 的顶部的对象 push 向 Stack 的顶部添加一个对象 peek 返回在 Stack 的顶

顺序栈的简单操作

今天简单的实现了一下顺序栈,栈的核心函数是push(),top(),pop().首先是我自己编写的栈,后面是STL标准库调用栈函数. sqstack.h //栈的简单实现lifo #ifndef SQSTACK_H_ #define SQSTACK_H_ const int DEFAULT_SIZE=10; #include <iostream> using std::cout; using std::endl; template <typename T> class Sqstac

C++中 栈的简单封装

/*******************  *      Stack    *  * *****************/ #include <iostream> using namespace std; /***************************定义***************************************/ class Stack {     public: Stack(int capacity = 5); virtual ~Stack(); bool p

链表栈的简单实现

今天实现了链表栈的简单实现,贴出来以后可以看一看.链表栈就是用链表来实现栈的一些操作. LinkStack.h #ifndef LINKSTACK_H_ #define LINKSTACK_H_ #include <iostream> using std::cout; using std::endl; using std::ostream; template <typename T> struct Node { T data; Node<T> *next; Node()

数据结构之栈的简单应用(判断字符串中括号的合法性)

数据结构之栈(判断字符串中括号的合法性) 栈的定义 栈是一种线性数据结构,栈的特征是数据的插入和删除只能通过一端来实现,这一端称为"栈顶",相应的另一端称为"栈底":另外其还有先进后出,后进先出的特征. 栈是一种高效的数据结构,因为数据只能在栈的顶端添加或者删除,所以这样的操作很快而且容易实现. 说到线性结构,得先了解一下数据的逻辑结构,数据的逻辑结构分为线性结构.集合结构.树形结构和图形结构,如下图所示,栈是一种特殊的线性表,是线性结构的一种. JavaScrip

栈的简单应用1-平衡符号

因为在编程中,使用{}()[]等都是成对出现的,因此可以使用栈来进行一些匹配判断. 原理: 读取一段字符串,如果遇到{([这些开放字符,就将其压入栈中,如果读到})]这些封闭字符,就与当前栈顶的符号进行比较,如果栈顶的符号正好是其对应的开放符号,将栈顶元素弹出,继续读取.否则,出现警告.但是如果弹出栈顶后新的栈顶是与其匹配的开放符号,那么就是它出错了.如果全部字符串读取完毕但是栈不是空的的话,那么栈剩下的字符串都缺少匹配. 简单代码,因为使用的输入流问题对程序实现有较大误差,但思路没有问题,需要

栈的简单实现(2)-单链表实现

引言 栈(stack)是一种被广泛使用的线性数据结构,它只允许在表的一端进行插入或删除操作,因而栈也可以被称作为操作受限的线性表 .在栈中,允许插入或删除的一端称作栈顶(top)不允许插入和删除的另一端称作栈底(bottom); 示意图如下: 此文借助单链表简单地实现栈及其基本操作. 代码如下: typedef struct stack{ int data; struct stack* next; }ListStack; 注:这里假设栈中储存的是整型 (int) 的数据 基本操作 1.栈的初始化

栈的简单实现(1)-数组实现

引言 栈(stack)是一种被广泛使用的线性数据结构,它只允许在表的一端进行插入或删除操作,因而栈也可以被称作为操作受限的线性表 .在栈中,允许插入或删除的一端称作栈顶(top)不允许插入和删除的另一端称作栈底(bottom); 示意图如下: 此文借助数组简单地实现栈及其基本操作. 代码如下: #define MaxSize 100 typedef struct{ int data[MaxSize]; int top; }SeqStack; 注:这里假设栈中储存的是整型 (int) 的数据 基本

栈的简单应用-迷宫问题

                                             迷宫问题 迷宫问题一直是计算机工作者感兴趣的问题,因为它可以展现栈的巧妙应用, 这里将利用栈开发一个走迷宫程序,虽然在发现正确路径前,程序要尝试许多 错误路径,但是,一旦发现,就能够重新走出迷宫,而不会再去尝试任何错误路径. 迷宫问题求解 计算机中可以用如图所示的方块图表示迷宫.图中空白方块为通道,蓝色方块为墙 迷宫的储存可以使用二维数组,其中"0"代表墙值,"1"代表通路.由