栈的应用——四则表达式求值

栈的应用有很多,四则运算是一个比较常见的应用。对于四则运算,括号内的要先运算,而且还要先乘除后加减,又要涉及到负数和浮点数,看上去简简单单的式子,其实暗藏杀机。

常用的方法是利用后缀表达式(逆波兰)进行计算。主要分为两步:

(1)将中缀表达式转化为后缀表达式(栈用来进出运算的符号):

从左到右遍历中缀表达式的每一个数字和符号,若是数字就输出,既成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减),则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

(2)将后缀表达式进行运算得出结果(栈用来进出运算的数字)

从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

使用C语言实现的算法:

/*==============================================================
 *     FileName: expression_calc.c
 *         Desc: 使用栈完成四则表达式的计算,支持大中小括号以及负数,不支持浮点数
 *       Author: Hu Chunxu
 *        Email: [email protected]
 *      Version: 0.0.1
 *   LastChange: 2014-07-15 10:07:48
 *      History:
 *=============================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OK      1
#define ERROR   0
#define TRUE    1
#define FALSE   0
#define MAXSIZE 50

typedef int Status;
typedef int SElemType;

//定义一个顺序存储栈
typedef struct
{
    SElemType data[MAXSIZE];
    int top;
}SqStack;

/*******************栈的基本操作********************************/
Status init_stack(SqStack *s)
{
    s->top = -1;
    return OK;
}

Status clear_stack(SqStack *s)
{
    s->top = -1;
    return OK;
}

Status stack_empty(SqStack s)
{
    if(s.top == -1)
        return TRUE;
    else
        return FALSE;
}

int stack_length(SqStack *s)
{
    return s->top+1;
}

Status push(SqStack *s, SElemType e)
{
    if(s->top == MAXSIZE-1)
        return ERROR;
    s->top++;
    s->data[s->top] = e;
    return OK;
}

Status pop(SqStack *s, SElemType *e)
{
    if(s->top == -1)
        return ERROR;
    *e = s->data[s->top];
    s->top--;
    return OK;
}

/*******************中序表达式转换为后续表达式********************************/
Status infix_to_postfix(char *infix, char *postfix)
{
    SqStack s;
    int e = 0;
    int i = 0, j = 0;
    int flag = 0;

    if(init_stack(&s) != OK)
        return ERROR;

    while(infix[i]!=‘\0‘)
    {
        while(infix[i]>=‘0‘ && infix[i]<=‘9‘)    //如果是数字则输出
        {
            if(flag)
            {
                flag = 0;
                postfix[j++] = ‘-‘;
            }
            postfix[j++] = infix[i];
            i++;
            if(infix[i]<‘0‘ || infix[i]>‘9‘)
                postfix[j++] = ‘ ‘;
        }
        if(infix[i]==‘)‘ || infix[i]==‘]‘ || infix[i]==‘}‘)       //如果符号,则进行栈操作
        {
            pop(&s, &e);
            while(e!=‘(‘ && e!=‘[‘ && e!=‘{‘)
            {
                postfix[j++] = e;
                postfix[j++] = ‘ ‘;
                pop(&s, &e);
            }
        }
        else if(infix[i]==‘+‘ || infix[i]==‘-‘)
        {
            if(infix[i] == ‘-‘ && (i==0 || (i!=0 && (infix[i-1]<‘0‘ || infix[i-1]>‘9‘))))  //当‘-‘号处于第一位,或前面是符号时,为负号标志
                flag = 1;
            else if(stack_empty(s))
                push(&s, infix[i]);
            else
            {
                do
                {
                    pop(&s, &e);
                    if(e==‘(‘ || e==‘[‘ || e== ‘{‘)
                        push(&s, e);
                    else
                    {
                        postfix[j++] = e;
                        postfix[j++] = ‘ ‘;
                    }
                }while(!stack_empty(s) && e!=‘(‘ && e!=‘[‘ && e!=‘{‘);
                push(&s, infix[i]);
            }
        }
        else if(infix[i]==‘*‘ || infix[i]==‘/‘ || infix[i]==‘(‘ || infix[i]==‘[‘ || infix[i] == ‘{‘)
            push(&s, infix[i]);
        else if(infix[i] == ‘\0‘)
            break;
        else
            return ERROR;
        i++;
    }

    while(!stack_empty(s))
    {
        pop(&s,&e);
        postfix[j++] = e;
        postfix[j++] = ‘ ‘;
    }

    clear_stack(&s);
    return OK;
}

/*******************根据后续表达式计算结果********************************/
Status calculate(char *postfix, int *result)
{
    SqStack s;
    char *op; //存放后缀表达式中的每个因数或运算符
    char *buf=postfix; //声明bufhe saveptr两个变量,是strtok_r函数的需要。
    char *saveptr=NULL;
    int d,e,f;

    if(init_stack(&s) != OK)
        return ERROR;

    while((op = strtok(buf, " ")) != NULL)
    {
        buf = NULL;
        switch(op[0])
        {
            case ‘+‘:
                pop(&s, &d);
                pop(&s, &e);
                f = d+e;
                push(&s, f);
                break;
            case ‘-‘:
                if(op[1]>=‘0‘ && op[1]<=‘9‘)    //是负号而不是减号
                {
                    d = atoi(op);
                    push(&s, d);
                    break;
                }
                pop(&s, &d);
                pop(&s, &e);
                f = e-d;
                push(&s, f);
                break;
            case ‘*‘:
                pop(&s, &d);
                pop(&s, &e);
                f = e*d;
                push(&s, f);
                break;
            case ‘/‘:
                pop(&s, &d);
                pop(&s, &e);
                f = e/d;
                push(&s, f);
                break;
            default:
                d = atoi(op);
                push(&s, d);
                break;
        }
    }
    pop(&s, result);
    clear_stack(&s);
}

void main()
{
    char infix[MAXSIZE] = {0};
    char postfix[MAXSIZE] = {0};
    int result = 0;

    scanf("%s", infix);

    infix_to_postfix(infix, postfix);
    calculate(postfix, &result);

    printf("%d\n",result);
}

栈的应用——四则表达式求值

时间: 2024-07-28 16:09:28

栈的应用——四则表达式求值的相关文章

数据结构(7)----栈与队列之栈的应用四则运算表达式求值

栈与队列之栈的应用四则运算表达式求值 栈在四则运算表达式求值的应用为逆波兰表达式(后缀表达式) 普通算式(中缀表达式):9 + (3 - 1) * 3 + 10 / 2     ---(1) 逆波兰表达式(后缀表达式):9 3 1 - 3 * + 10 2 /         ---(2) 1:逆波兰表达式的计算规则 从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号,就将处于栈顶的两个数字出栈,进行运算,再把运算结果进栈,一直到最终获得结果.接下来我们以(2)式为例:

11、蛤蟆的数据结构笔记之十一栈的应用之表达式求值实现

11.蛤蟆的数据结构笔记之十一栈的应用之表达式求值实现 本篇名言:"人生不售来回票,一旦动身,绝不能复返." 继续栈应用实现,这次是来看下表达式求值的栈实现. 欢迎转载,转载请标明出处: 1.  表达式求值 表达式求值是设计语言编译中的一个基本问题,它的实现是栈应用的又一个典型例子. 任何一个表达式都是由操作数(Operand).运算符(operator)和界限符(delimiter)组成. 操作数可以是常数也可以是变量或变量的标识符. 运算符可以分为算术运算符.关系运算符和逻辑运算符

栈的应用—算术表达式求值

例三.算术表达式求值 1.问题描述 当一个算术表达式中含有多个运算符,且运算符的优先级不同的情况下,如何才能处理一个算术表达式????? 2.思路 首先我们要知道表达式分为三类:  ①中缀表达式:a+(b-c/d)*e ②前缀表达式+a*-be ③后缀表达式abcd/-e*+ 由于运算符有优先级,所以在计算机中计算一个中缀的表达式非常困难,特别是带括号的更麻烦,而后缀表达式中既无运算符优先又无括号的约束问题因为在后缀表达式中运算符出现的顺序正是计算的顺序,所以计算一个后缀的表达式更简单.所以,可

栈的典型应用-表达式求值【转】

本文转载自:http://www.voidcn.com/blog/lub0807/article/p-1510616.html 栈的一个应用是求四则运算表达式的值,这里的表达式包含数字.加减乘除4种运算符,以及小括号. 由于输入是一个字符串,因此解决这个问题需要以下3个步骤: 1.输入字符串转化为中缀表达式: 2.中缀表达式转化为后缀表达式: 3.后缀表达式求值. 现在表达式为:9 + ( 3 - 1 )* 3 + 10 / 2 ,先看一下运行结果: 首先解释一下中缀表达式和后缀表达式的概念.所

数据结构 算法3.4(栈的应用) 表达式求值(stl版and数组模拟版)

问题是 输入一串表达式 其中包括 数字 和各种运算符(   +,-,*,/,(,) ) 求它的值 如 4+(5+2*7)*3 stl版: #include<iostream> #include<cstdio> #include<cstring> #include<stack> using namespace std; int operate(int a,char op,int b) { if(op=='+') return a+b; if(op=='-')

【数据结构】栈的应用——中缀表达式求值(c++)

头文件: #pragma once #include <iostream> #include <assert.h> #include <string> using namespace std; template<class Type> class SeqStack { public: SeqStack(size_t sz = INIT_SZ); ~SeqStack(); public: bool empty()const; bool full()const;

c++:栈的应用之表达式求值

Stack.hpp #pragma once template <class T> class Stack{ private: T* _array; size_t _capacity; int _topindex; public: Stack()          //构造函数 :_array(0) , _capacity(0) , _topindex(-1) {} void Push(const T& x){                         //入栈操作 if (_t

栈的应用 算术表达式求值 学习笔记

//SeqStack.h typedef struct stack { DATA data[SIZE+1];  //数据元素  int top;  //栈顶  }SeqStack; SeqStack *SeqStackInit() { SeqStack *p; if(p=(SeqStack *)(malloc)(sizeof(SeqStack)))  //申请栈内存  { p->top = 0; //设置栈顶为零  return p; //返回指向栈的指针  } return NULL; } i

栈的应用:表达式求值运算

http://blog.csdn.net/wenzhou1219/article/details/23961307 #include <iostream> #include <cstdio> #include <stack> #include <cstring> #include <stdlib.h> using namespace std; #define LEVEL_invalid -1 #define LEVEL_same 0 #defin