检验括号是否匹配的方法可以用“期待的急迫程度”这个概念来描述。
例如,考虑下列括号序列:
[ ( [ ] [ ] ) ]
1 2 3 4 5 6 7 8
当计算机接受了第一个括号后,它期待着与其匹配的第八个括号的出现,然而等来的却是第二个括号,此时第一个括号“[”只能暂时靠边,而迫切等待与第二个括号相匹配的、第七个括号“)”的出现,类似地,因等来的是第三个括号“[”,其期待匹配的程度较第二个括号更急迫,则第二个括号也只能靠边,让位于第三个括号,显然第二个括号的期待急迫性高于第一个括号;在接受了第四个括号之后,第三个括号的期待得到满足,消解之后,第二个括号的期待匹配就成为当前最急迫的任务了,……依此类推。
很显然,这样的一个处理过程和栈的特点非常吻合,因此,这个问题可以用栈来解决。
解决思路:
1.在算法中设置一个栈,每次读入一个括号;
2.若是右括号,则或者使置于栈顶的最急迫的期待得以消解,此时将栈顶的左括号弹出;或者是不合法的情况,此时将右括号压入;
3.若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性都降低一级;
4.在算法的开始和结束时,栈应该为空。
代码1:
Stack是一个已实现的栈,可使用的相关类型和函数:
typedef char SElemType; // 栈Stack的元素类型
Status InitStack(Stack &s);
Status Push(Stack &s, SElemType e);
Status Pop(Stack &s, SElemType &e);
Status StackEmpty(Stack s);
Status GetTop(Stack s, SElemType &e);
1 Status MatchCheck(SqList exp) 2 /* 顺序表exp表示表达式; */ 3 /* 若exp中的括号配对,则返回TRUE,否则返回FALSE */ 4 { 5 Stack s; 6 char e; 7 8 //逐个读入括号 9 for(int i=0;i<exp.length;i++) 10 { 11 if(exp.elem[i]=='('||exp.elem[i]=='{'||exp.elem[i]=='[')//若遇左括号,则直接入栈 12 { 13 Push(s,exp.elem[i]); 14 } 15 else if(exp.elem[i]==')')//若遇右圆括号,则尝试匹配栈顶括号 16 { 17 if(GetTop(s,e)) 18 { 19 if(e=='(')//匹配成功,左圆括号出栈 20 { 21 Pop(s,e); 22 } 23 else//匹配不成功,右圆括号入栈 24 { 25 Push(s,exp.elem[i]); 26 } 27 } 28 else//栈为空,则将右括号入栈 29 { 30 Push(s,exp.elem[i]); 31 } 32 } 33 else if(exp.elem[i]=='}')//若遇右花括号,则尝试匹配栈顶括号 34 { 35 if(GetTop(s,e)) 36 { 37 if(e=='{')//匹配成功,左花括号出栈 38 { 39 Pop(s,e); 40 } 41 else//匹配不成功,右花括号入栈 42 { 43 Push(s,exp.elem[i]); 44 } 45 } 46 else 47 { 48 Push(s,exp.elem[i]); 49 } 50 } 51 else if(exp.elem[i]==']')//若遇右方括号,则尝试匹配栈顶括号 52 { 53 if(GetTop(s,e)) 54 { 55 if(e=='[')//匹配成功,左方括号出栈 56 { 57 Pop(s,e); 58 } 59 else//匹配不成功,右方括号入栈 60 { 61 Push(s,exp.elem[i]); 62 } 63 } 64 else 65 { 66 Push(s,exp.elem[i]); 67 } 68 } 69 } 70 if(StackEmpty(s))//当所有括号匹配成功时,栈应为空 71 { 72 return TRUE; 73 } 74 else 75 { 76 return FALSE; 77 } 78 }
完整的C程序,该算法的时间复杂性为O(n),其中n为输入串的长度:
1 #include "stdio.h"
2 #include "string.h"
3 #include "stdlib.h"
4
5
6 #define StackSize 100 //假定预分配的栈空间最多为100个元素
7 #define MaxLength 100 //最大的字符串长度
8
9 typedef int DataType; //假定栈元素的数据类型为整数
10 typedef struct
11 {
12 DataType data[StackSize];
13 int top;
14 }SeqStack;
15
16 void Initial(SeqStack *S);
17 int IsEmpty(SeqStack *S);
18 int IsFull(SeqStack *S);
19 void Push(SeqStack *S, DataType x);
20 DataType Pop(SeqStack *S);
21 DataType Top(SeqStack *S);
22 void PrintMatchedPairs(char *expr);
23
24
25 void main(void)
26 {
27 char expr[MaxLength];
28 printf("请输入符号个数小于%d的表达式:\n",MaxLength);
29
30 gets(expr);
31
32 printf("括号对是:\n");
33
34 PrintMatchedPairs(expr);
35
36 return;
37 }
38
39 //置栈空
40 void Initial(SeqStack *S)
41 {
42 S -> top = -1;
43 }
44
45 //判断栈是否空
46 int IsEmpty(SeqStack *S)
47 {
48 return S -> top == -1;
49 }
50
51 //判断栈是否满
52 int IsFull(SeqStack *S)
53 {
54 return S -> top == StackSize -1;
55 }
56
57 //进栈
58 void Push(SeqStack *S, DataType x)
59 {
60 if(IsFull(S))
61 {
62 printf("栈上溢!");
63 exit(1);
64 }
65
66 S -> data[++ S -> top] = x;
67
68 return;
69 }
70
71 //出栈
72 DataType Pop(SeqStack *S)
73 {
74 if(IsEmpty(S))
75 {
76 printf("栈为空!");
77 return -1;
78 }
79
80 return S -> data[S -> top--]; //栈顶指针加1后将x入栈
81 }
82
83 //取栈顶元素
84 DataType Top(SeqStack *S)
85 {
86 if(IsEmpty(S))
87 {
88 printf("栈为空!");
89 exit(1);
90 }
91
92 return S -> data[S -> top];
93 }
94
95 //括号匹配
96 void PrintMatchedPairs(char *expr)
97 {
98 SeqStack S;
99 int i , j , length = strlen(expr);
100
101 Initial(&S);
102
103 for(i = 1 ; i <= length ; i++)
104 {
105 if(expr[i - 1] == '(')
106 {
107 Push(&S,i);
108 }
109 else if(expr[i - 1] == ')')
110 {
111 j = Pop(&S);
112 if(j == -1)
113 {
114 printf("没有对应第%d个右括号的左括号\n", i);
115 }
116 else
117 {
118 printf("%d %d\n",i,j);
119 }
120 }
121 }
122
123 while(!IsEmpty(&S))
124 {
125 j = Pop(&S);
126 printf("没有对应第%d个左括号的右括号\n", j);
127 }
128 }
代码3:算法:检测表达式中的字符,若是左括号就入栈,如果是右括号就出栈一个元素与其配对,配对成功则继续访问下一个字符,否则退出。出现非括号字符则跳过。
- #include <stdio.h>
- #include <malloc.h> //malloc,realloc
- #include <math.h> //含有overflow
- #include <process.h> //exit()
- #define S_SIZE 100 //栈的空间大小
- #define STACKINCREAMENT 10//增加空间
- struct SqStack{
- int *base; //栈底
- int *top; //栈顶
- int stacksize; //栈当前的存储空间
- };
- void main()
- {//子函数声明
- void InitStack(SqStack &S);//初始化空栈
- int StackEmpty(SqStack S);//判空
- void push(SqStack &S,int e);//进栈
- void pop(SqStack &S,int &e);//出栈
- //主函数开始
- SqStack s;//初始化空栈
- InitStack(s);
- char ch[100],*p;int e;
- p=ch;
- printf("输一个含义有()[]{}的括号表达式:\n");
- gets(ch);
- while(*p)
- {
- switch (*p)
- {
- case '{':
- case '[':
- case '(': push(s,*p++);break;//只要是左括号就入栈
- case '}':
- case ']':
- case ')':pop(s,e);
- if ((e=='{' && *p=='}') ||(e=='[' && *p==']') || (e=='(' && *p==')'))
- p++;
- else
- {printf("括号不匹配!");exit(OVERFLOW);}
- break;
- default :p++;//其他字符就后移
- }
- }
- if (StackEmpty(s))
- printf("括号匹配成功");
- else
- printf("缺少右括号!");
- printf("\n");
- }
- void InitStack(SqStack &S)
- {S.base=(int *)malloc(S_SIZE*sizeof(int));
- S.stacksize=S_SIZE;
- S.top=S.base;//初始化空栈
- }
- int StackEmpty(SqStack S)
- {
- if(S.base==S.top)
- return 1;
- else
- return 0;
- }
- void push(SqStack &S,int e)
- {//进栈
- if(S.top-S.base>=S.stacksize)
- {S.base=(int *)realloc(S.base,(S.stacksize+STACKINCREAMENT)*sizeof(int));
- S.top=S.base+S.stacksize;
- S.stacksize+=STACKINCREAMENT;}
- *(S.top)=e;
- S.top++;
- }
- void pop(SqStack &S,int &e)
- {//出栈
- if(S.base!=S.top)
- {S.top--;
- e=*S.top;}
- }