数据结构之栈

代码见:点击打开链接,高抬贵手赞一个呗,,,,,

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;

算符优先法的规则:

  • 先乘除,后加减
  • 从左算都右
  • 先括号内,后括号外
    为了实现算符优先法,需要使用两个栈,一个是操作数栈(opnd),一个是操作符栈(optr)。

4.2设计思路

    算法的基本思想是:

  1. 首先让操作数栈(opnd)为空栈,表达式起始符“#”为运算符栈的栈底元素;
  2. 依次读入表达式中每个字符,或是操作数则进操作数栈(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

运行结果:



“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页
评论

打赏作者

一眼碗里

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值