问题说明:

假设数学表达式中允许包含两种括号:圆括号“()”和方括号“[]”,嵌套顺序任意。

正确的嵌套模式:( [ ] ( ) )、[ ( [ ] [ ] ) ]

正确的表达式例:(a+b)[c*(d-e)]

错误的嵌套模式:[ ( ] )、( ( ) ]

比如,在处理表达式(A)时

(A)  4+(2+8)*[5/(9-7)]

有以下步骤:

(1)检测到第一个括号“(”;

(2)检测到第二个括号“)”,说明子表达式 “4+(2+8)” 已完成匹配;

(3)检测到第三个括号“[”;

(4)检测到第四个括号“(”,与(3)中的括号不匹配,但由于同是左括号,可以继续匹配;

(5)检测到第五个括号“)”,由括号的作用可知,后来的括号比先来的括号优先级高,因此与(4)中括号匹配;

(6)检测到第六个括号“]”,由于原来优先级更高的括号已完成,因此与(3)中括号匹配。至此所有括号匹配完成。

解决方案:

可以看出,匹配成功的条件很简单:每一个检测到的括号与已检测到的优先级最高的括号都匹配。

匹配失败的条件:

(1)检测到与已检测到的优先级最高的括号不匹配的括号;

(2)扫描完整个表达式,还是有已检测到的括号没有完成匹配;

由于栈具有“先进后出”的特点,能很好地表现优先级这个性质,因此可以用栈来存储已经检测到的括号。

以(A)为例:

有以下步骤:

(1)检测到第一个括号“(”,进栈;

(2)检测到第二个括号“)”,进栈。子表达式 “4+(2+8)” 完成匹配,匹配的括号都出栈;

(3)检测到第三个括号“[”,进栈;

(4)检测到第四个括号“(”,进栈。与(3)中的括号不匹配,但由于同是左括号,可以继续匹配;

(5)检测到第五个括号“)”,进栈。由括号的作用可知,后来的括号比先来的括号优先级高,因此与(4)中括号匹配,匹配的括号都出栈;

(6)检测到第六个括号“]”,进栈。由于原来优先级更高的括号已完成,因此与(3)中括号匹配。匹配的括号都出栈,至此所有括号匹配完成。

需要注意的是,第一个括号进栈时,没有比较对象,因此需要特别处理。

判断函数 judge () 如下:

  1. 1 Status judge(Stack *S)
  2. 2 {
  3. 3 //进行表达式的输入和判断
  4. 4 SElemType *p;
  5. 5 char n;
  6. 6
  7. 7 scanf("%c",&n); //第一个括号的检测
  8. 8 while(n!='(' && n!='[') //忽略数字等其他符号,直到输入括号
  9. 9 {
  10. 10 if(n==')' || n==']' || n=='#') return FALSE; //若为')'或']',则表明不匹配。'#'用于结束输入
  11. 11 scanf("%c",&n);
  12. 12 }
  13. 13
  14. 14 if(n=='(' || n=='[') Push(S,n); //检测到左括号,进栈
  15. 15 scanf("%c",&n);
  16. 16 while(n!='#') //'#'用于结束输入
  17. 17 {
  18. 18 if(n=='(' || n==')' || n=='[' || n==']')
  19. 19 {
  20. 20 p=S->top;
  21. 21 Push(S,n);
  22. 22 if(*(p-1)=='(') //与前一个括号比较
  23. 23 {
  24. 24 if(*p==')')
  25. 25 {
  26. 26 printf("%c\n",Pop(S));
  27. 27 printf("%c\n",Pop(S));
  28. 28 }
  29. 29 else if(*p==']') return FALSE;
  30. 30 }
  31. 31 else if(*(p-1)=='[')
  32. 32 {
  33. 33 if(*p==']')
  34. 34 {
  35. 35 printf("%c\n",Pop(S));
  36. 36 printf("%c\n",Pop(S));
  37. 37 }
  38. 38 else if(*p==')') return FALSE;
  39. 39 }
  40. 40 }
  41. 41 scanf("%c",&n);
  42. 42 }
  43. 43 if(S->top==S->base) return TRUE; //栈内没有元素时,说明匹配
  44. 44 else return FALSE;
  45. 45 }

