利用顺序栈实现括号匹配的检验

NOTICE: 本题代码是按照源码顺序贴上的,复制可直接运行

环境: Visual Stdio Code

 

题目

利用顺序栈实现括号匹配的检验(严蔚敏版《数据结构》第49页3.2.2)

思路

我的思路是直接入栈和检验同时进行,即:如果两个相近的括号的差值符合要求([ ] 的差值为 2、( ) 的差值为 1),就将此时顺序栈的最上边两个元素出栈,如果 StackLength 为 0, 则证明所有元素均已出栈(即:匹配检验通过),返回成功提醒,否则必须输入‘#’才能停止程序。最后打印出当前的顺序栈(此时如果看到顺序栈不为空,就证明没有通过检验)。

操作流程示意图:

emmmm,小编觉得思路还是比较清晰的。

源码

初始化:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define STACK_INIT_SIZE 10 // 初始化分配量
#define STACKINCREMENT 1  // 分配增量
#define ERROR 0
#define OK 1

typedef int Status;
typedef char SElemType;

typedef struct
{
    SElemType *base;  // 栈底指针
    SElemType *top;   // 栈顶元素
    int stacksize;
}SqStack;

Status InitStack(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;
}//InitStack

销毁:

Status DestroyStack(SqStack &S)
{   // 销毁
    if(S.base)
    {
        delete S.base;  // C++ 中用来释放之前动态分配的内存
        S.stacksize = 0;
        S.base = S.top = NULL;
    }
    return OK;
}//DestroyStack

判断是否为空栈:

Status StackEmpty(SqStack &S)
{   // 判断是否为空栈
    if(S.top == S.base) return OK;
    else return ERROR;
}//StackEmpty

获取栈容量:

Status StackLength(SqStack &S)
{   // 获取栈容量
    return S.top - S.base;
}//StackLength

入栈:

Status 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) return ERROR;
        S.top = S.base + S.stacksize;
        S.stacksize += STACKINCREMENT;
    }
    *S.top ++= *e;
    return OK;
}//Push

出栈:

Status Pop(SqStack &S, SElemType *e)
{   // 出栈
    if(S.top == S.base) return ERROR;
    *e = *--S.top;
    return OK;
}//Pop

打印栈:

Status StackTraverse(SqStack &S)
{   // 打印
    SElemType *p = (SElemType *)malloc(sizeof(SElemType));
    p = S.top;
    if(!p) return ERROR;
    else
    {
        p--;
        while(p >= S.base)
        {
            printf("%c ", *p);
            p--;
        }
    }
    return OK;
}//StackTraverse

获取栈顶元素:

Status GetTop(SqStack &S, SElemType *e)
{   // 若栈不空,用 e 返回 S 的栈顶元素,并返回 OK,否则返回 ERROR
    if(S.top == S.base) return ERROR;
    *e = *(S.top-1);
    return OK;
}//GetTop

检验:

Status Judge(SqStack &S)
{   // 括号匹配检验
    SElemType e, out;
    // 入栈、判断
    printf("\n请依次输入想要检验的括号(输入 # 结束):\n");    
    while(e != '#')    // 如果匹配不通过,必须手动输入 # 来结束程序
    {
        printf("\n请输入入栈元素:\n");
        scanf("%c", &e);
        getchar();
        if(e == '#') break;       // 我发现不写这行会出现一个问题,就是输入一个 # 不会退出
        if(StackLength(S) >= 0)     
        {
            int i = 0;
            GetTop(S, &out);       // 获取当前栈顶元素
            Push(S, &e);            // 入栈
            printf("\n栈顶元素与输入元素的差的绝对值为:%d\n",abs(out-e));   // 如上文分析所说,'[' - ']' = 2, '(' - ')' = 1
            if(abs(out-e) == 1 || abs(out-e) == 2)  // 如果括号匹配通过
            {
                while(i != 2)         // 之所以出栈两次是因为,新的元素已经插入,此时栈顶两个元素是匹配成功的,删除的是这两个元素
                {
                    Pop(S, &out);         
                    printf("\n出栈元素为:%c\n", out);
                    i ++;
                }
                if(StackEmpty(S))    // 顺序栈为空,跳出循环,提示通过
                {
                    printf("\n检验通过!\n");
                    break;
                }
                continue;
            }
            printf("\n栈容量:%d\n", StackLength(S));     // 可以不要,我只是想直观地看一下栈当前容量
        }
    }
    printf("\n栈的当前容量为:%d\n", StackLength(S));       // 从这行往下都是最后返回栈元素的语句,目的是当匹配不通过时返回所有元素
    printf("\n------------------------------------\n");
    {   // 出栈,查看当前剩余元素
        printf("\n栈的元素为:\n");
        while(S.top != S.base)
        {
            Pop(S, &e);
            printf("%c ", e);
        }
    }
    return OK;
}//Judge

主函数:

int main()
{
    SqStack S;
    
    if(InitStack(S)) printf("\n初始化成功!\n");
    else exit(0);
    Judge(S);
    DestroyStack(S);      // 要养成用完即销毁的好习惯,虽然现在的计算机会自动销毁,但是养成这个好习惯还是没坏处的
    return OK;
}

运行结果示意图:

我不晓得怎么截取长图.......

THE END!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章