棧在數據結構中用處非常大,它就是一種先入後出的結構。可以用數組或者鏈表來完成棧的編程。具體選用哪種得看你的應用場景。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();
}
}
測試結果: