栈的应用

前言

   之前的一篇博客更新了用C++语言实现栈,原文在这哟😘
https://chenyunxin.cn/posts/3345531452.html
https://blog.csdn.net/qq_44036990/article/details/104922762

   今天更新一篇栈的应用(PS:使用的是C++库里面的栈),所以要加入头文件#include <stack>

进制转换

描述

   在计算机中存储的数据都是二进制,所以往往需要把十进制数据转换成二进制,转换的过程实际就是除2取余数,这其中我们可以看到最先求得余数实际是个位数,书写一个数据的时候都是先书写高位的数据,而后依次到个位。这正好利用栈先进后出的原理。

基本思想

   将待转换数取余得到的数push进栈,并且待转换数/= 进制数,直到待转换数 = 0,最后将栈依次输出并且pop出栈。

代码实现

//进制转化
void BinaryConversion(int num, int transform) {
    char Letter[26];
    for (int i = 0; i < 26; i++)
        Letter[i] = 'A' + i;
    stack<int> Binary;

    //计算转化结构
    while (num) {
        Binary.push(num % transform);
        num /= transform;
    }

    //输出结果
    int len = Binary.size();
    for (int i = 0; i < len && !Binary.empty(); i++) {
        int p = Binary.top();
        if (p < 10)
            cout << p;
        else
            cout << Letter[p - 10];
        Binary.pop();
    }
}

运行结果

括号匹配

括号匹配的四种情况

  1. 左右括号匹配正确
  2. 左右括号匹配错误
  3. 左括号多于右括号
  4. 右括号多于左括号

   但是云开在这里偷了个懒,只实了一种括号的匹配,所以没有第二种情况:2. 左右括号匹配错误😜

基本思想

  1. 扫描带匹配的字符串,当遇到三种类型的左括号('{'、'('、'[')时候让该括号进栈;
  2. 当扫描到某一种类型的右括号时,出栈;
  3. 若字符串当前为的右括号而栈已经空,则右括号多于左括号;
  4. 字符串循环扫描结束时,若堆栈非空,则说明左括号多于右括号;
  5. 否则,括号配对正确。

代码实现

//括号匹配
bool ParenthesisMatching(char c, string str) {
    char c0;
    if (c == '(')
        c0 = ')';
    else if (c == '{')
        c0 = '}';
    else
        c0 = ']';

    stack<char> Matching;

    int len = str.length();
    for (int i = 0; i < len; i++) {
        if (str[i] == c)
            Matching.push(c);
        if (str[i] == c0) {
            if (Matching.empty())
                return false;
            else
                Matching.pop();
        }
    }
    return Matching.empty();
}

运行结果

简单表达式求值

基本思想

  1. 扫描字符串,如果字符为数字,进数字栈

  2. 当扫描到某一种类型的右括号时,出栈;

  3. 若字符串当前为的右括号而栈已经空,则右括号多于左括号;

  4. 为操作符,操作符栈为空时,操作符进栈;

  5. 为操作符,操作符栈非空时,栈顶操作符优先级小,操作符进栈;

  6. 为操作符,操作符栈非空时,栈顶操作符优先级大:

    ​ 连续两次取数字栈(num1 ,num2)的数据出栈;

    ​ 将num2和num1按操作符栈顶的运算法则运算;

    ​ 得到的结果进数字栈,扫描的操作符进操作符栈;

  7. 扫描完后,若操作符栈非空,则重复一遍步骤四的计算方法。

辅助函数

优先级判断

//优先级判断
int priori(char c) {
    if (c == '*' || c == '/')
        return 2;
    if (c == '+' || c == '-')
        return 1;
    return 0;
}

判断是数字还是操作符

/*
 * 判断是数字还是操作符
 * 数字返回:true
 * 操作符返回:false
*/
bool is_num(char c) {
    return !(c == '+' || c == '-' || c == '*' || c == '/');
}

运算

/*
 * c:操作符
 * num1,num2:操作数
 * 返回的是num2 c num1 的值
*/
double calculation(char c, double num2, double num1) {
    if (c == '*')
        return num2 * num1;
    if (c == '/')
        return num2 / num1;
    if (c == '+')
        return num2 + num1;
    if (c == '-')
        return num2 - num1;
    return 0;
}

主函数

//简单表达式求值
void ExpressionEvaluation(string str) {
    stack<char> operate;
    stack<double> num;
    int len = str.length();

    int n = 0;
    for (int i = 0; i < len; i++) {
        //为数字时
        if (is_num(str[i])) {
            n = 10 * n + str[i] - '0';
            if (!is_num(str[i + 1]) || str[i + 1] == '\0') {
                num.push(n);
                n = 0;
            }
        }
        //为操作符时
        else {
            //操作符栈非空
            if (!operate.empty()) {
                char temp = operate.top();
                //栈顶操作符优先级大
                if (priori(temp) >= priori(str[i])) {
                    //取数据
                    double n1 = num.top();
                    num.pop();
                    double n2 = num.top();
                    num.pop();
                    //运算并进数字栈
                    num.push(calculation(temp, n2, n1));

                    operate.pop();
                    operate.push(str[i]);
                } else
                    operate.push(str[i]);
            } else
                operate.push(str[i]);
        }
    }
    while(!operate.empty()){
        char t=operate.top();operate.pop();
        double t1=num.top();num.pop();
        double t2=num.top();num.pop();
        num.push(calculation(t,t2,t1));
    }
    cout<<num.top()<<endl;
}

运行结果

小结

博客完整的源码已经上push到了github和gitee了哟😜

Github源码

Gitee源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值