数据结构-栈2(括号匹配)

1.普通匹配

表达式括号匹配1

题目描述

假设一个表达式有英文字母(小写)、运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”。表达式长度小于255,左圆括号少于20个。

输入描述

一行表达式。

输出描述

“YES” 或“NO”

样例

  输入

2*(x+y)/(1-x)@

 输出

YES

思路

用栈进行匹配,遇见'('入栈

遇见')'出栈,下溢时做出错处理

若没有出错且栈为空,匹配成功

代码实现

#include<bits/stdc++.h>
using namespace std;
int main(){
    //初始化
    stack<char>s;
    string t;
    int f=1;
    cin>>t;
    //遍历输入字符串所有字符
    for(int i=0;i<t.size();i++){
    	if(t[i]=='@') break;//结束符
    	else if(t[i]=='(') s.push(t[i]);//入栈
    	else if(t[i]==')'){
    		if(s.empty()) {//若为空做出错处理
    			f=0;break;
			}
			else s.pop();//出栈
		}
	}
	if(f&&s.empty()) cout<<"YES";//没有出错且栈为空
	else cout<<"NO";
    return 0;
}

练习一下~

表达式括号匹配2

题目描述

假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序任意,如([]())或[([][])]等为正确的匹配,[(])或([]()或(()))均为错误的匹配。
现在的问题是,要求检验一个给定的表达式中的括弧是否正确匹配?
输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出“OK”,不匹配就输出“Wrong”。

输入描述

输入一行字符(字符个数小于255)。

输出描述

数据匹配就输出“OK”,不匹配就输出“Wrong”。

样例

 输入

[(])

 输出

Wrong

代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    //初始化
    stack<char>s;
    string t;
    cin>>t;
    int f=1;
    for(int i=0;i<t.size();i++){
        //入栈
    	if(t[i]=='[') s.push(t[i]);
    	if(t[i]=='(') s.push(t[i]);
    	if(t[i]==']'){
    		if(s.empty()){//若为空做出错处理
    			f=0;
    			break;
			}
            //出栈至有括号配对
    		while(s.top()!='['){
    			if(s.empty()){//若为空做出错处理
    				f=0;
    				break;
				}
				s.pop();				
			}
			if(s.empty()){//若为空做出错处理
    			f=0;
    			break;
			}
			s.pop();
		}
		if(t[i]==')'){
			if(s.empty()){//若为空做出错处理
    			f=0;
    			break;
			}
            //出栈至有括号配对
    		while(s.top()!='('){
    			if(s.empty()){//若为空做出错处理
    				f=0;
    				break;
				}
				s.pop();				
			}
			if(s.empty()){//若为空做出错处理
    			f=0;
    			break;
			}
			s.pop();
		}
	}
	if(f==1&&s.empty()) cout<<"OK";//没有出错且栈为空
	else cout<<"Wrong";
    return 0;
}

2.运行崩溃调试

表达式括号匹配3

题目描述

给你一串字符,不超过50个字符,可能包括括号、数字、字母、标点符号、空格,你的任务是检查这一串字符中的( ) ,[ ],{ }是否匹配。

输入描述

每次输入一个字符串,字符串长度不超过50

输出描述

如果匹配就输出“yes”,不匹配输出“no”

样例

输入

sin(20+10)

输出 

yes

初试

如果按刚刚的操作去处理,得到如下代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    stack<char>s;
    string t;
    int f=1;
    getline(cin,t);//有空格!!!!
    for(int i=0;i<t.size();i++){
		if(t[i]=='['||t[i]=='('||t[i]=='{') s.push(t[i]);
        if(t[i]==')'){
            while(s.top()!='('){
				if(s.empty()){
					f=0;
                    break;
                }
                s.pop();
            }
            if(s.empty()){
				f=0;
                break;
            }
            s.pop();
        }
        if(t[i]==']'){
            while(s.top()!='['){
				if(s.empty()){
					f=0;
                    break;
                }
                s.pop();
            }
            if(s.empty()){
				f=0;
                break;
            }
            s.pop();
        }
        if(t[i]=='}'){
            while(s.top()!='{'){
				if(s.empty()){
					f=0;
                    break;
                }
                s.pop();
            }
            if(s.empty()){
				f=0;
                break;
            }
            s.pop();
        }
    }
    if(f&&s.empty()) cout<<"yes";
    else cout<<"no";
	return 0;
}

然后……

运行崩溃 (60%)  

为什么会这样?

分析与调试

看这段代码:

while(s.top()!='('){
    if(s.empty()){
	    f=0;
        break;
    }
    s.pop();
 }

while时复杂度提高,所以导致出错

分析:括回左边只要有不匹配的括号,就是无法匹配

所以直接判断左边括号是否匹配即可

经过分析后,上面的代码可以修改成: 

if(s.top()=='(') s.pop();//匹配
else{
    f=0;
    break;//否则无法匹配
}

