表达式求值(栈)

数据结构系列:表达式求值

——————————————————————————

1. 算法思想:

该算法在读入用户输入的中缀表达式后,直接对其进行计算。算法的基本流程如下:首先建立两个栈OPTR(操作符栈)和OPND(操作数栈),分别用于存放操作符和操作数,然后对用户输入的表达式进行扫描。如果遇到数字,就将其压入数值栈OPND,并读入表达式的下一个字符;如果遇到操作符,则比较操作符栈OPTR栈顶的操作符与当前索引下的操作符的优先级,并根据比较结果做出不同的操作:

( 1 ) 若栈顶操作符的优先级低于当前索引下的操作符,则将当前索引下的操作符压入操作符栈OPTR,并读入表达式的下一个字符;
( 2 ) 若栈顶操作符与当前索引下的操作符优先级相同,则将栈顶操作符弹出,并读入表达式的下一个字符;
( 3 ) 若栈顶操作符的优先级高于当前索引下的操作符,则取出栈顶操作符 o p ,并从数值栈OPND中依次取出操作数 b a ,计算表达式 < a , o p , b > 的值,并将结果压入数值栈 O P N D 中。
( 4 ) 重复进行上述操作,直到读取到表达式的结束标记并且操作符栈OPTR为空,此时数值栈 O P N D 中存放的数值即为表达式计算的最终结果。*

——————————————————————————

2. 算法流程图:

这里写图片描述
图2:算法流程图

应该能看懂吧,看不懂的话应该是数据结构没好好听课了。

——————————————————————————

第二步:话不多说放代码

   

#include "stdafx.h"
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <math.h>  

#define Stack_increment 20
#define Stack_Size 100  

/*运算符数组*/
char ops[7] = { '+', '-', '*', '/', '(', ')', '#' };

/*用来进行比较运算符优先级的矩阵,3代表'=',2代表'>',1代表'<',0代表不可比*/
int  cmp[7][7] = {  { 2, 2, 2, 2, 2, 1, 1 },
                    { 2, 2, 2, 2, 2, 1, 1 },
                    { 1, 1, 2, 2, 2, 1, 1 },
                    { 1, 1, 2, 2, 2, 1, 1 },
                    { 2, 2, 2, 2, 3, 1, 0 },
                    { 1, 1, 1, 1, 0, 1, 1 },
                    { 2, 2, 2, 2, 2, 0, 3 }  };


/*运算符栈的定义*/
typedef struct
{
    int stacksize;
    int *top;
    int *base;
}SeqStack;


/* 运算数栈的定义*/
typedef struct
{
    int stacksize;
    int *top;
    int *base;
}numSeqStack;


/*初始化运算符栈*/
void InitStack(SeqStack *S)
{
    S->base = (int *)malloc(Stack_Size * sizeof(int));
    S->top = S->base;
    S->stacksize = Stack_Size;
}


/*初始化运算数栈*/
void InitStacknum(numSeqStack *S)
{
    S->base = (int *)malloc(Stack_Size * sizeof(int));
    S->top = S->base;
    S->stacksize = Stack_Size;
}

/*判操作符栈为空栈时返回值为真,反之为假*/
int IsEmpty(SeqStack *S)
{
    return(S->top  == S->base ? 1 : 0);
}

/*判断栈S为空栈时返回值为真,反之为假*/
int IsEmptynum(numSeqStack *S)
{
    return(S->top == S->base ? 1 : 0);
}

/*判断符号栈S为满栈时返回值为真,反之为假*/
int IsFull(SeqStack *S)
{
    return (*S->top == Stack_Size - 1 ? 1 : 0);
}

/*判断操作数栈为满栈时返回值为真,反之为假*/
int IsFullnum(numSeqStack *S)
{
    return (*S->top == Stack_Size - 1 ? 1 : 0);
}

/*运算符栈入栈函数, '#'为结束标志*/
void Push(SeqStack *S, char x)
{
    if (* (S -> top) == Stack_Size - 1)
    {
        printf("Stack is full\n");
        S->base = (int *)realloc(S->base, (S->stacksize + Stack_increment) * sizeof(int));
        S->top = S->base + S->stacksize;
        S->stacksize = S->stacksize + Stack_increment;
    }
    else if (x == '#')
    {
        return;
    }
    else
    {
        *S->top++ = x;
    }
}

/*运算数入栈函数*/
void Pushnum(numSeqStack *S, int x)
{
    if (*S->top == Stack_Size - 1)
    {
        S->base = (int *)realloc(S->base, (S->stacksize + Stack_increment) * sizeof(int));
        S->top = S->base + S->stacksize;
        S->stacksize = S->stacksize + Stack_increment;
    }
    else  if ((char)x == '#')
    {
        return;
    }
    else
    {
        *(S -> top) = x;
        S -> top++;
    }
}


/*运算符栈出栈函数*/
int Pop(SeqStack *S)
{
    if (S->top == S->base)
    {
        return 0;
    }
    else
    {
        --(S->top);
        return 1;
    }
}


