堆栈的应用1:括号匹配算法
括号匹配问题
假设算术表达式中包含圆括号,方括号,和花括号三种类型。使用栈数据结构编写一个算法判断表达式中括号是否正确匹配,并设计一个主函数测试。
比如:{a+[b+(c*a)/(d-e)]} 正确
([a+b)-(c*e)]+{a+b} 错误
对于表达式中的括号是否匹配,不能仅仅通过统计左括号'('出现的次数和右括号')'出现的次数是否相等来实现,“a*)b+c(”这样的表达式中的括号显然是不匹配的。检验括号是否匹配最常见的方法是借助于栈这种数据结构,从左到右逐个字符扫描表达式,碰到左括号"("则压入栈中(push),碰到右括号")"则弹出栈顶元素(pop)如果栈为空,则匹配失败。字符串扫描完成后,如果栈为空,则匹配成功,否则匹配失败。
//-------------------------------------------------------------在这里虽然Java给出了Stack的类但是还是自定义
//下面是一个stack接口的定义
1 //栈接口
2 public interface Stack {
3
4 // 入栈
5 public void push(Object obj) throws Exception;
6
7 // 出栈
8 public Object pop() throws Exception;
9
10 // 获得栈顶元素
11 public Object getTop() throws Exception;
12
13 // 判断栈是否为空
14 public boolean isEmpty();
15 }
Stack interface
//顺序栈的具体实现,通过数组实现
1 //顺序栈
2
3 public class SequenceStack implements Stack {
4
5 Object[] stack; // 对象数组
6 final int defaultSize = 10; // 默认长度
7 int top;// 栈顶位置
8 int maxSize;// 最大长度
9
10 public SequenceStack() {
11 // 默认方法初始化
12 init(defaultSize);
13 }
14
15 // 显示调用方法初始化
16 public SequenceStack(int size) {
17 // 根据用户传入的参数进行初始化
18 init(size);
19 }
20
21 // 初始化方法
22 private void init(int size) {
23 this.maxSize = size;
24 top = 0;
25 stack = new Object[size];
26 }
27
28 // 入栈操作
29 @Override
30 public void push(Object obj) throws Exception {
31 // TODO Auto-generated method stub
32 // 判断栈是否已满
33 if (top == maxSize) {
34 throw new Exception("堆栈已满");
35 }
36 // 入栈
37 stack[top] = obj;
38 top++;
39 }
40
41 // 出栈
42 @Override
43 public Object pop() throws Exception {
44 // TODO Auto-generated method stub
45 // 判断栈是否为空
46 if (isEmpty()) {
47 throw new Exception("堆栈为空!");
48 }
49 // 因为在入栈之后默认将top值进行了++所以导致不指示当前位置
50 top--;
51 return stack[top];
52 }
53
54 // 获得栈顶元素
55 @Override
56 public Object getTop() throws Exception {
57 // TODO Auto-generated method stub
58 if (isEmpty()) {
59 throw new Exception("堆栈为空!!");
60 }
61 // 单纯获得栈顶元素
62 return stack[top - 1];
63 }
64
65 @Override
66 public boolean isEmpty() {
67 // TODO Auto-generated method stub
68 return top == 0;
69 }
70
71 }
View Code
//获得栈的具体使用操作后,下面使用堆栈完成对括号匹配算法的使用:
1 import java.util.Scanner;
2
3 //平衡符号算好,检查算数式的括号是否是正确的,小括号,中括号,大括号
4 public class Test {
5 public static void main(String[] args) throws Exception {
6 String str = "{a + [b + ( c * a ) / ( d * e)]}";
7 String str2 = "{a+(a*B)+[a-1] + }";
8
9 signCheck(str2);
10 }
11
12 // 字符串检查
13 public static void signCheck(String str) throws Exception {
14 SequenceStack stack = new SequenceStack();
15 String[] arr = expToStringArray(str);
16 for (int i = 0; i < arr.length; i++) {
17 // 如果数组中有这三种左括号元素那么直接进行入栈操作
18 if (arr[i].equals("(") || arr[i].equals("[") || arr[i].equals("{")) {
19 stack.push(arr[i]);
20 }
21
22 else if (arr[i].equals(")") && !stack.isEmpty()
23 && stack.getTop().equals("(")) {
24 // 上面的if判断主要是当我们遇到右括号时,发现当前位于栈顶的是左括号,那么此时可以出栈了
25 stack.pop();
26 }
27
28 else if (arr[i].equals(")") && !stack.isEmpty()
29 && !stack.getTop().equals("(")) {
30
31 System.out.println("左右括号匹配次序不成功");
32 return;
33 }
34 // 遇到中括号时
35 else if (arr[i].equals("]") && !stack.isEmpty()
36 && stack.getTop().equals("[")) {
37 // 上面的if判断主要是当我们遇到右括号时,发现当前位于栈顶的是左括号,那么此时可以出栈了
38 stack.pop();
39 }
40
41 else if (arr[i].equals("]") && !stack.isEmpty()
42 && !stack.getTop().equals("[")) {
43
44 System.out.println("左右括号匹配次序不成功");
45 return;
46 }
47
48 // 大括号匹配
49 else if (arr[i].equals("}") && !stack.isEmpty()
50 && stack.getTop().equals("{")) {
51 // 上面的if判断主要是当我们遇到右括号时,发现当前位于栈顶的是左括号,那么此时可以出栈了
52 stack.pop();
53 }
54
55 else if (arr[i].equals("}") && !stack.isEmpty()
56 && !stack.getTop().equals("{")) {
57
58 System.out.println("左右括号匹配次序不成功");
59 return;
60 }
61
62 // 右括号多于左括号的情况
63 else if (arr[i].equals(")") || arr[i].equals("]")
64 || arr[i].equals("}") && stack.isEmpty()) {
65 System.out.println("右括号多于左括号");
66 return;
67 }
68 }
69 // 经历完一趟循环后如果堆栈不为空,那么左括号就多了
70 if (!stack.isEmpty()) {
71 System.out.println("左括号多于右括号");
72 } else {
73 System.out.println("匹配正确");
74 }
75
76 }
77
78 // 字符串转为字符串数组
79 public static String[] expToStringArray(String exp) {
80 // 字符串数组长度
81 int n = exp.length();
82 String[] arr = new String[n];
83 for (int i = 0; i < n; i++) {
84 arr[i] = exp.substring(i, i + 1);
85 }
86
87 return arr;
88 }
89 }