如何用递归实现简单的单括号匹配

1.什么是括号匹配?

直觉上是这个形式的:((3+5)*8+9)+(5/3-3)

对于计算机而言其主要特征是:

(1)在从左向右读取括号的过程中,左括号数量总是大于等于右括号

(2)同样,从右向左读取时,右括号数量总是大于等于左括号

(3)读取结束时,左右括号相等。

2.算法雏形

(1)我们需要处理掉表达式左侧及右侧的非括号内容,找到左侧和右侧的第一个括号元素。

(2)于是我们可以从第一个左括号开始,对左右括号分别计数,左括号等于右括号时即读取到一个括号复合体(当然可以直接读至表达式的末尾,但为了将一个括号复合体单独提取出,以便对其进行内)容读取,所以我们在此时结束,并对此括号复合体内部,及右边剩余表达式进行相同处理),将其分离开,并对其括号内部及右侧剩余表达式进行相同处理。

以上,便有了递归算法的思想。

3.代码实现

/ /           trim()函数处理掉表达式(此处表达式我们用char[]来表示)左侧及右侧的非括号元素,并保留各自括号元素的引用

void trim(const char exp[],int &lo,int& hi){

  while(  (lo<=hi)  &&  (exp[lo]!= '('  )  &&(exp[lo]!=  ')'  )   lo++;

  while(  (lo<=hi)  &&  (exp[hi]!= '('  )  &&(exp[hi]!=  ')'  )   hi--;

//无括号时lo会大于hi;仅有一个括号时,lo和hi势必有一个此时对应的括号形式错误(如lo本应左括号,却对应了右括号),可以交由后面的函数进行检验

}

 

/ /  divide()函数负责括号复合体的切分工作

int divide(const char exp[],int lo, int hi){

  int mi=lo;int crc=1;          //记录左括号与右括号之差,显然当差值等于零时即得到一个括号复合体

  while( (0<crc)&&(++mi<hi) ){

    if(      exp[mi]=  '('      )      crc++;    if  (  exp[mi]=  ')'  )  crc--;}

   if(crc>1)return  mi+1;      //处理左括号过多情况。 

   return mi; 

  

/ /  paren()函数负责将以上操作整合,并实现迭代

bool paren(const char exp[], int lo, int hi) {
  trim(exp, lo, hi); if (lo > hi)return true;                //对应无括号,返回true
  if (  (exp[lo] == ')'  )   ||    (exp[hi] == '(')   )  return false;    //括号匹配错误时,返回false
  int mi = divide(exp, lo, hi);                  //mi应指向右括号
  if (mi > hi)    return false;                //此时左括号过多,返回false
  return paren(exp, lo + 1, mi - 1) && paren(exp, mi + 1, hi);    //对括号内部及右侧剩余表达式递归,当且仅当所有括号匹配时返回true

}  

 

posted @ 2023-04-13 22:59  南极沙丁鱼  阅读(198)  评论(0)    收藏  举报