<数据结构基础学习>(三)Part 1 栈

一.栈 Stack

栈也是一种线性的数据结构

相比数组,栈相对应的操作是数组的子集。

只能从一端添加元素,也只能从一端取出元素。这一端成为栈顶。

1,2,3依次入栈得到的顺序为 3,2,1,栈顶为3,只能取出栈顶的元素3(出栈)。

栈是一种后进先出的数据结构 LIFO(Last In First Out)

栈的应用

1.无处不在的Undo操作(撤销)

2.程序调用的系统栈

编程时,用到子过程调用时,当一个子过程执行完成之后自动回到上层中断的位置:

系统栈记录每次调用过程中中断的那个点

function A(){
   ...      //1    
   B()      //2
   ...      //3    
  
}
function B(){
   ...      //1    
   C()      //2
   ...      //3    
  
}
function B(){
   ...      //1    
   ...      //2
   ...      //3    
  
}

 A2 B2依次入栈 B2 A2依次出栈

3.编译器 括号匹配(第三条会用代码实现)

二.栈的基本实现(基于动态数组)

Stack<E>   5个方法

void push(E)  入栈  O(1)均摊

E pop()  出栈 O(1)均摊

E peek()  查看栈顶元素   O(1)

int getSize()  栈里元素个数   O(1)

boolean isEmpty()    判断栈是否为空   O(1)

具体底层实现,用户不关心,实际底层有多种实现方式。

设置Interface Stack<E>,设置五种方法,用类ArrayStack<E>继承接口具体实现(基于第一章动态数组)

Interface Stack<E>

public interface Stack<E> {

    int getSize();
    boolean isEmpty();
    void push(E e);
    E pop();
    E peek();

}

ArrayStack<E>继承接口

public class ArrayStack<E> implements Stack<E>

 1.基本的构造函数

  Array<E> array;

    public ArrayStack(int capacity){
        array = new Array<>(capacity);
    }

    public ArrayStack(){
        array = new Array<>();
    }

 基础操作:判断是否为空,获取栈中元素个数,获取栈的容量

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    public int getCapacity(){
        return array.getCapacity();
    }

2.入栈操作

@Override
    public void push(E e) {
        array.addLast(e);
    }

3.出栈操作

@Override
    public E pop() {
        return array.removeLast();
    }

在第一章动态数组的Array类中加入getLast()和getFirst()方法得到动态数组的最后一个数和第一个数

其中注意,return get(size - 1); 不可写为return data[size - 1];因为万一size为0,data[-1]索引不合法

//获取index索引位置的元素
    E get(int index){
        if(index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        return data[index];
    }

    public E getLast(){
        return get(size-1);
        //return data[size - 1];  万一size为0,产生不合法索引
    }

    public E getFirst(){
        return get(0);
    }

4.栈的查看栈顶操作

 @Override
    public E peek() {
        return array.getLast();
    }

5.重写toString方法,让输出更具有可读性

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append("Stack:");
        res.append("[");
        for(int i = 0 ; i < array.getSize() ; i ++){
            res.append(array.get(i));
            if(i != array.getSize()-1){
                res.append(",");
            }
        }
        res.append("] top");
        return res.toString();
    }

三.栈的括号匹配

思想:将一个字符串遍历,对于每一个字符如果为左括号就入栈,如果为右括号,就查看此时栈顶的元素是否为匹配的左括号,如果不是就return false,最后return stack.isEmpty();而不是true。

栈顶元素反映了在嵌套的层次关系中,最近的需要匹配的元素。

  public boolean isValid(String s){
        ArrayStack<Character> stack = new ArrayStack<>();
        for(int i = 0; i < s.length() ; i ++){
            char c = s.charAt(i);
            if(c == '(' || c == '[' || c == '{'){
                stack.push(c);
            }else {
                if(stack.isEmpty())
                    return false;

                char topChar = stack.pop();
                if(c == ')' && topChar != '(')
                    return false;
                if(c == ']' && topChar != '[')
                    return false;
                if(c == '}' && topChar != '{')
                    return false;
            }
        }

        return stack.isEmpty();
    }
原文地址:https://www.cnblogs.com/HarSong13/p/10665837.html