栈系列(洛谷刷题记录)

本文介绍了如何使用C语言解析后缀表达式,并提供了两个实例,一个是计算后缀表达式的值,另一个是处理加法和乘法的算术表达式。在解析过程中,利用数组模拟栈进行计算,注意数字可能多位,运算结果需要取模,以及栈顶指针的正确使用。同时,给出了一个计算表达式值的问题,强调了取模和溢出预防的重要性。
摘要由CSDN通过智能技术生成

语言:C语言 由于clion会自动加上return,所以有时候可能没写……

P1449 后缀表达式

题目描述:

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。

如:3*(5–2)+7对应的后缀表达式为:3.5.2.-*7.+@。’@’为表达式的结束符号。‘.’为操作数的结束符号。

题解如下: 

//
// Created by Lee on 2022/2/1.
//main16
//
//用数组模拟栈
#include <stdio.h>
long array[10000];
int p;//栈顶指针
int temp;//存临时数
char ch;
int main(){
    while((ch=getchar())!='@'){
        if(ch>='0'&&ch<='9'){
            temp = temp * 10 + ch -'0';
        }
        else if(ch=='.'){
            array[p++] = temp;
            temp = 0;//一定要注意归零,否则下一次temp会用这一次的继续往上加
        }
        else if(ch=='+'){
            int a = array[p-2];
            int b = array[p-1];
            p -= 2;
            int c = a+b;
            array[p++] = c;
        }
        else if(ch=='-'){
            int a = array[p-2];
            int b = array[p-1];
            p -= 2;
            int c = a-b;
            array[p++] = c;
        }
        else if(ch=='*'){
            int a = array[p-2];
            int b = array[p-1];
            p -= 2;
            int c = a*b;
            array[p++] = c;
        }
        else if(ch=='/'){
            int a = array[p-2];
            int b = array[p-1];
            p -= 2;
            float c = a/b;
            array[p++] = c;
        }
    }
    printf("%d",array[0]);
    return 0;
}

本题需要注意的地方:

1. 数字不一定只有一位。需要根据 '.' 来判断一个数字到底有几位。

2. 栈顶指针 p 其实是指向栈顶元素的再上面一位,即array[p-1]才是栈顶元素。取数的时候需要注意。

3. 除法的运算结果向下取整。这一点题目好像没表述清楚,但是自己要注意,因为我之前用float错了。

P1981 [NOIP2013 普及组] 表达式求值

题目描述:

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。

输入格式:

一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘法运算符“×”,且没有括号,所有参与运算的数字均为 0 到 2^{31}−1 之间的整数。

输入数据保证这一行只有 0−9、+、这 12 种字符。

输出格式:

一个整数,表示这个表达式的值。

注意:当答案长度多于 4 位时,请只输出最后 4 位,前导 0 不输出。

题解如下: 

//
// Created by Lee on 2022/2/2.
//main17
//
//思路:数字进栈,加号不处理,乘号的话,取最上面的数和下一个输入的数相乘,结果进栈。最后把栈里的元素累加。
#include <stdio.h>
//怕两个大int相乘会溢出,故使用longlong的数组
long long array[100010];
char ch[100010];//专门存放符号的数组
int p;//数字数组栈顶指针
int q;//符号数组栈顶指针
long long sum;
int main(){
    scanf("%lld",&array[p++]);//先读第一个数字,然后是符号数字交替
    while(1){
        scanf("%c",&ch[q++]);
        if(ch[q-1]=='\n') break;
        scanf("%lld",&array[p++]);
        if(ch[q-1]=='+') {
            continue;
        }
        else if(ch[q-1]=='*') {
            array[p-2] = array[p-2] * array[p-1];
            array[p-2] = array[p-2] %10000;
            p--;
        }
    }
    for(int i=0;i<p;i++){
        sum += array[i];
        sum %= 10000;
    }
    sum = sum%10000;
    printf("%d",sum);
}

本题需要注意的地方:

1. 题目只要求输出最低四位,那么我们在运算的过程中就尽可能的多做取模运算,防止溢出。我之前是只在最后加起来的过程中进行了取模的运算,没有通过。我个人的猜测是,就算乘法没有溢出,但是积很大,可能加起来的时候有溢出。所以保险起见,可以每一步都取模。

2. 本题使用数组模拟堆栈,还是要熟悉栈顶指针的位置,可以自己模拟一下进栈出栈的过程。

3. 我之所以单独处理第一个输入的数字,是因为这样可以保证后面输入是符号与数字交替,且符号在前。这样可以针对符号,对符号之后的数字进行操作。比如如果输入的是乘号,我就可以将乘号前的数字与乘号后的数字乘起来。

P1044 [NOIP2003 普及组] 栈

题目描述:

现在可以进行两种操作,

  1. 将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的 push 操作)
  2. 将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的 pop 操作)

使用这两种操作,由一个操作数序列就可以得到一系列的输出序列。

你的程序将对给定的 n,计算并输出由操作数序列 1,2,…,n 经过操作可能得到的输出序列的总数。

题解如下: 

//
// Created by Lee on 2022/1/28.
//main15
//
#include <stdio.h>
int n;
int res[20];
int main(){
    scanf("%d",&n);
    res[0] = 1;
    res[1] = 1;
    for(int i=2;i<=n;i++){
        for(int j=0;j<i;j++){
            res[i] += res[j] * res[i-1-j];
        }
    }
    printf("%d",res[n]);
    return 0;
}

本题需要注意的地方:

1. 算法:本题我是使用递归的方法求卡特兰数。

2. 卡特兰数与本题的关系:

我们假设最后一个出栈的数字是x。

那么在x之前出栈的数字可以分为两类:比x大的和比x小的。

令 f[x] 代表序列1~x通过进出栈操作可以得到的序列种类的总数。

比x小的数有x-1个,比x大的数有n-x个。把它们分开考虑,分别会有f[x-1]和f[n-x]种序列数,再根据排列组合的知识,可得f[x] = f[x-1] * f[n-x] 。

另外,由于x有n个取值,所以 res = f[0]*f[n-1] + f[1]*f[n-2] + ... + f[n-1]*f[0];

(参考了大佬inexistent的题解 登录 - 洛谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值