栈:只允许访问一个数据项,数据项遵循先进后出的顺序。栈提供栈top引用,可以通过top引用对表进行pop(),和push()方法。

其中pop()方法弹出栈顶元素,并将栈顶引用向前移动一个。push()方法向堆栈里面推入一个元素并将引用指向当前元素。另外还会提供gettop()方法获取堆栈当前栈顶的元素,但是不更新top位置的引用。实现MyStack的源码如下所示(链表形式实现):

package com.stack.mystack;
import javax.xml.soap.Node;

public class MyStack<T> {
	private int size;
	private Node top;
	
	private class Node{
		public Node prev;//Node对于MyStack是private的,所以Node中的属性可是设置为public,在MyStack都是不可见的
		public T Data;
	}
	
	public MyStack() {
		// TODO Auto-generated constructor stub
		clear();
	}
	
	public void clear(){
		this.size = 0;
		this.top = null;
	}
	
	public int getSize(){
		return this.size;
	}
	
	public T pop(){
		T temp = null;
		if(this.top!=null){
			temp = top.Data;
			size--;
			top = top.prev;
		}
		return temp;
		
	}
	public boolean push(T data){
		boolean flag = false;
		Node temp = new Node();
		temp.Data = data;
		temp.prev = top;
		top = temp;
		size++;
		return flag;
	}
	
	public T gettop(){
		T temp = null;
		if(this.top!=null)
			temp = top.Data;
		return temp;
	}
}

编写测试程序

package com.stack.mystack;

public class stackmain {
	public static void main(String[] args) {
		MyStack<String> myStack = new MyStack<>();
		int i = 0;
		for(i=0; i<10; i++){
			myStack.push(""+i);
		}
		for(i=0; i<10; i++){
			System.out.println(myStack.pop());
		}
	}
}



测试结果显示正确

接下来例举一些Stack的常用的实例。比较典型的有符号匹配,计算逆波兰式,由逆波兰式计算等式的值。首先来看一个最简单的例子,就是括号匹配的例子。编译写代码会有这样的体会,编译器会在你少输入或者多输入括号的时候提示错误,一些不好的编译器甚至提示你整一大段都是错误的。当然我们现在举得例子只是一个简化的版本。假设我们现在只关心(){}和[]并且需要一一对应,比如({)}是错误的,而{()}则是正确的,现在假设输入字符串中除了()[]和{}之外还存在一些其他的字符,现在来验证括号是否匹配。代码如下,这里使用的是上面实现的MyStack类:




import java.io.PushbackInputStream;

public class CheckBracket {
	private static MyStack<Character> stack;
	private static char temp;
	public static void main(String[] args) {
		stack = new MyStack<>();
		boolean flag = true;
		String str = "sd{d[ddad(}p(dd)]}";
		for(int i=0; i<str.length()&&flag; i++){
			char ch = str.charAt(i);
			switch (ch) {
			case '(':
			case '{':
			case '[':
				stack.push(ch);
				break;
			case ')':
				temp = stack.pop();
				if(temp!='('){
					System.out.println("括号不匹配");
					flag = false;
				}
				break;
			case ']':
				temp = stack.pop();
				if(temp!='['){
					System.out.println("括号不匹配");
					flag = false;
				}
				break;
			case '}':
				temp = stack.pop();
				if(temp!='{'){
					System.out.println("括号不匹配");
					flag = false;
				}
				break;
			default:
				break;
			}
		}
		if(stack.pop()==null)
			System.out.println("括号匹配");
	}

}



还有一个例子是计算逆波兰式的值,这里使用的是简单的0-9的整数四则运算,因为这样涉及到的字符串识别四则运算的数据这一步就会比较简单,思想是一样的。复杂数字只要用空格隔开就好了,以下是计算逆波兰式值的代码:

public class ExperValue {
	private static MyStack<Integer> stack;
	private static String exper;
	public static void main(String[] args) {
		exper = "324*+224*-+82/+";
		stack = new MyStack<>();
		char ch;
		Integer num2,num1;
		int a,b;
		for(int i=0; i<exper.length();i++){
			ch = exper.charAt(i);
			if(ch=='#')
				break;
			else if(isDigital(ch))
				stack.push(Integer.parseInt(ch+""));
			else {
				num2 = stack.pop();
				num1 = stack.pop();
				switch (ch) {
				case '+':
					stack.push(num1+num2);
					break;
				case '-':
					stack.push(num1-num2);
					break;
				case '*':
					stack.push(num1*num2);
					break;
				case '/':
					stack.push(num1/num2);
					break;
				default:
					break;
				}
			}
		}
		if(stack!=null)
			System.out.println(stack.pop());
	}
	static boolean isDigital(char ch){
		if(ch>='0'&&ch<='9')
			return true;
		else 
			return false;
	}
}

接下来是实现正常表达式到逆波兰式的转换,这里假设输入的四则混合运算表达式是正常的,并且数据也比较简单,那么可以用下面的方式去实现中序表达式转换成逆波兰式。


import javax.print.DocFlavor.STRING;

public class ChangeExper {
	private String inExper;
	private String outExper;
	private MyStack<String> stack;
	
 	public ChangeExper(){
		this.inExper = "3+2*4+(2-2*4)+8/2";
		this.outExper = new String();
		this.stack = new MyStack<>();
	}
	
	public ChangeExper(String in){
		this.inExper = in;
		this.outExper = new String();
		this.stack = new MyStack<>();
	}
	
	public  String change(){
		String temp;
		for(int i=0; i<inExper.length(); i++ ){
			temp = inExper.substring(i, i+1);
			if(isDigital(temp)){
				this.outExper += temp;
				System.out.println(outExper);
				}
			else{
				switch (temp) {
				case "(":
					stack.push(temp);
					break;
				case "/":
				case "*":
					changeLevel(temp, 2);
					break;
				case "+":
				case "-":
					changeLevel(temp, 1);
					break;
				case ")":
					getall();
					break;
				default:
					break;
				}
			}
		}
		while(stack.getSize()>0){
			outExper += stack.pop();
		}
		return outExper;
	}
	
	public void getall(){
		String top = stack.pop();
		while(!top.equals("(")){
			outExper += top;
			top = stack.pop();
		}
	}
	public void changeLevel(String temp, int level){
		while(stack.getSize()>0){
			String top = stack.pop();
			if(top.equals("(")){
				stack.push(top);
				break;
			}
			else{
				int leveltop = 0;
				if(top.equals("*")||top.equals("/"))
					leveltop = 2;
				else if(top.equals("+")||top.equals("-"))
					leveltop = 1;
				if(leveltop>=level){
					this.outExper += top;
					System.out.println(outExper);
				}
				else{
					stack.push(top);
					break;
				}
			}
		}
		stack.push(temp);
	}
	public boolean isDigital(String temp){
		boolean is = temp.matches("[0-9]+");
		return is;
	}
	
	public void print(){
		System.out.println("before change: "+inExper);
		System.out.println("after change: "+outExper);
		
	}
	
	public static void main(String[] args) {
		ChangeExper changeExper = new ChangeExper();
		changeExper.change();
		changeExper.print();
	}
}