棧的應用---平衡符號的檢測

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

測試結果:


發佈了26 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章