7-1 括号匹配 (20分)(数据结构)
检查一段C语言代码的小括号( )、 中括号 [ ] 和大括号{ } 是否匹配。
输入格式:
在一行中输入一段C语言代码,长度不超过1000个字符(行末以换行符结束)。
输出格式:
第一行输出左括号的数量和右括号的数量,中间以一个空格间隔。 若括号是匹配的,在第二行打印YES,否则打印NO。
输入样例1:
for(int i=0; i<v; i++){ visited[i] = 0; for(int j=0; j<v; j++)
scanf("%d",&(g->Adj[i][j])); }
输出样例1:
8 8
YES
输入样例2:
for(int i=0; i<v; i++) a(i]=0;
输出样例2:
2 2
NO
思考
- 看到这道题,第一反应是要在一群代码里找到C语言常用的大中小括号,就要过滤掉代码里的其他内容,还要判断左右括号是否配对,按要求组合等情况。在这里我是先用一个数组去将代码存起来,在通过遍历、压栈、出栈等操作去实现括号的配对查询。
- 当遇到左括号时就被压进栈中,在遇到右括号时出栈,当出栈的元素跟所遇到的右括号不匹配时就可知道是不匹配的情况。当所有代码遍历完后,栈中还有元素,就证明括号也是不匹配的。
- 栈的特性也正好符合括号匹配查找的特点,我在这里用的是栈的链式储存去完成。
代码展示
#include<stdio.h>
#include<stdlib.h>
#include <malloc.h>
#define MAX 1001
typedef char ElementType;
typedef struct stack { //在这里新建一个栈结构
ElementType a;//这个用来存储括号类型
struct stack *next;//指向下一个结点
} List,*lp;
struct stack *create();//初始化栈
int Push(lp L,ElementType x);//入栈
int Pop(lp L,ElementType e);//出栈
int main(void) {
char s[MAX];//新建一个数组并存储输入的代码
gets(s);
int i=0,left=0,right=0,flag=1;//分别是左括号、右括号的计数和判断是否匹配的旗帜
lp L=NULL;//新建一个栈指针,并初始化(不熟悉的同学可以去参考一下浙大线性结构的教材)
L=create();
while(s[i]!='\0') {//开始对数组遍历
//在遍历过程中,只对括号元素反应。
if(s[i]=='(') {
Push(L,'(');//遇到左括号就进行压栈,并计数
left++;
} else if(s[i]=='[') {
Push(L,'[');
left++;
} else if(s[i]=='{') {
Push(L,'{');
left++;
} else if(s[i]==')') {
//遇见右括号就先判断括号是否匹配,并开始计数
if(Pop(L,'(')!=1) flag=0 ;//这里我直接用相应的左括号去配对
right++;
} else if(s[i]==']') {
if(Pop(L,'[')!=1) flag=0 ;
right++;
} else if(s[i]=='}') {
if(Pop(L,'{')!=1) flag=0 ;
right++;
}
i++;
}
if(L->next!=NULL) flag=0;//在遍历完所有代码后就判断栈中是否为空
printf("%d %d\n",left,right);//输出左右括号的个数
if(flag==1) {//输出匹配的情况
printf("YES\n");
} else {
printf("NO\n");
}
}
struct stack *create() {//初始化
lp s=NULL;//新建一个栈指针
s=(lp)malloc(sizeof(lp));//申请空间
s->next=NULL;
return s;
}
int Push(lp L,ElementType x) {//压栈
lp p=(lp)malloc(sizeof(lp));//新建结点
p->a=x;//将左括号压进栈
p->next=L->next;//将next指针进行更新
L->next=p;//连接链表
return 1;
}
int Pop(lp L,ElementType e) {
lp p=(lp)malloc(sizeof(lp));//新建一个结点
if(L->next==NULL) return 0;//先判断链表是否为空
p=L->next;//将栈顶的元素取出
if(p->a==e) {//如果括号对得上,就返回1
L->next=p->next;//指向下个结点
free(p);//将刚申请的结点空间free掉
return 1;
} else {//对不上则返回0
return 0;
}
}
这个是我PTA上提交的情况:
- 这道题是我花了不少时间去琢磨的(因为我菜),思路还是很清晰的,只是我操作方面存在不少问题,也希望我的这个代码能给你们提供一些思路,也欢迎大家提出更好的做法。
- 喜欢的朋友能否给个赞?谢谢各位看官老爷了。(第一次写博文)
2020.03.29