修改后代码: 

#include<bits/stdc++.h>
using namespace std;
int main(){
    stack<char>s;
    string t;
    int f=1;
    getline(cin,t);//有空格!!!!
    for(int i=0;t[i];i++){
		if(t[i]=='['||t[i]=='('||t[i]=='{') s.push(t[i]);
        if(t[i]==')'){
            if(s.top()=='(') s.pop();//匹配
            else{
                f=0;
                break;//否则无法匹配
            }
        }
        if(t[i]==']'){
            if(s.top()=='[') s.pop();//匹配
            else{
                f=0;
                break;//否则无法匹配
            }
        }
        if(t[i]=='}'){
            if(s.top()=='{') s.pop();//匹配
            else{
                f=0;
                break;//否则无法匹配
            }
        }
    }
    if(f&&s.empty()) cout<<"yes";
    else cout<<"no";
	return 0;
}

呃好像……

运行崩溃 (60%) 

为了进一步防止 运行崩溃 (60%) ,我们可以用数组代替栈,top为头指针

#include<bits/stdc++.h>
using namespace std;
int main(){
    char stack[55];
    char t[55];
    int f=1,top=0;
    fgets(t,55,stdin);
    for(int i=0;t[i];i++){
		if(t[i]=='['||t[i]=='('||t[i]=='{') stack[top++]=t[i];
        if(t[i]==')'){
            if(stack[top-1]=='(') top--;
            else{
                f=0;
                break;
            }
        }
        if(t[i]==']'){
            if(stack[top-1]=='[') top--;
            else{
                f=0;
                break;
            }
        }
        if(t[i]=='}'){
            if(stack[top-1]=='{') top--;
            else{
                f=0;
                break;
            }
        }
    }
    if(f&&top==0) cout<<"yes";
    else cout<<"no";
	return 0;
}

结果:正确 

3.顺序匹配

字符串匹配问题

题目描述

字符串中只含有括号 ()[]<>{} 判断输入的字符串中括号是否匹配。如果括号有互相包含的形式,从内到外必须是 <>()[]{},例如。输入: [()] 输出YES,而输入 ([])([)] 都应该输出 NO

输入描述

文件的第一行为一个整数nn,表示以下有多少个由括好组成的字符串。接下来的nn行,每行都是一个由括号组成的长度不超过255的字符串。

输出描述

在输出文件中有nn行,每行都是YES或NO。

样例

输入 

注:为清晰样例添加了空格

5
{ }{ }< >< >( )( )[ ][ ]
{ { } }{ { } }< < > > < < > > ( ( ) ) ( ( ) ) [ [ ] ] [ [ ] ]
{ { } } { { } } < < > > < < > > ( ( ) ) ( ( ) ) [ [ ] ] [ [ ] ]
{ < > } { [ ] } < < < > > < < > > > ( ( < > ) ) ( ( ) ) [ [ ( < > ) ] ] [ [ ] ]
> < } { { [ ] } < < < > > < < > > > ( ( < > ) ) ( ( ) ) [ [ ( < > ) ] ] [ [ ] ]

输出

YES

YES

YES

YES

NO

基本代码

就是在上一题基础上添了顺序嘛

把顺序先放一边,做其他处理

排序思路与实现

其实很简单,因为只有左括号,只要判断前面的括号嵌套是否正确即可

可以使用整数栈操作

#include<bits/stdc++.h>
using namespace std;
bool stackst(char t[]){
	stack<int>s;	
	for(int i=0;i<strlen(t);i++){
		int num=0;
		switch(t[i]){
			case '<':
				s.push(4);
				break;
			case '(':
				if(s.empty()) s.push(3);
				else{				
					num=s.top();
					if(num>3) return 0;
					s.push(3);					
				} break;							
			case '[':
				if(s.empty()) s.push(2);
				else{
					num=s.top();
					if(num>2) return 0;
					s.push(2);
				} break;			
			case '{':				
				if(s.empty()) s.push(1);
				else{
					num=s.top();
					if(num>1) return 0;
					s.push(1);          							
				} break;
			case '>':
				if(s.empty()) return 0; 
				num=s.top();
           		if(num!=4) return 0;
				s.pop();
				break;
			case ')':
           		if(s.empty()) return 0;
				num=s.top();
				if(num!=3) return 0;
				s.pop();
				break;
			case ']':
				if(s.empty()) return 0;
				num=s.top();
           		if(num!=2) return 0;
				s.pop();
				break;
			case '}':
				if(s.empty()) return 0;
				num=s.top();
           		if(num!=1) return 0;
				s.pop();
				break;
		}										
    }
	if(s.empty()) return 1;
	return 0;
}
int main(){
    int N;
    cin>>N;
    while(N){        
        char t[300];
        cin>>t;
        if(stackst(t)) cout<<"YES"<<'\n';
        else cout<<"NO"<<'\n';
		N--;
    }
    return 0;
}

 

  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值