栈的应用---平衡符号的检测

     栈在数据结构中用处非常大,它就是一种先入后出的结构。可以用数组或者链表来完成栈的编程。具体选用哪种得看你的应用场景。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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章