java集合:stack及其应用举例

一 API

栈是一种线性数据结构,遵从 LIFO(后进先出)的操作顺序,所有操作都是在顶部进行。

Java 集合框架中的 Stack 继承自 Vector:跟 Vector 一样,它是 数组实现的栈。jdk1.8源码如下:

public
class Stack<E> extends Vector<E> {
    /**
     * Creates an empty Stack.
     */
    public Stack() {
    }

    /**
     * Pushes an item onto the top of this stack. This has exactly
     * the same effect as:
     * <blockquote><pre>
     * addElement(item)</pre></blockquote>
     *
     * @param   item   the item to be pushed onto this stack.
     * @return  the <code>item</code> argument.
     * @see     java.util.Vector#addElement
     */
    public E push(E item) {
        addElement(item);

        return item;
    }

    /**
     * Removes the object at the top of this stack and returns that
     * object as the value of this function.
     *
     * @return  The object at the top of this stack (the last item
     *          of the <tt>Vector</tt> object).
     * @throws  EmptyStackException  if this stack is empty.
     */
    public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }

    /**
     * Looks at the object at the top of this stack without removing it
     * from the stack.
     *
     * @return  the object at the top of this stack (the last item
     *          of the <tt>Vector</tt> object).
     * @throws  EmptyStackException  if this stack is empty.
     */
    public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }

    /**
     * Tests if this stack is empty.
     *
     * @return  <code>true</code> if and only if this stack contains
     *          no items; <code>false</code> otherwise.
     */
    public boolean empty() {
        return size() == 0;
    }

    /**
     * Returns the 1-based position where an object is on this stack.
     * If the object <tt>o</tt> occurs as an item in this stack, this
     * method returns the distance from the top of the stack of the
     * occurrence nearest the top of the stack; the topmost item on the
     * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt>
     * method is used to compare <tt>o</tt> to the
     * items in this stack.
     *
     * @param   o   the desired object.
     * @return  the 1-based position from the top of the stack where
     *          the object is located; the return value <code>-1</code>
     *          indicates that the object is not on the stack.
     */
    public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = 1224463164541339165L;
}

可以看到pop跟peek返回值一样,只是多了一步移除栈顶元素操作。Vector 是线程安全的。

二 应用demo

场景1 简单括号匹配:

Given a string containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

package com.daojia.collect;

import java.util.Stack;

public class StackTest {

	public boolean isValid(String input){
		 int stackSize = input.length();  
	        Stack stack= new Stack();  
	        int x=0;  
	        for (char c : input.toCharArray()) {  
	              
	            switch (c) {  
	                case '{':  
	                case '[':  
	                case '(':  
	                    stack.push(c);  
	                    break;  
	                case '}':  
	                case ']':  
	                case ')':  
	                    if(!stack.isEmpty()) {  
	                        char chx = (char) stack.pop();  
	                        if ((c == '}' && chx != '{') ||  
	                            (c == ']' && chx != '[') ||  
	                            (c == ')' && chx != '(')  
	                           ) {  
	                            System.err.println("Error:" + c + "at "+ x );  
	                           return false; 
	                        }  
	                    }else {  
	                        System.err.println("Error:" + c + "at "+ x );  
	                        return false;  
	                    }  
	                    break;  
	                default:  
	                    break;  
	            }  
	            x++;  
	        }  		
		return stack.isEmpty();		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 String a = "(())abc{[(])}"; // 左右括号次序匹配不正确
		 String b = "(()))abc{[]}"; // 右括号多于左括号
		 String c = "(()()abc{[]}"; // 左括号多于右括号
		 String d = "(())abc{[]()}"; // 左右括号匹配正确
		 StackTest test = new StackTest();
		System.out.println("a:"+test.isValid(a));
		System.out.println("b:"+test.isValid(b));
		System.out.println("c:"+test.isValid(c));
		System.out.println("d:"+test.isValid(d));
	}
}

场景2 生成n对匹配的括号

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n = 3, a solution set is:

"((()))", "(()())", "(())()", "()(())", "()()()"

这道题要生成正确形式的括号匹配的数量,其实就是卡特兰数,参见百科  

单纯的搜索这个,常见的解法是基于递归实现的,但是把背后的原理说明白的不太多,多是c++的代码,基于vector。

题目转换为:有个队列,假设在位置k我们还剩余left个左括号和right个右括号,如果left>0,则我们可以直接打印左括号,而不违背规则。

能否打印右括号,我们还必须验证left和right的值是否满足规则,如果left>=right,则我们不能打印右括号,因为打印会违背合法排列的规则,

否则可以打印右括号。如果left和right均为零,则说明我们已经完成一个合法排列,可以将其打印出来

package com.daojia.collect;

import java.util.Stack;

public class StackTest2 {
	
	public static void generate(int leftNum,int rightNum,String s,Stack result){
		//都为零,输出
		if( leftNum ==0 && rightNum ==0){
			result.push(s);
		}
		//剩余左括号数>0,可以输出左括号
		if(leftNum >0){
			generate(leftNum-1,rightNum,s+'(',result);
		}
		//剩余右括号数>0,且剩余左括号数<右括号数,可以输出右括号
		if(rightNum>0 && leftNum<rightNum){
			generate(leftNum,rightNum-1,s+')',result);
		}
		
	}
	
	public static Stack generateParenthesis(int n){
		Stack s  =new Stack();
		generate(n,n,"",s);
		return s;
	}

	public static void main(String[] args) {

		Stack s =generateParenthesis(3);
		while(!s.isEmpty())
		{
			System.out.println(s.pop());			
		}				
	}
}
运行结果:
()()()
()(())
(())()
(()())
((()))

还有个典型的场景是后缀表达式的计算,单独整理一下。

参考:

https://blog.youkuaiyun.com/yutianzuijin/article/details/13161721


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bohu83

买个馒头吃

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值