栈相关算法(括号匹配 )

stack
  • 堆栈是一种特殊的线性表,只允许在表的顶 端top进行插入或者删除操作,是一种操作受 限制的线性表。
  • 栈元素服从后进先出原则
    • LIFO——Last In First Out
括号匹配
  • 给定字符串,仅由"()[]{}"六个字符组成。设 计算法,判断该字符串是否有效。
    • 括号必须以正确的顺序配对,如:“()”、“()[]” 是有效的,但“([)]”无效。
算法分析
  • 在考察第i位字符c与前面的括号是否匹配时:
  • 如果c为左括号,开辟缓冲区记录下来,希望c能够 与后面出现的同类型最近右括号匹配。
  • 如果c为右括号,考察它能否与缓冲区中的左括号 匹配。
    • 这个匹配过程,是检查缓冲区最后出现的同类型左括号
    • 即:后进先出——栈
括号匹配算法流程
  • 从前向后扫描字符串:
  • 遇到左括号x,就压栈x;
  • 遇到右括号y:
    • 如果发现栈顶元素x和该括号y匹配,则栈顶元素出栈, 继续判断下一个字符。
    • 如果栈顶元素x和该括号y不匹配,字符串不匹配;
    • 如果栈为空,字符串不匹配;
  • 扫描完成后,如果栈恰好为空,则字符串匹配,否则,字符串不匹配。
代码
bool IsLeftParentheses(char c){
	return (c=='(')||(c=='[')||(c=='{');
}

bool IsMatch(char left,char c){
	if(left == '(')
		return c==')';
	if(left == '[')
		return c==']';
	if(left == '{')
		return c=='}';
}

bool MatchParentheses(const char* p){
	stack<char> s;
	char cur;
	while(*p){
		cur = *p;
		if(IsLeftParentheses(cur))
			s.push(cur)
		else //if(IsRightParentheses(cur))
		{
			if(s.empty() || !IsMatch(s.top,cur))
				return false;
			s.pop();
		}
		p++;
	}
	return s.empty();
}

int _tmain(int argc,_TCHAR* argv[]){
	char* p = "(({})[])[()]"
	bool bMatch = MatchParentheses(p);
	if(bMatch)
		cout << p <<"括号匹配。\n";
	else
		cout << p << "括号不匹配。\n";
	return 0;
}
最长括号匹配
  • 给定字符串,仅包含左括号‘(’和右括号‘)’, 它可能不是括号匹配的,设计算法,找出最 长匹配的括号子串,返回该子串的长度。
  • 如:
    • (():2
    • ()():4
    • ()(()):6
    • (()()):6
算法分析
  • 记起始匹配位置start=-1;最大匹配长度ml=0:
  • 考察第i位字符c:
  • 如果c为左括号,压栈;
  • 如果c为右括号,它一定与栈顶左括号匹配;
  • 如果栈为空,表示没有匹配的左括号,start=i,为下一次可能 的匹配做准备
    • 如果栈不空,出栈(因为和c匹配了);
      • 如果栈为空,i-start即为当前找到的匹配长度,检查i-start是否比 ml更大,使得ml得以更新;
      • 如果栈不空,则当前栈顶元素t是上次匹配的最后位置,检查i-t是否比ml更大,使得ml得以更新。
  • 注:因为入栈的一定是左括号,显然没有必要将它们本身入栈,应该入栈的是该字符在字符串中的索引。
代码实现
int GetLongestParenthese(const char *p)
{
   int size = (int)strlen(p);
   stack<int> s;
   int answer = 0; //最终解
   int start = -1; //左括号的前一个位置
   for (int i = 0; i < size; i++)
   {
       if (p[i] == '(')
       {
           s, push(i);
       }
       else //p[i]==')'
       {
           if (s.empty())
               start = i;
           else
           {
               s.pop();
               if (s.empty())
                   answer = max(answer, i - start);//(()) /(())(i()(()) 
               else
                   answer = max(answer, i - s.top());//(()
           }
       }
   }
   return answer;
}

更多内容请关注微信公众号:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值