栈的定义

  栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

  简而言之,这种数据结构类似于长条形的存储空间,并且一端封闭,它的特点是先入后出。

  数据呈现方式如下图:

  需要特别注意的是,栈是一种逻辑结构,并不是一种物理上存在的数据结构,如果你要实现一个栈来存储数据,你可以使用数组或链表来实现。

 

入栈

  现在我们要在栈中添加一个数据100,将100这个数据压入栈(push)。

  栈只有一个入口,添加数据只能从栈顶一侧放入,新放入的数据位置成为新的栈顶。

 

出栈

  出栈就是取出元素,专业术语叫做弹出元素(pop),因为它具有取出数据并且删除两个效果。

  这就没有了指定弹出哪一个数据的说法了,你只能说弹出一个数据,至于弹出哪一个?永远都是处在栈顶那一个。

 

  弹出一个数据:

  再弹出一个数据:

效率

  无论是入栈还是出栈,都只是涉及到栈顶的那一个元素,不涉及其他元素的移动,所以栈的出栈入栈时间复杂度都是O(1)。

使用场景

  栈在实战中使用场景应该很少,但肯定是有的,比如需要每次访问最新的数据时,就可以选择栈来存储数据。

  栈在计算机中是不可获取的机制,在CPU内部就有栈使用这个数据结构来进行函数调用和返回、数字转字符、表达式求值、走迷宫等等,只要数据的保存具有先进后出的需求,都优先考虑使用栈。

代码实现

  栈的核心是入栈与出栈的规则,所以为了规避掉数据类型、扩容等问题,我这里使用动态数组ArrayList来实现

/**
 * @Description 栈
 * @Author zhaobaolin
 * @Date 2019/5/26
 */
public class MyStack<T> {

    private ArrayList<T> arr = new ArrayList<>();

    public void push(T data)
    {
        arr.add(data);
    }
    private boolean isEmpty()
    {
        return arr.isEmpty();
    }

    public T pop()
    {
        if(isEmpty()){
            return null;
        }
        int index = arr.size() - 1;
        T data = arr.get(index);
        arr.remove(index);
        return data;
    }

    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        myStack.push("hello");
        myStack.push(666);
        myStack.push("world");
        myStack.push(888);
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
    }
}

 

最小栈

/**
 * @Description
 * @Author zhaobaolin
 * @Date 2019/5/26
 *
 *
 * 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
 *
 * push(int x) -- 将元素 x 推入栈中。
 * pop() -- 删除栈顶的元素。
 * top() -- 获取栈顶元素。
 * getMin() -- 检索栈中的最小元素。
 */
public class MinStack {
    private List arr;
    private int minIndex = -1;
    public MinStack() {
        arr = new ArrayList();
    }

    public void push(int x) {
        if(arr.isEmpty()){
            minIndex = 0;
        }
        arr.add(x);
        if(x < (int)arr.get(minIndex)){
            minIndex = arr.size() - 1;
        }
    }

    public void pop() {
        if(!arr.isEmpty()){
            int i = arr.size() - 1;
            arr.remove(i);
            if(i == this.minIndex){
                this.minIndex = getArrayListMinIndex();
            }
        }
    }

    public int top() {
        if(arr.isEmpty()){
            return -1;
        }
        int i = arr.size() - 1;
        int data = (int) arr.get(i);
        if(i == this.minIndex){
            this.minIndex = getArrayListMinIndex();
        }
        return data;
    }

    private int getArrayListMinIndex()
    {
        if(arr.isEmpty()){
            return -1;
        }
        Object obj = Collections.min(arr);
        return arr.indexOf(obj);
    }

    public int getMin() {
        return this.minIndex >= 0 ? (int) arr.get(this.minIndex) : -1;
    }

    public static void main(String[] args) {

    //测试用例
/*
        MinStack minStack = new MinStack();
        minStack.push(1);
        minStack.push(2);
        System.out.println(minStack.top()); //  --> 返回 2
        System.out.println(minStack.getMin()); //  --> 返回 1
        minStack.pop();
        System.out.println(minStack.getMin()); //  --> 返回 1
        System.out.println(minStack.top()); //  --> 返回 1
*/


/*        MinStack minStack = new MinStack();
        minStack.push(-2);
        minStack.push(0);
        minStack.push(-3);
        System.out.println(minStack.getMin()); //  --> 返回 -3.
        minStack.pop();
        System.out.println(minStack.top());   //   --> 返回 0.
        System.out.println(minStack.getMin());//   --> 返回 -2.
        */
    }
}

 

有效的括号

这也是一道痕经典的题

/**
 * @Description
 * @Author zhaobaolin
 * @Date 2019/5/26
 *
 * 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
 *
 * 有效字符串需满足:
 * 左括号必须用相同类型的右括号闭合。
 * 左括号必须以正确的顺序闭合。
 * 注意空字符串可被认为是有效字符串。
 *
 * 例如:
 * 输入: "()"  输出: true
 * 输入: "()[]{}" 输出: true
 * 输入: "(]" 输出: false
 * 输入: "([)]" 输出: false
 * 输入: "{[]}" 输出: true
 * 输入: "(([]){})" 输出: true
 */
public class Bracket {
    private Map map;
    private Stack stack;

    public Bracket() {
        map = new HashMap();
        map.put("(",")");
        map.put("{","}");
        map.put("[","]");
    }

    public boolean isValid(String s) {
        this.stack = new Stack();

        s = s.trim();
        int len = s.length();
        for(int i=0;i<len;i++){
            String str = s.substring(i,i+1);

            if(this.stack.empty()){
                stack.push(str);
                continue;
            }

            String peek = (String)stack.peek();

            //如果栈顶的元素不是该符号的对应 则判断该符号是否是起始符号
            if(str.equals(map.get(peek))){
                stack.pop();
            }else{
                if(map.containsKey(str)){
                    stack.push(str);
                }else{
                    return false;
                }
            }
        }
        return this.stack.empty();
    }

    public static void main(String[] args) {
        Bracket bracket = new Bracket();
        System.out.println(bracket.isValid("()"));  // true
        System.out.println(bracket.isValid("()[]{}")); // true
        System.out.println(bracket.isValid("(]"));  // false
        System.out.println(bracket.isValid("([)]"));    // false
        System.out.println(bracket.isValid("{[]}"));    // true
        System.out.println(bracket.isValid("(([]){})"));    // true
    }
}

 

posted @ 2019-05-14 10:54  不该相遇在秋天  阅读(1567)  评论(0编辑  收藏  举报