《数据结构》:中缀表达式合法性判断

一、要求

输入一串任意的中缀表达式,对该表达式的合法性进行判断。

二、分析

不合法的表达式如:

(a+b *a+b a+() (a+b)(a-b)

          

大致可以归纳为以下四种非法情况

1、括号不匹配

例如:

(a+b:左括号未匹配

a+b):右括号未匹配

a+b)+(a+c:括号数量相同但显然不匹配

2、操作符左右元素不合法

中缀表达式的操作符是以中缀形式位于运算数中间,所以一个操作符的左右应该都有元素,且必须是运算数(中缀表达式经常使用括号,所以这里的运算数不局限于数字,也可以是一个表达式)。

例如:

+(a+b):操作符 + 号前一位没有运算数

(a+b)*:操作符 * 号后一位没有运算数

a+-b:操作符 + 号后一位还是操作符

(a+b)-(a+c):虽然操作符 - 号的前后一位都是括号,但是这里应该把 a+ba+c 整体的表达式看作一个运算数,所以是合法的

总结:

① 操作符前后位不能为空

② 操作符前后位不能为操作符

③ 操作符前一位可以为 ),但不能为 ( ;操作符后一位可以为 (,但不能为 ) 。

注:'-' 号比较特殊,需要判断它是作为负数符号还是操作符。

3、左括号和右括号相邻

例如:

(a+b)(a-b):括号匹配但明显不合法

(a+b)-():括号匹配但明显不合法

注:以上三种情况可能会出现重叠,但问题不大,只要能检测出不合法就行

三、算法实现

程序代码:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<ctype.h>

#define ERROR 0
#define OK 1
#define STACK_INT_SIZE 10  /*存储空间初始分配量*/
#define STACKINCREMENT 5   /*存储空间分配增量*/
#define M 50

typedef char ElemType;     /*定义字符数据类型*/

/*字符栈*/
typedef struct{
    ElemType *base;
    ElemType *top;
    int stacksize;     /*当前已分配的存储空间*/
}SqStack;

int InitStack(SqStack *S);          /*构造空栈*/
int push(SqStack *S,ElemType e);    /*入栈*/
int Pop(SqStack *S,ElemType *e);    /*出栈*/
int StackEmpty(SqStack *s);         /*栈空判断*/
int isoperator(char c);             /*操作符判断*/
int ExpressionCheck(ElemType *str); /*中缀表达式合法性检查*/

/*初始化栈*/
int InitStack(SqStack *S){
    S->base=(ElemType *)malloc(STACK_INT_SIZE * sizeof(ElemType));
    if(!S->base)
        return ERROR;  //分配失败
    S->top = S->base;
    S->stacksize = STACK_INT_SIZE;
    return OK;
}/*InitStack*/

/*入栈*/
int Push(SqStack *S,ElemType e){
    //判断栈满
    if(S->top - S->base >= S->stacksize){
        S->base = (ElemType *)realloc(S->base,(S->stacksize + STACKINCREMENT)*sizeof(ElemType));
        if(NULL == S->base)  //分配失败
            return ERROR;
        S->top = S->base + S->stacksize;
        S->stacksize = S->stacksize+STACKINCREMENT;
    }
    *S->top = e;
    S->top++;
    return OK;
}

/*出栈*/
int Pop(SqStack *S,ElemType *e){
    //判断栈空
    if(S->top == S->base)
        return ERROR;
    S->top--;
    *e=*S->top;
    return OK;
}/*Pop*/

/*判断栈空*/
int StackEmpty(SqStack *s){
    if(s->top == s->base)
        return OK;
    return ERROR;
}/*StackEmpty*/

/*判断字符c是否为运算符*/
int isoperator(char c)
{
    switch(c)
    {
        case '+':return OK;
        case '-':return OK;
        case '*':return OK;
        case '/':return OK;
        default:return ERROR;
    }
}

/*判断中缀表达式是否合法*/
//str为输入的中缀表达式字符串
int ExpressionCheck(ElemType *str)
{
    //初始化一个字符栈
    SqStack s;
    InitStack(&s);
    ElemType e;
    int i;

    //不合法情况1:括号不匹配
    for(i=0 ; i<strlen(str) ; i++)  //遍历中缀表达式
    {
        if(str[i] == '(')
            Push(&s,str[i]);
        if(str[i] == ')')
        {
            if(StackEmpty(&s))
                return ERROR;
            Pop(&s,&e);
        }
    }
    if(!StackEmpty(&s))
        return ERROR;

    //不合法情况2:操作符左右元素不合法
    for(i=0 ; i<strlen(str) ; i++)
    {
        //先判断 '-' 是不是负数符号
        if('-' == str[i])
        {
            if( 0==i || '('==str[i-1] ) //如果 - 在第一位或者前面有(,一定是作为负数符号而非操作符
                i++;
        }
        if(isoperator(str[i]))
        {
            if( 0==i || strlen(str)-1==i )
                return ERROR;
            if( isoperator(str[i-1]) || isoperator(str[i+1]) )
                return ERROR;
            if( '('==str[i-1] || ')'==str[i+1] )
                return ERROR;
        }
    }

    //不合法情况3:左括号和右括号相邻,例:a+()和(a+b)(a+b)
    for(i=0 ; i<strlen(str) ; i++)
    {
        if(str[i]=='(' && str[i+1]==')')
            return ERROR;
        if(str[i]==')' && str[i+1]=='(')
            return ERROR;
    }
    return OK;  //未出现不合法情况,返回1
}

int main()
{
    char str[M];
    printf("\n输入一串中缀表达式:\n");
    gets(str);
    int v = ExpressionCheck(str);
    if( v )
    {
        printf("\n中缀表达式合法\n");
        return 0;
    }
    printf("\n中缀表达式不合法\n");
    return 0;
}

  • 运行结果:

非法情况1:

非法情况2: 

     '-' 作为负数符号

非法情况3:

合法情况判断:

猜你喜欢

转载自blog.csdn.net/Amentos/article/details/129171785