栈的应用(一)——中缀表达式转后缀表达式

原文地址

这是一个栈的使用的例子:四则运算表达式求值时中缀表达式转后缀(逆波兰)表达式,包含括号平衡判断。

转换的规则:
从左到右依次遍历中缀表达式中的数字和符号,若遇到数字则直接输出到后缀表达式;若遇到符号,则将其与栈顶符号进行优先级比较,如果是右括号或者优先级不高于栈顶符号,则栈顶元素依次出栈,并将当前符号进栈,循环处理,直到将中缀表达式遍历完成。

源代码目录结构

直接贴代码:

头文件:Stack.h
#ifndef STACK_H  
#define STACK_H  

/*定义状态码*/  
#define ERROR -1  
#define TRUE 1  
#define FALSE 0  
typedef int Status;  

/*定义结构体*/  
#define MAXSIZE 100  
typedef char ElemType;  
typedef struct  
{  
    ElemType data[MAXSIZE];  
    int top;  
}Stack , *PtrStack;  

/*函数原型说明*/  
PtrStack InitStack ();  
Status IsEmpty(Stack *s);  
Status Push (Stack *s , ElemType e);  
Status Pop (Stack *s , ElemType *e);  
int ExpMidToLast(char *midExp , char *postExp);  
int IsExpBalance (char *midExp);  

#endif  
主函数所在,EX_Stack.c
#include "Stack.h"  
#include<stdio.h>  

void inputMidExp(char *midExp);  
void outputPostExp(char *postExp);  

void main ()  
{  
    int i = 0;  
    char c;  
    char midExp[100] , postExp[100];  
    inputMidExp(midExp);  
    if(IsExpBalance (midExp) == 1)  
    {  
        printf("表达式中括号平衡\n");  
        if (ExpMidToLast (midExp , postExp) == -1)  
        {  
            printf("ERROR");  
        }  
        else   
        {  
            outputPostExp(postExp);  
        }  
    }  
    else  
    {  
        printf("表达式括号不平衡\n");  
    }  
}  

void inputMidExp(char *midExp)  
{  
    char c;  
    int i = 0;  
    printf("请输入四则运算表达式:\n");  
    scanf("%c" , &c);  
    while (c != '\n')  
    {  
        midExp[i++] = c;  
        scanf("%c" , &c);  
    }  
    midExp[i] = '\0';  
}  

void outputPostExp(char *postExp)  
{  
    int i = 0;  
    printf("逆波兰表达式:\n");  
    while (postExp[i] != '\0')  
    {  
        printf("%c" , postExp[i]);  
        i++;  
    }  
    printf("\n");  
}  
判断中缀表达式是否括号平衡,IsExpBalance.c

若表达式中有诸如<>[]等,也是一样处理,这里只是举例说明

#include "Stack.h"  
#include<stdio.h>  

int IsExpBalance (char *midExp)  
{  
    int i = 0;  
    ElemType e;  
    PtrStack s;  
    s = InitStack();  
    if (!s)  
    {  
        return -1;  
    }  

    while (midExp[i] != '\0')  
    {  
        switch(midExp[i])  
        {  
            case '(':  
                Push(s , midExp[i]);  
                break;  
            case ')':  
                if (IsEmpty(s))  
                {  
                    return 0;  
                }  
                Pop(s , &e);  
                break;  
            default :  
                break;  
        }  
        i++;  
    }  

    if(IsEmpty(s))  
    {  
        return 1;  
    }  
    else  
    {  
        return 0;  
    }  
} 
栈的基本操作的实现,StackOperation.c

包括初始化、判断是否为空、入栈、出栈,

#include "Stack.h"  
#include<stdio.h>  
#include<stdlib.h>  

PtrStack InitStack()  
{  
    PtrStack s;  
    s = (PtrStack)malloc(sizeof(Stack));  
    if (s != NULL)  
    {  
        s ->top = -1;  
    }  
    return s;  
}  

Status IsEmpty (Stack *s)  
{  
    if (s->top == -1)  
    {  
        return TRUE;  
    }  
    return FALSE;  
}  

Status Push (Stack *s , ElemType e)  
{  
    if (s->top == MAXSIZE - 1)  
    {  
        return ERROR;  
    }  
    s->data[++s->top] = e;  
    return TRUE;  
}  

Status Pop (Stack *s , ElemType *e)  
{  
    if (s->top == -1)  
    {  
        return ERROR;  
    }  
    *e = s->data[s->top];  
    s->top --;  
    return TRUE;  
}  
中缀表达式转后缀表达式核心代码,MidToPost.c
#include "Stack.h"  
#include<stdio.h>  

int ExpMidToLast (char *midExp , char *postExp)  
{  
    int i , j;  
    char elem , temp;  
    ElemType e;  
    PtrStack s;  
    s = InitStack();  
    if (!s)  
    {  
        return -1;  
    }  

    i = j = 0;  
    elem = midExp[i];  
    while (elem != '\0')  
    {  
        switch (elem)  
        {  
            case '(':  
            {  
                Push(s , elem);  
                break ;  
            }  
            case ')':  
            {  
                postExp[j++] = ' ';  
                Pop(s , &e);  
                temp = e;  
                /*只要不是左括号,则全部弹出*/  
                while('(' != temp)  
                {  
                    postExp[j++] = temp;  
                    Pop(s , &e);  
                    temp = e;  
                }  
                break;  
            }  
            case '*':  
            case '/':  
            {  
                postExp[j++] = ' ';  
                if ( !IsEmpty(s) )  
                {  
                    Pop(s , &e);  
                    temp = e;  
                    while(temp != '+' && temp != '-' && temp != '(')  
                    {  
                        postExp[j++] = temp;  
                        postExp[j++] = ' ';  
                        if(IsEmpty(s))  
                        {  
                            break;  
                        }  
                        Pop(s , &e);  
                        temp = e;  
                    }  
                    Push(s , temp);  
                }  
                Push(s , elem);  
                break;  
            }  
            case '-':  
            case '+':  
            {  
                postExp[j++] = ' ';  
                if(!IsEmpty(s))  
                {  
                    /*弹出所有非左括号的操作符*/  
                    Pop(s , &e);  
                    temp = e;  
                    while('(' != temp )  
                    {  
                        postExp[j++] = temp;  
                        postExp[j++] = ' ';  
                        if(IsEmpty(s))  
                        {  
                            break;  
                        }  
                        Pop(s , &e);  
                        temp = e;  
                    }  
                    if('(' == temp)  
                    {  
                        Push(s , temp);  
                    }  
                }  
                Push(s , elem);  
                break;  
            }  
            default:  
            {  
                /*数字直接输出到后缀表达式*/  
                postExp[j++] = elem;  
                break;  
            }  
        }  
        elem = midExp[++i];  
    }  

    /*将栈中非空的操作符输出到后缀表达式中*/  
    while(!IsEmpty(s))  
    {  
        Pop(s , &e);  
        temp = e;  
        postExp[j++] = ' ';  
        postExp[j++] = e;  
    }  
    postExp[j] = '\0';  
    return 1;  
}  
结果

最后补充两点:

1、根据后缀(逆波兰)表达式求值更简单,规则为:从左到右依次遍历后缀表达式,遇到数字就进栈(这里要注意数字的转化处理,根据分隔符-空格判断),遇到符号就将处于栈顶的两个数字出栈进行运算之后将结果进栈,直到遍历结束即可得到表达式的运算结果。这里就不写代码出来了。

2、关于初始输入的中缀表达式的格式的判断问题,我现在只能想到最拙劣的办法,就是遍历表达式,然后去判断每个字符前后的字符是否符合规则,比如‘+’前一个字符不能是运算符和‘(’,后一个字符不能是运算符和‘)’,并且不能位于表达式的第一个位置。大家如果有什么好办法可以留言交流。

:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值