栈在数据结构中用处非常大,它就是一种先入后出的结构。可以用数组或者链表来完成栈的编程。具体选用哪种得看你的应用场景。Java内存中的栈用来存放已知生命周期和大小的数据,局部变量都存放在栈中。它也是是用来进行方法处理的一个数据区域,一个方法从调用到完成对应了一个栈帧从入栈到出栈的过程。
这篇文章主要说明了栈的一个应用---平衡符号的检测。括号都是成对成对出现的,比如( ),{ },[ ]等。当然括号里面也是可以有括号的,前提是成对出现。如果括号不成对,如
[ ( ]等就说明出错了。我这里就是对三种括号进行检测( ),{ },[ ]。它们的编程过程不难,只要遇到开括号则入栈,遇到闭括号比出栈。字符串读完,如果栈里面还有数据也是错误的。这里还加入了对注释符的处理过程,注释符为 /* */,它是两个符号,并且是连在一起,开符号和闭符号只是顺序不用。注释符号内部的数据不用检测,直接跳过。这里的处理是加了个boolean类型的note变量。note=false说明不在注释符号内,括号正常检测,note=true代表在注释内,只需要检测*符号来结束这个注释。
下面来重点说一下/和*的检测。我的程序是当note=false时先检查/,它只能和*同时出现,如果只有他一个则出错。它不用出栈和入栈,由*来代表。后面的程序是检测*,它的出现同样要检测是否同/在一起。如果遇到的是/* ,则将*入栈,note变为true;如果遇到的是*/ ,则将*出栈,note变为false。最后,每个字符都检查玩之后,判断note是否为false并且栈里面是否还有数据。当note=false且栈里没有数据时则返回true。
我的程序可以进行手都输入和文件的字符串检测。处理的方法是test方法,自己还写了个MyVector类。
代码如下:
---------------------------------------2015/2/5日更新----------------------------
我使用char数组存放括号对象,这种做法可能显得有点笨。对象少的话可以用if直接判断,多的话还是推荐用HashMap,将开括号和闭括号分别存在key和value上面。
import java.io.*;
public class VectorTest
{
//栈的应用:括号的平衡检测
public static void main(String[] args)throws Exception
{
System.out.println("栈的应用:括号的平衡检测(包括注释)\n括号必须成对出现(){}[],或相互嵌套如([]...{[]}),注释是/*XXX*/,注释里面的内容不进行检测");
System.out.println("\n请选择类型:file代表文件,input代表输入,输入其他无效");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String input=br.readLine();
System.out.println("输入的是 "+input);
if(input.equals("input"))
{
System.out.println("请输入字符串,'quit'代表退出程序");
String text=null;;
while(!((text=br.readLine()).equals("quit")))
{
System.out.println("结果:"+test(text));
}
System.out.println("程序结束");
}
else
{
if(input.equals("file"))
{
System.out.println("请输入文件名:");
String text=br.readLine();
File file=new File(text);
if(file.exists())
{
FileReader fr=new FileReader(file);
StringBuilder sb=new StringBuilder();
char[] c=new char[128];
int i;
while((i=fr.read(c))!=-1)
{
sb.append(new String(c));
}
System.out.println("结果是:"+test(sb.toString()));
fr.close();
}
else
System.out.println("文件不存在");
}
}
}
//检测括号使用是否正确{},[],() 数据结构与算法分析P/65
public static boolean test(String s)
{
if(s==null | s.length()<1)
return false;
char[] close=new char[]{'}',']',')'}; //括号的索引是对应的
char[] open=new char[]{'{','[','('};
char[] ch=s.trim().toCharArray();
boolean note=false; //注释标志位,false代表不在注释内
MyVector<Character> my=new MyVector<Character>();
for(int i=0;i<ch.length;i++) //循环每个字符,然后入栈和出栈判断括号是否对应(判断开放括号和封闭括号的索引是否相等e:
{
if(note==false) //说明不在注释符号内,需要每个括号都处理
{
if(ch[i]=='/') //处理'/'符号,因为它总是和'*'连在一起,所以判断它的出现是不是和'*'在一起,不在一起就返回false
{ //出入栈值只对'*'处理
if(i>0&i<ch.length-1)
{
if(ch[i+1]=='*'|ch[i-1]=='*')
continue;
else
return false;
}
else
{
if(i==0)
{
if(ch[i+1]!='*')
return false;
}
else
{
if(ch[i-1]!='*')
return false;
}
}
}
else if(ch[i]==open[0] |ch[i]==open[1]|ch[i]==open[2] |ch[i]=='*')
{
if(ch[i]!='*') //输入的是三个括号中的一个
{
my.push(ch[i]);
System.out.println("入栈:"+ch[i]);
}
else //输入的是'*',则要判断上一个是不是'*',如果是则一起入栈,不是则返回false
{
if(i>0&i<ch.length-1)
{
if(ch[i-1]=='/')
{
my.push(ch[i]);
System.out.println("入栈:"+"/*");
note=true; //开启注释,直到结束注释,中间的都不再出栈和入栈
}
else
return false;
}
else
return false;
}
}
else if(ch[i]==close[0] |ch[i]==close[1]|ch[i]==close[2] )
{
int index=4;
for(int j=0;j<3;j++)
{
if(ch[i]==close[j])
{
index=j;
break;
}
}
if(index<4)
{
if(my.size()==0)
return false;
char c=my.pop();
System.out.println("出栈:"+ch[i]);
int in=4;
for(int j=0;j<3;j++)
{
if(c==open[j])
{
in=j;
break;
}
}
if(index!=in)
return false;
}
}
}
else //在注释内部,遇到'*/'则结束注释
{
if(ch[i]=='*')
{
if(i>0&i<ch.length-1)
{
if(ch[i+1]=='/')
{
char c=my.pop();
System.out.println("出栈:"+"*/");
if(c!='*')
return false;
note=false; //结束注释
}
}
else
return false;
}
}
}
if(note==true| my.size()!=0) //开启了注释却没关闭返回false,入栈了却没出栈也返回false
return false;
else
return true;
}
}
//栈:入栈push,出栈pop。以数组为基础,是在数组的最后进行操作
class MyVector<E>
{
//入栈和出栈都在数组的最后
private int size; //size代表元素的个数
private int minSize=10;
private Object[] element;
public MyVector()
{
size=0;
element=new Object[minSize];
}
public void push(Object o) //入栈
{
ensureCapacity(size+1);
element[size++]=o;
}
public E pop() //出栈
{
if(size>0)
{
Object o=element[size-1];
element[size-1]=null;
size--;
return (E)o;
}
else
return null;
}
public int size()
{
return size;
}
public void clear()
{
element=null;
size=0;
}
public void ensureCapacity(int i)
{
if(i<0 || i<size)
throw new IllegalArgumentException("IllegalArgument:"+i);
else
{
int j=(i*3)/2+1;
if(j<minSize)
j=minSize;
Object[] old=new Object[j];
for(int len=0;len<size;len++)
old[len]=element[len];
element=old;
}
}
@Override
public String toString()
{
StringBuilder sb=new StringBuilder();
sb.append("[");
for(int i=0;i<size;i++)
{
E e=(E)element[i];
sb.append(e);
if(i<(size-1))sb.append(",");
}
return sb.append("]").toString();
}
}
测试结果: