代码见:点击打开链接,高抬贵手赞一个呗,,,,,
1.引入
栈,先进先出(First in first out),它是一种只能在表尾进行插入和删除的特殊线性表。
2.原理
栈,作为一种特殊的线性表,它的表尾叫做栈顶(top),表头叫做栈底(bottom)。下面是栈的示意图:
栈的基本操作有插入、删除、判空、取栈顶元素。
栈的数据结构如下:
Stack说明:
count:表示当前栈的大小(元素的个数)
top:栈顶元素
push(T t):向栈中添加元素
pop():弹出栈顶运算
T getTop():获取栈顶元素(不删除栈顶元素)
boolean isEmpty():判断栈是否为空
int getLength():返回栈的大小(也就是count)
String display():打印出栈的内容
Node说明:
T data:存储的数据
T next:指向下一个元素的指针(应用)
3.代码实现
Node.java
package stack;
public class Node<T> {
private T t;
private Node<T> next;
public Node()
{
t=null;
next=null;
}
public Node(T t,Node<T> next)
{
this.next=next;
this.t=t;
}
public Node(T t)
{
this.t=t;
this.next=null;
}
protected T getT() {
return t;
}
protected void setT(T t) {
this.t = t;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
}
Stack.java
package stack;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Stack<T> implements Serializable {
private int count = 0;
// private Node<T> bottom=new Node<T>();
private Node<T> top = new Node<T>();
/**
* 深拷贝
*
* @auther 冯利
* @version 创建时间:2018年5月3日 上午9:41:32
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Object deepCloned() throws IOException, ClassNotFoundException {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
public void push(T t) throws ClassNotFoundException, IOException {
Node<T> n = new Node<T>(t);
Node<T> temp=top;
n.setNext(temp);
top = n;
count++;
}
public T pop() {
T temp = top.getT();
top = top.getNext();
count--;
return temp;
}
public boolean isEmpty() {
if (count == 0) {
return true;
}
else
{
return false;
}
}
public T getTop() {
return top.getT();
}
public int getLength() {
return count;
}
public String display() {
String temp="";
Node<T> temp2=top;
for(int i=count;i>0;--i)
{
temp+=temp2.getT()+",";
temp2=temp2.getNext();
}
System.out.println(temp);
return temp;
}
}
4.实例解决--表达式求值
4.1问题描述
表达式求值,是程序设计中语言编译中的一个最基本的问题。常用的解决方式是“算符优先法”。下面举一个例子:
4+2*3-10/5=4+6-10/5=10-10/5=10-2=8;
算符优先法的规则:
- 先乘除,后加减
- 从左算都右
- 先括号内,后括号外
4.2设计思路
算法的基本思想是:
- 首先让操作数栈(opnd)为空栈,表达式起始符“#”为运算符栈的栈底元素;
- 依次读入表达式中每个字符,或是操作数则进操作数栈(opnd),或是操作符则和操作符栈(optr)的栈顶运算符比较优先权后做相应的处理,直至整个表达式求值完毕(即optr栈的栈顶元素和当前读入的字符均为“#”)。
算符的流程图如下:
表达式求值的uml图:
expression:表达式(以“#”结尾)
priorityTable:算符优先表
index:表示下一个待处理的操作符或操组数的下标
evaluateExpression():计算表达式
operate(a,theta,b):运算
getNext():获取下一个操作符或操组数
PriorityTable(String path)://从path下面构建一个PriorityTable对象
col,raw:表示操作符
priority:表示操作符之间的优先级
4.3代码及运行结果
Expression.java
package stack;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Expression {
private String expression = "";
private int index = 0;// 表示待处理的操作符或操组数下标
private PriorityTable pt;
public Expression(String expression) throws FileNotFoundException {
this.expression = expression+"#";//在表达式后面加一个“#”表示结束
pt = new PriorityTable("src/priorityTable");
}
public double evaluateExpression() throws ClassNotFoundException, IOException {
Stack<String> optr = new Stack<String>();
Stack<Double> opnd = new Stack<Double>();
optr.push("#");
int index = 0;
String c = getNext();
while (!(c.equals("#") && optr.getTop().equals("#"))) {
if (!pt.isOptr(c)) {
opnd.push(Double.valueOf(c));
c = getNext();
} else {
String priority = pt.queryPriority(optr.getTop(), c);
if (priority.equals("<")) {
optr.push(c);
c = getNext();
continue;
} else if (priority.equals("=")) {
optr.pop();
c = getNext();
continue;
} else {
String theta = optr.pop();
double b = opnd.pop();
double a = opnd.pop();
opnd.push(operate(a, theta, b));
continue;
}
}
}
return opnd.getTop();
}
/**
* 运算
* @auther 冯利
* @version 创建时间:2018年5月10日 上午8:45:59
* @param a
* @param theta
* @param b
* @return
*/
public double operate(double a, String theta, double b) {
if (theta.equals("+")) {
return a + b;
}
if (theta.equals("-")) {
return a - b;
}
if (theta.equals("*")) {
return a * b;
}
if (theta.equals("/")) {
return a / b;
}
return -1;
}
/**
* 获取表达式的下一个操作符或操作数
*
* @auther 冯利
* @version 创建时间:2018年5月9日 下午9:15:57
* @return
*/
public String getNext() {
String c = expression.charAt(index) + "";
try
{
Double.parseDouble(c);
while(true)
{
try{
if(index>=expression.length()-1)
{
return c;
}
Double.parseDouble(expression.charAt(++index)+"");
c=c+expression.charAt(index)+"";
}
catch(NumberFormatException e)
{
return c;
}
}
}
catch(NumberFormatException e)
{
++index;
return c;
}
//return c;
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
}
PriorityTable.java
package stack;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class PriorityTable {
private String[] col;
private String[] row;
private String[][] priority;// 用-1表示小于,用0表示等于,用1表示大于
public PriorityTable(String path) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(path);
System.setIn(fis);
Scanner sc = new Scanner(System.in);
int n = Integer.valueOf(sc.nextLine());
col = new String[n];
row = new String[n];
priority = new String[n][n];
String temp = null;
if (sc.hasNextLine()) {
temp = sc.nextLine();
//System.out.println(temp);
}
row = col = temp.split("\t");
int i=0;
while (sc.hasNextLine())
{
//System.out.println(sc.nextLine());
String temp2=sc.nextLine();
//System.out.println(temp2);
if(temp2.equals(""))
{
break;
}
priority[i++]=temp2.split("\t");
}
}
public String queryPriority(String optr1,String optr2)
{
int I = -1,J=-1;
for(int i=0;i<row.length;++i)
{
if(optr1.equals(row[i]))
{
I=i;
break;
}
}
for(int j=0;j<col.length;++j)
{
if(optr2.equals(col[j]))
{
J=j;
break;
}
}
if(I==-1||J==-1)
{
return null;
}
return priority[I][J];
}
public boolean isOptr(String c)
{
for(int i=0;i<row.length;++i)
{
if(c.equals(row[i]))
{
return true;
}
}
return false;
}
}
测试:输入为3+2*(3+6)/2
运行结果: