zoukankan      html  css  js  c++  java
  • 栈的应用:表达式括号匹配检测(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
    ",Pop(S));
    27                     printf("%c
    ",Pop(S));
    28                 }
    29                 else if(*p==']')    return FALSE;
    30             }
    31             else if(*(p-1)=='[')
    32             {
    33                 if(*p==']')    
    34                 {
    35                     printf("%c
    ",Pop(S));
    36                     printf("%c
    ",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
    ",Pop(S));
                        printf("%c
    ",Pop(S));
                    }
                    else if(*p==']')    return FALSE;
                }
                else if(*(p-1)=='[')
                {
                    if(*p==']')    
                    {
                        printf("%c
    ",Pop(S));
                        printf("%c
    ",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...
    ");
        if(InitStack(S)) printf("DONE!
    ");
    
        printf("enter an expression(stop by '#'):
    ");
        if(judge(S)==1)    printf("It's True!");
        else printf("It's False
    ");
        
        return 0;
    }
    source
  • 相关阅读:
    元素和容器, Model and View
    KeyboardHook in C#
    项目步骤
    对编程的思考
    Web开发中使用数据库的3种方式
    动态得到属性的名字
    WPF Databinding examples
    【SPOJ】220 Relevant Phrases of Annihilation
    【FOJ】2075 Substring
    【UVa】760 DNA Sequencing
  • 原文地址:https://www.cnblogs.com/stargazer7/p/9823227.html
Copyright © 2011-2022 走看看