利用順序棧實現括號匹配的檢驗

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!

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