/*运算数栈出栈函数*/
int Popnum(numSeqStack *S)
{
    if (S -> top == S -> base)
    {
        return 0;
    }
    else
    {
        --(S -> top);
        return 1;
    }
}


/*运算符栈取栈顶元素函数*/
char GetTop(SeqStack *S)
{
    return (*(S->top - 1));
}

/*运算数栈取栈顶元素函数*/
int GetTopnum(numSeqStack *S)
{
    if (S -> top == S -> base)
    {
        return (*(S -> top ));
    }
    return (* (S -> top - 1));
}

int Isoperator(char ch)        /*判断输入字符是否为运算符函数,是返回TRUE,不是返回FALSE*/
{
    int i;
    for (i = 0; i < 7; i++)
    {
        if (ch == ops[i])
            return (int)1;
    }
    return (int)0;
}

/*比较运算符优先级函数*/
/*保存优先级比较后的结果'>'、'<'、'='*/
char Compare(char ch1, char ch2)
{
    int i, m = 0, n = 0;
    int priority;
    for (i = 0; i < 7; i++)
    {
        if (ch1 == ops[i])
            m = i;
        if (ch2 == ops[i])
            n = i;
    }
    priority = cmp[m][n];
    switch (cmp[m][n])
    {
    case 1:
        return (char)('<');
    case 2:
        return (char)('>');
    case 3:
        return (char)('=');
    default:
        printf("表达式错误!\n");
        break;
    }
}

/*运算函数*/
int Execute(int a, char op, int b)
{
    switch (op)
    {
    case '+':
        return  (b + a);
        break;
    case '-':
        return (b - a);
        break;
    case '*':
        return (b * a);
        break;
    case '/':
        return (b / a);
        break;
    }
}


/*读入一个简单算术表达式并计算其值。optr和operand分别为运算符栈和运算数栈,OPS为运算符集合*/
int ExpEvaluation()
{
    int a, b, v;
    int sum = 0;
    char ch, op, temp;
    char str[100];

    numSeqStack operand;
    SeqStack optr;

    /*初始化,没有元素*/
    InitStack(&optr);
    InitStacknum(&operand);

    printf("请输入表达式(#为结束符):\n");                      /*表达式输入*/
    scanf_s("%s", str, 100);                                         /*取得一行表达式至字符串中*/
    int i = 0;

    for (i; i < (strlen(str) + 1); )
    {
        ch = str[i];
        if (ch == '#')
        {
            if (IsEmpty(&optr))
            {
                v = GetTopnum(&operand);
                return v;
            }
            else
            {
                a = GetTopnum(&operand);
                Popnum(&operand);
                b = GetTopnum(&operand);
                Popnum(&operand);
                op = GetTop(&optr);
                Pop(&optr);
                v = Execute(a, op, b);
                Pushnum(&operand, v);
                if (ch == ')')
                {
                    Pop(&optr);
                }
            }
        }

        else if (!Isoperator(ch))
        {
            int dis = 0;
            int j = i, j1 = i, j2 = i, j3 = i;
            int k;                                  /*记录原始值*/
            for (k = i; k < (strlen(str) + 1); )
            {
                if (!Isoperator(ch))
                {
                    i++;
                    ch = str[i];
                    k++;
                    dis = i - j;                            /*记录差距的位数*/
                    j1 = i;
                    j2 = i;
                    j3 = i;
                }
                else if (Isoperator(ch))
                {
                    break;
                }
            }
            for (j1 = j1 - dis; j1 < j2 ; j1++)
            {
                int temp;
                temp = (int)(str[j1] - '0');
                sum = sum + temp * pow(10, (j2 - j1 - 1));              /*求和*/
                if (j2 - j1 < 0)
                {
                    break;
                }
            }
            Pushnum(&operand, sum);
            sum = 0;
            dis = 0;
        }

        else if (Isoperator(ch))
        {
            if (optr.base == optr.top)
            {
                Push(&optr, ch);
                i++;
            }
            else
            {
                char buf ;
                temp = GetTop(&optr);
                buf = Compare(temp, ch);
                if (buf == '>')
                {
                    Push(&optr, ch);
                    i++;
                }
                else if (buf == '=')
                {
                    Pop(&optr);
                }
                else
                {
                    a = GetTopnum(&operand);
                    Popnum(&operand);
                    b = GetTopnum(&operand);
                    Popnum(&operand);
                    op = GetTop(&optr);
                    Pop(&optr);
                    v = Execute(a, op, b);
                    Pushnum(&operand, v);
                    if (ch == ')')
                    {
                        Pop(&optr);
                    }
                    else
                    {
                        Push(&optr, ch);
                    }
                    i++;
                }
            }
        }
    }
}


/*主函数*/
int main()
{
    int result = 0;
    result = ExpEvaluation();
    printf("\n表达式结果是%d\n", result);
    getchar();
    getchar();
    return 0;
}

——————————————————————————

三:程序运行展示

这里写图片描述
图2:运行结果

四:结语

    等老师留了递归非递归遍历二叉树的作业,在继续放程序

猜你喜欢

转载自blog.csdn.net/asd20172016/article/details/80489304