(栈实现)逆波兰表达式的理解、转换、计算

咱们熟悉的四则表达式1+2,1+(23),1+(2+34)等等都是中缀表示法.
后缀表达式又叫逆波兰表达式,它是由相应的语法树的后序遍历的结果得到的。

如果现在举例计算:(1+(2*3))-(4/5):如果这个式子没有括号的话,可以画很多二叉树,我这里括起来,方便大家理解这个图,没错只要是有个括号他就有一个分支,分支到末尾即是数据。
(栈实现)逆波兰表达式的理解、转换、计算_第1张图片
二叉树的后序遍历顺序是左孩子节点,右孩子节点,根节点,
所以按照后序遍历结果为:1 2 3 * + 4 5 / -
没错得到了逆波兰表达式(后缀表达式),是不是很神奇!
介绍完了后缀与中缀,当然有前缀,这就自己去百度了,

那么计算机为什么喜欢处理逆波兰表达式,因为给出一串包含数字和操作符的时候,
计算机是按照顺序来读取的,采用逆波兰就是遇到操作符时就取前面刚刚读取的两个数字进行计算,如:1 2 3 * + 4 5 / -
计算机从左至有遍历时,读取了1 2 3 后遇到操作符* 就取前面两个数字即 2 3再相乘得到6,再把值放回,又遇到了加号时 把1和6进行操作…这样操作下来计算机就不用考虑优先级的问题,所以为什么要用到逆波兰表达式,
我将给出下面两段代码,计算和转换为逆波兰
1.用户输入中缀表达式,转化为逆波兰表达式
2.已知逆波兰表达式,求计算结果

//用户输入中缀表达式子,转化为逆波兰表达式
#include
#include
#include
#define OK     1
#define ERROR  0
#define STACK_INIT_SIZE 2
#define STACKINCREMENT  3
#define MAXBUFF   10
typedef int Status;
typedef char SElemType; //这里定义的是char类型
typedef struct{
    SElemType *top;
    SElemType *base;
    int stacksize;
}sqStack;
Status StackInit(sqStack *s){
    s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if(!s->base)
        return ERROR;
    s->top = s->base;
    s->stacksize = STACK_INIT_SIZE;
    return OK;
}
void Push(sqStack *s,SElemType e){
    if(s->top - s->base >= s->stacksize){
        s->base = (SElemType *)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(SElemType));
        if(!s->base){
            exit(0);
        }
        s->top = s->base + s->stacksize;
        s->stacksize += STACKINCREMENT;
    }
    *(s->top) = e;
    s->top++;
}
void Pop(sqStack *s,SElemType *e){
    if(s->top == s->base){
        return;
    }
    *e = *--(s->top);
}
int StackLength(sqStack *s){
    return (s->top - s->base);
}
int main(){
	sqStack s;
    StackInit(&s);
    char c,e;//e接收临时处理的数据,c读取输入的数据
    printf("请输入中缀表达式,以#作为结束标志!\n");
    scanf("%c",&c);
    while(c!='#'){
        if('0'<=c&&'9'>c){//相当于isdigit(),记得加上头文件ctype.h
            printf("%c",c);
        }
        else if(')'==c){
            Pop(&s,&e);
            while('('!=e){
                printf("%c",e);
                Pop(&s,&e);
            }
        }
        else if('+'==c||'-'==c){
            if(!StackLength(&s)){
                Push(&s,c);
            }
            else{
                do{
                    Pop(&s,&e);
                    if('('==e){
                        Push(&s,e);
                    }
                    else{
                        printf("%c",e);
                    }
                }while('('!=e&&StackLength(&s));
                Push(&s,c);
            }
        }
        else if('*'==c||'/'==c||'('==c){
            Push(&s,c);
        }
        else{
            printf("输入的字符有误,tips:中间是否存在空格,是否为英文括号,\n\t\t是否为整数,是否输入作为#结束..");
            return -1;
        }
        scanf("%c",&c);
    }

    while(StackLength(&s)){
        Pop(&s,&e);
        printf("%c",e);
    }
    return 0;
}
/*
====test:====
请输入中缀表达式,以#作为结束标志!
1+(2-3*4)-10/6#
1234*-+106/-
*/
//已知逆波兰表达式,计算结果,定义的SElemType类型与上面不一样
#include
#include
#include
#define OK     1
#define ERROR  0
#define STACK_INIT_SIZE 2
#define STACKINCREMENT  3
#define MAXBUFF   10
typedef int Status;
typedef double SElemType;//这里定义的是double类型
typedef struct{
    SElemType *top;
    SElemType *base;
    int stacksize;
}sqStack;
Status StackInit(sqStack *s){
    s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if(!s->base)
        return ERROR;
    s->top = s->base;
    s->stacksize = STACK_INIT_SIZE;
    return OK;
}
void Push(sqStack *s,SElemType e){
    if(s->top - s->base >= s->stacksize){
        s->base = (SElemType *)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(SElemType));
        if(!s->base){
            exit(0);
        }
        s->top = s->base + s->stacksize;
        s->stacksize += STACKINCREMENT;
    }
    *(s->top) = e;
    s->top++;
}
void Pop(sqStack *s,SElemType *e){
    if(s->top == s->base){
        return;
    }
    *e = *--(s->top);
}
int StackLength(sqStack *s){
    return (s->top - s->base);
}
int main(){
	sqStack s;
    char str[MAXBUFF];
    char c;
    SElemType d,first,last;
    StackInit(&s);
    int i=0;
    printf("请输入后缀表达式(数据可为浮点型),\n\t\t数据和操作符以空格隔开,\n\t\t和以#作为结束标志..\n");
    scanf("%c",&c);
    while(c!='#'){
        while(isdigit(c)||c=='.'){
            str[i++]=c;
            if(i>10){
                printf("输入的单个字符过大!\n");
                return -1;
            }
            scanf("%c",&c);
            if(c==' '){
                d = atof(str);
                Push(&s,d);
                i = 0;
            }
        }
        switch(c){
            case '+':
                Pop(&s,&first);
                Pop(&s,&last);
                Push(&s,last+first);
                //printf("%c",(last+first-96));
                break;
            case '-':
                Pop(&s,&first);
                Pop(&s,&last);
                Push(&s,last-first);
                break;
            case '*':
                Pop(&s,&first);
                Pop(&s,&last);
                Push(&s,last*first);
                break;
            case '/':
                Pop(&s,&first);
                Pop(&s,&last);
                Push(&s,last/first);
                break;
        }
        scanf("%c",&c);
    }
    printf("计算结果为:");
    Pop(&s,&d);
    printf("%f\n",d);
    return 0;
}

/*
====test:====
请输入后缀表达式(数据可为浮点型),
                数据和操作符以空格隔开,
                和以#作为结束标志..
1 2 3 4 * - + 10 6 / -#
转化为十进制结果为:-9.166667
*/

关于c++篇————波兰式、逆波兰式与表达式求值

在我的下一篇csdn文章中——c语言栈的应用(实战-逆波兰表达式)
来实现将上述用户输入转化为逆波兰和用逆波兰实现计算功能合二为一。

你可能感兴趣的:(数据结构,数据结构,c语言,算法,栈)