实验三 栈和循环队列的表示与实现 栈部分
一、实验目的
掌握顺序栈和链栈的入栈、出栈基本操作,栈满、栈空的条件;
二、实验内容
假设表达式中允许包含圆括号、方括号和大括号3种括号,编写一个算法判断表达式中的括号是否正确配对。并将其用C语言实现,上机运行输出结果。
用顺序栈实现。提示:输入一串包括左右圆、方、大括号的字符,则左括号入栈,当和右括号匹配时,则出栈。
头文件及宏定义:
/*CaptainUniverse_ 2022.4.1*/
#include <stdio.h>
#include <stdlib.h>
#define LEFT 1
#define RIGHT 2
#define FALSE 0
#define STACK_INIT_SIZE 20
typedef int Status;
typedef struct
{
int top;
int base;
char *data;
}sqStack;
/*CaptainUniverse_ 2022.4.1*/
子函数声明:
/*CaptainUniverse_ 2022.4.1*/
Status isBrackets(char);//判断是否为括号
void InitStack(sqStack *);//栈初始化
void Push(sqStack *,char);//压栈
void Pop(sqStack *,char *);//弹栈
/*CaptainUniverse_ 2022.4.1*/
子函数主体:
/*CaptainUniverse_ 2022.4.1*/
void InitStack(sqStack *s)
{
s->data=malloc(STACK_INIT_SIZE*sizeof(char));
if(!s->data)
{
printf("内存分配失败!");
exit(0);
}
s->top=s->base=0;
s->data[++(s->top)]='#';//栈内首元素压入'#'
}
void Push(sqStack *s,char ch)
{
if(s->top==STACK_INIT_SIZE)
{
printf("左括号过多!即将退出!\n");
exit(0);
}
s->data[++(s->top)]=ch;
}
void Pop(sqStack *s,char *ch)
{
if(s->top==s->base)
{
printf("栈已空!\n");
exit(0);
}
*ch=s->data[(s->top)--];
}
Status isBrackets(char ch)
{
if(ch=='('||ch=='['||ch=='{')
{
return LEFT;
}
else if(ch==')'||ch==']'||ch=='}')
{
return RIGHT;
}
else
{
return FALSE;
}
}
/*CaptainUniverse_ 2022.4.1*/
主函数:
/*CaptainUniverse_ 2022.4.1*/
int main()
{
char ch,temp;
sqStack s;
InitStack(&s);
printf("请输入一串括号字符以#结束!\n");
printf("左括号上限19个!\n")
while((ch=getchar())!='#')
{
if(isBrackets(ch)==LEFT)
{
Push(&s,ch);
}
if(isBrackets(ch)==RIGHT)
{
Pop(&s,&temp);
if((ch!=(temp+1))&&(ch!=(temp+2)))
{
NO: printf("不匹配!\n");
return 0;
}
}
}
Pop(&s,&temp);
if(temp=='#')
{
printf("匹配!\n");
}
else
{
goto NO;//纯粹图方便和美观
}
return 0;
}
/*CaptainUniverse_ 2022.4.1*/
分析:
1.遇到左括号压栈,遇到右括号将其与弹栈符号比较,如果符合则继续输入继续比较,直到输入'#'结束。注意:当输入'#'时已结束循环,故输入的'#'不参与比较。
2.匹配条件:左括号个数等于右括号个数,且此时栈内只有初始化时的’#'。
3.三种情况:
①左括号个数=右括号个数(包括左右括号个数都为零)。正常比较。
②左括号个数>右括号个数。假设所有右括号比较完毕,遇到'#'跳出循环,此时栈内存的不只是'#',还有多余的左括号,故不匹配。
③左括号个数<右括号个数。假设栈内所有左括号已比较完毕,下一个右括号讲与栈内'#‘元素比较,自然不匹配。
4.右括号与左括号的比较实为其ASCII码的比较。
'(' = 40
')' = 41
'[' = 91
']' = 93
'{' = 123
'}' = 125
这就是括号是否匹配的关键判断因素。
可略过部分:
我们设左括号为left,右括号为right(都为char类型),
如果left+1==right 为真 或者 left+2==right 为真 则括号匹配,转换成C语言:
if((left+1==right)||(left+2==right))
printf("真");
else
printf("假");
但我们此时想实现“如果不匹配则结束循环”
我们只需要将条件改为否命题,再将结果换位即可。
if((left+1!=right)&&(left+2!=right))
printf("假");
else
printf("真");
这是常用的“正难则反”思想。