一、概述

说到栈,大家都不会陌生,相对于其他复杂的数据结构,栈相对来说概念上比较号理解,也比较简单,但是栈的具体应用却是非常灵活的,需要平时的积累和偶尔的灵感。栈(stack)只能对末尾的元素进行操作,该端称为栈顶,另一端称为栈尾。

大家想必都知道栈有后进先出(或先进后出)的特性,简称LIFO,不过很少记为FILO的,大致是约定俗成吧,就像队列是先进先出,记为FIFO,而大家很少会用LILO来表示,当然并不是完全没有啊,看到相应的表达还是要认识的。

 

二、实现

链表同顺序表一样,也有两种存储方法,分别是链栈和顺序栈。顺序栈的思路是通过数组等存储栈的元素,但是弊端在于数组的静态性,即如果数组初始长度过小,那么会出现存储不下的窘境;如果设置的过大则会造成内存的浪费。那么java集合Stack也是使用的数组,它是怎么做的呢?Stack继承于Vector,Vector使用的是扩容技术,即使用Arrays.copyOf()方法将数组赋给一个更大的数组,当然JDK是官方,对于我们实现如果能使用java.util.Arrays,那为什么不直接使用java.util.ArrayList替代数组呢?这样就没有动态扩容的问题了。当然都是可以实现的选项。

/*扩容的实现*/
stack = Arrays.copyOf(stack, newLength); //stack代表原数组,newLength代表新的长度,还有一个System.arrayCopy();
/*若新长度比原来大,剩下的值为默认值,否则截断旧数组*/*ArrayList实现栈*/package DS;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Stack;

public class StackDemo<T> {
    /*Domain*/
    private int size;
    private ArrayList <T> data;

    public StackDemo()
    {
        size = 0;
        data =new ArrayList<T>();
    }

    public T push (T t)
    {
        data.add(t);
        size++;
        return t;
    }

    public T pop()
    {
     if(size>0){ T end
= data.remove(size-1); size--; return end;}
}
public void tra() { Iterator it = data.iterator(); while(it.hasNext()) { System.out.print(it.next()); System.out.print("--"); } System.out.println(); } public static void main(String []args) { StackDemo <String> s = new StackDemo<>(); s.push("first"); s.push("second"); s.push("third"); s.push("forth"); s.tra(); System.out.println(s.pop()); s.tra(); s.pop(); s.tra(); // Stack } }

 

 

除了顺序栈,还有链栈的方法可选,即通过链表的方式把栈的各个元素串联起来,这样每次新数据入栈时只需申请新的节点即可,完全避免扩容的问题:

 

package DS;

public class LinkedStack<T> {
    private int size;
    private Node end;
    private Node head;
    private class Node<T> {
        T data;
        Node next;
        Node prev;
        public Node (T t)
        {
            data =t;
            next =null;
            prev =null;
        }
    }

    public LinkedStack()
    {
        size =0;
        end = null;
        head = null;
    }

    public T push(T m)
    {
        Node n = new Node (m);
        if(size == 0)
        {head = end = n;size++;}
        else
        {end.next = n;
        n.prev = end;
        end = n;
        size++;}

        return m;
    }

    public T pop()
    {
        if(size>1)
        {
            T x = (T)end.data;
            end.prev.next=null;
            end = end.prev;
            size--;
            return x;
        }
        else if (size == 1)
        {
            T x = (T)end.data;
            head = end = null;
            size--;
            return x;
        }
        else
        {
            System.out.println("ss");
            return null;
        }
    }

    public int getSize()
    {
        return size;
    }

    public void tr()
    {
        Node p = head;
        while (p!=null)
        {
            System.out.println(p.data);
            p = p.next;
        }
    }

    public static void main(String []args)
    {
        LinkedStack<Integer> ls = new LinkedStack<>();
        ls.push(4);
        ls.push(5);
        ls.push(9);
        ls.tr();
        System.out.println("The length is "+ls.getSize());
        ls.pop();
        ls.pop();
        ls.tr();
        System.out.println("The length is "+ls.getSize());
        ls.pop();
        ls.pop();
    }
}

 

 

 

 

三、实战

Valid Parentheses

 

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

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.

Note that an empty string is also considered valid.

 

Example 1:

Input: "()"
Output: true

Example 2:

Input: "()[]{}"
Output: true

Example 3:

Input: "(]"
Output: false

Example 4:

Input: "([)]"
Output: false

Example 5:

Input: "{[]}"
Output: true
 
本题为Leetcode第20题,关于这道题首先想到的是使用Java的Stack类,对于每个字符串中的字符,判断栈顶元素是否和下一个字符相匹配,如果匹配,则弹出栈顶元素,否则将该字符压入栈中。其实最主要的问题处在如何匹配 '(' 和 ')','[' 和 ‘]’ 以及 '{' 和 ‘}’ 。首先想到必然是ASCII码,但是我背不下来,也不愿意去查。所以就考虑使用if-else组合进行匹配,虽然可能会复杂些,但是也能达到目标。
 
这次我比较惊喜的是提交一次就成功Accpet,而且没有使用编译器,单纯的在网页上手打,并且没有百度过这道题,直接成功别提有多激动了!!!
 
import java.util.Stack;
class Solution {
    public boolean isValid(String s) {
        if (s.length()==0)
            return true;
        else if(s.length()%2==1)
            return false;
        else
        {
        Stack <Character>st = new Stack<Character>();
        for (int i=0;i<s.length();i++)
        {
            if(st.isEmpty())
            {
                st.push(s.charAt(i));
            }
            
            else if ((char)st.peek() == '(')
            {
                if (s.charAt(i) == ')')
                    st.pop();
                else
                    st.push(s.charAt(i));
            }
            else if (st.peek() == '[')
            {
                if (s.charAt(i) == ']')
                    st.pop();
                else
                    st.push(s.charAt(i));
            }
            
            else if (st.peek() == '{')
            {
                 if (s.charAt(i) == '}')
                    st.pop();
                else
                    st.push(s.charAt(i));
            }
            else
            {
               st.push(s.charAt(i));
            }
                
        }
            
        return st.isEmpty();
        }
    }
}

 

posted @ 2019-08-13 20:45  LeftBody  阅读(387)  评论(0编辑  收藏  举报