栈的应用:表达式括号匹配检测(C)

问题说明:

假设数学表达式中允许包含两种括号:圆括号“()”和方括号“[]”,嵌套顺序任意。

正确的嵌套模式:( [ ] ( ) )、[ ( [ ] [ ] ) ]

正确的表达式例:(a+b)[c*(d-e)]

错误的嵌套模式:[ ( ] )、( ( ) ]

比如,在处理表达式(A)时

(A)  4+(2+8)*[5/(9-7)]

有以下步骤:

(1)检测到第一个括号“(”;

(2)检测到第二个括号“)”,说明子表达式 “4+(2+8)” 已完成匹配;

(3)检测到第三个括号“[”;

(4)检测到第四个括号“(”,与(3)中的括号不匹配,但由于同是左括号,可以继续匹配;

(5)检测到第五个括号“)”,由括号的作用可知,后来的括号比先来的括号优先级高,因此与(4)中括号匹配;

(6)检测到第六个括号“]”,由于原来优先级更高的括号已完成,因此与(3)中括号匹配。至此所有括号匹配完成。

解决方案:

可以看出,匹配成功的条件很简单:每一个检测到的括号与已检测到的优先级最高的括号都匹配。

匹配失败的条件:

(1)检测到与已检测到的优先级最高的括号不匹配的括号;

(2)扫描完整个表达式,还是有已检测到的括号没有完成匹配;

由于栈具有“先进后出”的特点,能很好地表现优先级这个性质,因此可以用栈来存储已经检测到的括号。

以(A)为例:

有以下步骤:

(1)检测到第一个括号“(”,进栈;

(2)检测到第二个括号“)”,进栈。子表达式 “4+(2+8)” 完成匹配,匹配的括号都出栈;

(3)检测到第三个括号“[”,进栈;

(4)检测到第四个括号“(”,进栈。与(3)中的括号不匹配,但由于同是左括号,可以继续匹配;

(5)检测到第五个括号“)”,进栈。由括号的作用可知,后来的括号比先来的括号优先级高,因此与(4)中括号匹配,匹配的括号都出栈;

(6)检测到第六个括号“]”,进栈。由于原来优先级更高的括号已完成,因此与(3)中括号匹配。匹配的括号都出栈,至此所有括号匹配完成。

需要注意的是,第一个括号进栈时,没有比较对象,因此需要特别处理。

判断函数 judge () 如下:

 1 Status judge(Stack *S)
 2 {
 3     //进行表达式的输入和判断 
 4     SElemType *p;
 5     char n;
 6     
 7     scanf("%c",&n);            //第一个括号的检测
 8     while(n!='(' && n!='[')        //忽略数字等其他符号,直到输入括号
 9     {
10         if(n==')' || n==']' || n=='#')    return FALSE;    //若为')'或']',则表明不匹配。'#'用于结束输入
11         scanf("%c",&n);    
12     }
13     
14     if(n=='(' || n=='[')    Push(S,n);    //检测到左括号,进栈
15     scanf("%c",&n);
16     while(n!='#')    //'#'用于结束输入
17     {    
18         if(n=='(' || n==')' || n=='[' || n==']')
19         {
20             p=S->top;
21             Push(S,n);
22             if(*(p-1)=='(')        //与前一个括号比较
23             {
24                 if(*p==')')    
25                 {
26                     printf("%c\n",Pop(S));
27                     printf("%c\n",Pop(S));
28                 }
29                 else if(*p==']')    return FALSE;
30             }
31             else if(*(p-1)=='[')
32             {
33                 if(*p==']')    
34                 {
35                     printf("%c\n",Pop(S));
36                     printf("%c\n",Pop(S));
37                 }
38                 else if(*p==')')    return FALSE;
39             }
40         }
41         scanf("%c",&n);
42     }
43     if(S->top==S->base)    return TRUE; //栈内没有元素时,说明匹配 
44     else return FALSE;
45 }

源代码如下:

#include <stdio.h>
#include <stdlib.h>
#define INIT_SIZE 10
#define INCREMENT 5

#define OVERFLOW -2
#define FALSE 0 
#define OK 1
#define TRUE 1
#define ERROR 0

typedef char SElemType; 
typedef int Status;
typedef struct stack{
    SElemType *base;
    SElemType *top;
    int stacksize; 
}Stack;

Status InitStack(Stack *S)
{
    //初始化栈 
    S->base=(SElemType *)malloc(INIT_SIZE*sizeof(SElemType));
    if(!S->base) exit(OVERFLOW);
    S->top=S->base;
    S->stacksize=INIT_SIZE;
    return OK;
}

Status Push(Stack *S,char e)
{
    //入栈 
    if(S->top-S->base>=S->stacksize){    //栈满,重新分配内存 
        S->base=(SElemType *)realloc(S->base,(INIT_SIZE+INCREMENT)*sizeof(SElemType));
        if(!S->base) exit(OVERFLOW);
        S->top=S->base+S->stacksize;
        S->stacksize+=INCREMENT;
    }
    *S->top++=e;
    return OK;
}

char Pop(Stack *S)
{
    //出栈 
    char e;
    
    if(S->top==S->base)    return ERROR;    //栈空,出错 
    e=*(--S->top);
    return e;
}

Status judge(Stack *S)
{
    //进行表达式的输入和判断 
    SElemType *p;
    char n;
    
    scanf("%c",&n);            //第一个括号的检测
    while(n!='(' && n!='[')        //忽略数字等其他符号,直到输入括号
    {
        if(n==')' || n==']' || n=='#')    return FALSE;    //若为')'或']',则表明不匹配。'#'用于结束输入
        scanf("%c",&n);    
    }
    
    if(n=='(' || n=='[')    Push(S,n);    //检测到左括号,进栈
    scanf("%c",&n);
    while(n!='#')    //'#'用于结束输入
    {    
        if(n=='(' || n==')' || n=='[' || n==']')
        {
            p=S->top;
            Push(S,n);
            if(*(p-1)=='(')        //与前一个括号比较
            {
                if(*p==')')    
                {
                    printf("%c\n",Pop(S));
                    printf("%c\n",Pop(S));
                }
                else if(*p==']')    return FALSE;
            }
            else if(*(p-1)=='[')
            {
                if(*p==']')    
                {
                    printf("%c\n",Pop(S));
                    printf("%c\n",Pop(S));
                }
                else if(*p==')')    return FALSE;
            }
        }
        scanf("%c",&n);
    }
    if(S->top==S->base)    return TRUE; //栈内没有元素时,说明匹配 
    else return FALSE;
}

int main()
{
    Stack Sta;
    Stack *S=&Sta;
    
    printf("INITIALIZING...\n");
    if(InitStack(S)) printf("DONE!\n");

    printf("enter an expression(stop by '#'):\n");
    if(judge(S)==1)    printf("It's True!");
    else printf("It's False\n");
    
    return 0;
}
source

猜你喜欢

转载自www.cnblogs.com/stargazer7/p/9823227.html
今日推荐