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!