源代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define INIT_SIZE 10
  4. #define INCREMENT 5
  5.  
  6. #define OVERFLOW -2
  7. #define FALSE 0
  8. #define OK 1
  9. #define TRUE 1
  10. #define ERROR 0
  11.  
  12. typedef char SElemType;
  13. typedef int Status;
  14. typedef struct stack{
  15. SElemType *base;
  16. SElemType *top;
  17. int stacksize;
  18. }Stack;
  19.  
  20. Status InitStack(Stack *S)
  21. {
  22. //初始化栈
  23. S->base=(SElemType *)malloc(INIT_SIZE*sizeof(SElemType));
  24. if(!S->base) exit(OVERFLOW);
  25. S->top=S->base;
  26. S->stacksize=INIT_SIZE;
  27. return OK;
  28. }
  29.  
  30. Status Push(Stack *S,char e)
  31. {
  32. //入栈
  33. if(S->top-S->base>=S->stacksize){ //栈满,重新分配内存
  34. S->base=(SElemType *)realloc(S->base,(INIT_SIZE+INCREMENT)*sizeof(SElemType));
  35. if(!S->base) exit(OVERFLOW);
  36. S->top=S->base+S->stacksize;
  37. S->stacksize+=INCREMENT;
  38. }
  39. *S->top++=e;
  40. return OK;
  41. }
  42.  
  43. char Pop(Stack *S)
  44. {
  45. //出栈
  46. char e;
  47.  
  48. if(S->top==S->base) return ERROR; //栈空,出错
  49. e=*(--S->top);
  50. return e;
  51. }
  52.  
  53. Status judge(Stack *S)
  54. {
  55. //进行表达式的输入和判断
  56. SElemType *p;
  57. char n;
  58.  
  59. scanf("%c",&n); //第一个括号的检测
  60. while(n!='(' && n!='[') //忽略数字等其他符号,直到输入括号
  61. {
  62. if(n==')' || n==']' || n=='#') return FALSE; //若为')'或']',则表明不匹配。'#'用于结束输入
  63. scanf("%c",&n);
  64. }
  65.  
  66. if(n=='(' || n=='[') Push(S,n); //检测到左括号,进栈
  67. scanf("%c",&n);
  68. while(n!='#') //'#'用于结束输入
  69. {
  70. if(n=='(' || n==')' || n=='[' || n==']')
  71. {
  72. p=S->top;
  73. Push(S,n);
  74. if(*(p-1)=='(') //与前一个括号比较
  75. {
  76. if(*p==')')
  77. {
  78. printf("%c\n",Pop(S));
  79. printf("%c\n",Pop(S));
  80. }
  81. else if(*p==']') return FALSE;
  82. }
  83. else if(*(p-1)=='[')
  84. {
  85. if(*p==']')
  86. {
  87. printf("%c\n",Pop(S));
  88. printf("%c\n",Pop(S));
  89. }
  90. else if(*p==')') return FALSE;
  91. }
  92. }
  93. scanf("%c",&n);
  94. }
  95. if(S->top==S->base) return TRUE; //栈内没有元素时,说明匹配
  96. else return FALSE;
  97. }
  98.  
  99. int main()
  100. {
  101. Stack Sta;
  102. Stack *S=&Sta;
  103.  
  104. printf("INITIALIZING...\n");
  105. if(InitStack(S)) printf("DONE!\n");
  106.  
  107. printf("enter an expression(stop by '#'):\n");
  108. if(judge(S)==1) printf("It's True!");
  109. else printf("It's False\n");
  110.  
  111. return 0;
  112. }

source

