数据结构(java)——栈及其应用

   

1.  栈的简单介绍

      栈(Stack)是一种特殊的线性表,其插入和删除操作只允许在线性表的一端进行.允许操作的一端成为栈顶(Top),不允许操作的是另一端栈底(Bottom)。特点是后进先出,栈的基本操作有创建栈、判空、入栈、出栈和取栈顶元素。(下面用java实现栈的声明)

public interface Stack<T> {
	public abstract boolean isEmpty();
	public abstract void push(T x);
	//返回栈顶元素
	public abstract T peek();
	//出栈
	public abstract T pop();
}

     根据栈采用的存储结构分别有顺序栈和链式栈,(在此注意栈和线性表示不同的抽象数据类型,栈的概念不依懒于线性表或链表而存在)。

 

2.  栈的应用

在实现嵌套调用和递归调用、实现非线性结构的深度遍算法、以非递归方式实现递归算法等系统设计中,栈都是必不可少的数据结构。下面有两个例子运用栈来实现。

(1)  括号匹配的语法检查,例如:((1+2*3+4))(

首先设置一个infix存放字符串,从左向右依次对infix中的每个字符ch进行语法检查。若是左括号,则 ch入栈;若ch是右括号,则出栈,若出栈字符为左括号,表示这一对括号匹配;如果栈空或出栈字符不是左括号,表示缺少与ch匹配的左括号。然后重复执行上述步骤,直到infix检查结束,若栈空则全部括号匹配;否则栈中仍有括号。

  实现代码如下:

package Stackitcast;

/**
 * 括号匹配,((1+2)*3+4)(
 * 
 * @author Administrator
 * 
 */
public class Bracket {
	public static String isMatched(String infix) {
		// 检查字符创infix表达式中圆括号是否匹配,是,返回空串;否,返回错误信息
		Stack<String> stack = new SeqStack<String>(infix.length());
		for (int i = 0; i < infix.length(); i++) {
			char ch = infix.charAt(i);
			switch (ch) {
			case '(':
				stack.push(ch + "");
				break;
			case ')':
				if (stack.isEmpty() || !stack.pop().equals("("))
					return "期望(";
			}
		}
		return (stack.isEmpty()) ? "" : "期望)";
	}

	public static void main(String[] args) {
		String infix = "((1+2)*3+4))(";
		System.out.println(infix + "  ,编译错误:" + Bracket.isMatched(infix));
	}
}

(2)  使用栈计算算术表达式值

第一步:将中缀表达式转换为后缀表达式

 

第二步:后缀表达式求值,下图为栈的操作过程


具体实现代码如下:

package Stackitcast;

/**
 * 利用顺序栈和链式栈分别存储符号字符串和数字,对中缀表达式进行计算
 * 
 * @author Administrator
 * 
 */
public class Expression {
	/**
	 * 将中缀表达式转换为后缀表达式的过程
	 * 
	 * @param infix
	 * @return
	 */
	public static StringBuffer toPostfix(String infix) {

		// 运算符栈,顺序栈
		Stack<String> stack = new SeqStack<String>(infix.length());
		// 后缀表达式字符串
		StringBuffer postfix = new StringBuffer(infix.length() * 2);
		int i = 0;
		while (i < infix.length()) {
			char ch = infix.charAt(i);
			switch (ch) {
			case '+':
			case '-':
				while (!stack.isEmpty() && !stack.peek().equals("("))
					postfix.append(stack.pop());
				// 当前运算符入栈
				stack.push(ch + "");
				i++;
				break;
			case '*':
			case '/':
				while (!stack.isEmpty()
						&& (stack.peek().equals("*") || stack.peek()
								.equals("/")))
					postfix.append(stack.pop());
				stack.push(ch + "");
				i++;
				break;

			case '(':
				stack.push(ch + "");
				i++;
				break;

			case ')':
				// 遇到右括号出栈
				String out = stack.pop();
				while (out != null && !out.equals("(")) {
					postfix.append(out);
					out = stack.pop();
				}
				i++;
				break;
			default:
				while (i < infix.length() && ch >= '0' && ch <= '9') {

					postfix.append(ch);
					i++;
					if (i < infix.length())
						ch = infix.charAt(i);

				}
				postfix.append(" ");
			}
		}
		while (!stack.isEmpty()) {
			postfix.append(stack.pop());
		}
		return postfix;
	}

	/**
	 * 后缀表达式求值过程
	 */
	public static int toValue(StringBuffer postfix){
		Stack<Integer> stack = new LinkedStack<Integer>();
		int value=0;
		for(int i=0;i<postfix.length();i++){
			char ch = postfix.charAt(i);
			//不太懂、、、、、
			if(ch>='0'&&ch<='9'){
				value =0;
				while(ch!=' '){
					//将整数字符串转换成整数值
					value=value*10+ch-'0';
					ch=postfix.charAt(++i);
				}
				stack.push(value);
			}else
				if(ch!=' '){
					
					int y=stack.pop(), x=stack.pop();
					
					switch(ch){
					case '+':value=x+y; break;
					case '-':value=x-y; break;
					case '*':value=x*y; break;
					case '/':value=x/y; break;
					}
					//去掉(ch+"")直接就是x+y的结果了
					System.out.print(x+(ch+"")+y+"="+value+", ");
					stack.push(value);
				}
		}
		//这时候栈里就剩一个结果值
		return stack.pop();
	}
	public static void main(String[] args) {
		
		String infix="123+10*(45-50+20)/((35-25)*2+10)-11";
		StringBuffer postfix=toPostfix(infix);
		System.out.println("infix="+infix);
		System.out.println("postfix="+postfix);
		System.out.println("\nvalue="+toValue(postfix));
	}
}
由于两种栈的数据类型不一样,这里分别使用了顺序栈和链式栈实现。欢迎指正!


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值