栈:只允许访问一个数据项,数据项遵循先进后出的顺序。栈提供栈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();
}
}