栈的应用:表达式括号匹配检测(C)的更多相关文章

  1. luoguP1739 表达式括号匹配 x

    P1739 表达式括号匹配 题目描述 假设一个表达式有英文字母(小写).运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹 ...

  2. C++括号匹配检测(用栈)

    输入一串括号,包括圆括号和方括号,()[],判断是否匹配,即([]())或[([][])]为匹配的正确的格式,[(])或([())为不匹配的格式. #include<iostream> # ...

  3. java:数据结构(二)栈的应用(括号匹配)

    一.什么是括号匹配: 括号匹配就是利用计算机辨别表达式里面的括号是否书写成功 例如: {()((a)) }这就是一个正确 (()()   这就是一个错误的 二.括号匹配的算法: 众所周知,括号分为花括 ...

  4. 洛谷 P1739 表达式括号匹配

    题目链接https://www.luogu.org/problemnew/show/P1739 题目描述 假设一个表达式有英文字母(小写).运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为 ...

  5. P1739_表达式括号匹配(JAVA语言)

    思路:刚开始想用stack,遇到'('就push,遇到')'就pop,后来发现其实我们只需要用到栈里'('的个数,所以我们用一个变量统计'('的个数就好啦~ 题目描述 假设一个表达式有英文字母(小写) ...

  6. C++学习(三十一)(C语言部分)之 栈和队列(括号匹配示例)

    括号匹配测试代码笔记如下: #include<stdio.h> #include<string.h> #include <stdlib.h> #define SIZ ...

  7. python栈--字符串反转,括号匹配

    栈的实现: # 定义一个栈类 class Stack(): # 栈的初始化 def __init__(self): self.items = [] # 判断栈是否为空,为空返回True def isE ...

  8. java版括号匹配检测

    做一个空栈,读入字符直到结尾.如果读入一个封闭符号,空栈时报错;非空时弹出栈尾字符,如果不匹配则报错.否则读入为开放字符,压入栈中.最后如果栈空,返回true. 其中用到MyStack类,详情请见 p ...

  9. (栈 注意格式)P1739 表达式括号匹配 洛谷

    题目描述 假设一个表达式有英文字母(小写).运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”:否则返 ...

随机推荐

  1. Camtasia快捷键大全

    Camtasia是一款专业屏幕录制软件,它能在任何颜色模式下轻松地记录屏幕动作,另外它还具有即时播放和编辑压缩的功能.在生活上应用范围相当的广泛.在实际运用中如果能了解到相关的快捷键知识,相信是一定程 ...

  2. 在FL Studio中有序地处理人声的混音轨道

    关于人声处理的技巧,我们在以前也有讲到很多,当然在以后也会有新的人声处理技巧课程,这是在音乐后期制作中无法避免的一个环节,在制作许多流行音乐时都会用到,今天先为大家讲解一下在FL Studio中更有序 ...

  3. 「LOJ #6500」「雅礼集训 2018 Day2」操作

    description LOJ 6500 solution 根据常有套路,容易想到将区间差分转化为异或数组上的单点修改,即令\(b_i=a_i \ xor\ a_{i-1}\), 那么将\([l,l+ ...

  4. jQuery 第三章 CSS操作

    .css() .attr() .prop() .css() 参数填法:如下所示 ↓  可填px 可不填,注意点:background-color  这类属性,需要填成 小驼峰式  background ...

  5. leetcode 108 和leetcode 109

    //感想:有时候啊,对于一道题目,如果知道那个点在哪,就会非常简单,比如说这两题,将有序的数组转换为二叉搜索树, 有几个点: 1.二叉搜索树:对于某个节点,它的左节点小于它,它的右节点大于它,这是二叉 ...

  6. 我给 Apache 顶级项目提了个 Bug

    这篇文章记录了给 Apache 顶级项目 - 分库分表中间件 ShardingSphere 提交 Bug 的历程. 说实话,这是一次比较曲折的 Bug 跟踪之旅.10月28日,我们在 GitHub 上 ...

  7. L-Rui

    <!DOCTYPE html> <head> <meta charset="UTF-8"> <link rel="shortcu ...

  8. 2017-2018 ACM-ICPC Latin American Regional Programming Contest J - Jumping frog 题解(gcd)

    题目链接 题目大意 一只青蛙在长度为N的字符串上跳跃,"R"可以跳上去,"P"不可以跳上去. 字符串是环形的,N-1和0相连. 青蛙的跳跃距离K的取值范围是[1 ...

  9. Java基础教程——BigDecimal类

    BigDecimal类 float.double类型的数字在计算的时候,容易发生精度丢失. 使用java.math.BigDecimal类可以解决此类问题. 前面讲过Math类,现在的BigDecim ...

  10. 日期选择组件(DatePicker)的实现

    一.效果图 日期选择组件大概长这样: 从效果图可以看出,日期选择组件由两部分组成:日历表格和顶部操作栏. 二.日历表格 日期选择组件的核心主体是日历表格: 可以将日历表格表示成一个7️*的二维数组,数 ...