Java数据结构-栈

还是在上一节的基础上进行写,这栈基本上也是数组的一个子集,阉割了数组的功能,是后进先出

一、栈的实现

1. 自定义数组

package com.md.java2;

/**
 * @author md
 * @Desc
 * @date 2020/9/13 22:21
 */
public class Array<E> {

    private E[] data;
    private int size;

    // 0. 初始化,默认参数
    public Array(int capacity) {
        data = (E[]) new Object[capacity];
        size = 0;
    }

    public Array(){
        this(10);
    }

    // 1. 获取数组长度
    public int getCapacity(){
        return data.length;
    }


    public int getSize(){
        return size;
    }


    // 补充:动态数组
    private void resize(int newCapacity){

        E[] newData = (E[]) new Object[newCapacity];
        // 把之前数组中存放的数据放入到新的数组当中
        for (int i = 0; i < size; i++) {
            newData[i] = data[i];
        }
        // 新的数组再指向原来的数组
        data = newData;

    }


    // 2. 指定位置添加数据
    public void add(int index,E e){
        if (size == getCapacity())
//            throw new IllegalArgumentException("add failed");

            // 如果此时数组满的话,就进行扩容
            resize(2 * data.length);

        if (index < 0 || index > size)
            throw  new IllegalArgumentException("add failed");

        for (int i = size - 1; i >=index ; i--) {
            data[i+1] = data[i];
        }

        data[index] = e;
        size++;

    }

    // 3. 向末尾添加数据
    public void addLast(E e){
        add(size,e);
    }

    // 4. 向开头添加数据
    public void addFirst(E e){
        add(0,e);
    }

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

    // 查看最后一个元素
    public E getLast(){
        return get(size-1);
    }


    // 6. 删除指定位置的数据,并返回该数据
    public E remove(int index ){
        if (index < 0 || index > size-1)
            throw  new IllegalArgumentException("remove failed");

        // 先保存要删除的数据
        E num = data[index];

        for (int i = index+1; i < size ; i++) {
            data[i-1] = data[i];
        }

        size--;
        // 如果此时数组中剩余的是当前数组长度的一半,那么把数组的长度缩成一半
        // 由于时间复杂度的缘故,均摊复杂度,所以修改成下面的才合适
        if (size == data.length / 4 && data.length / 2 != 0)
            resize(data.length/2);

        return num;
    }

    // 7. 删除最后一个数据
    public E removeLast(){
        return remove(size-1);
    }

    // 8. 删除第一个数据
    public E removeFirst(){
        return remove(0);
    }

    // 9. 判断是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    // 重新toString
    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("Arr: size=%d,capacity=%d\n",size,getCapacity()));

        res.append("[");
        for (int i = 0; i < size; i++) {
            res.append(data[i]);
            if (i != size-1)
                res.append(",");
        }
        res.append("]");

        return res.toString();
    }
}


2. 写接口

package com.md.java2;

/**
 * @author md
 * @Desc
 * @date 2020/9/13 22:22
 */
public interface Stack<E> {

    /**
     * 获取栈中元素的个数
     * @return
     */
    int getSize();

    /**
     * 判断栈是否为空
     * @return
     */
    boolean isEmpty();

    /**
     * 入栈
     * @param e
     */
    void push(E e);

    /**
     * 弹栈
     * @return
     */
    E pop();

    /**
     * 查看栈顶元素
     * @return
     */
    E peek();
}

3. 实现接口

package com.md.java2;

/**
 * @author md
 * @Desc
 * @date 2020/9/13 22:22
 */
public class ArrayStack<E> implements Stack<E> {

    private Array<E> array;
    
    // 1. 在构造函数中进行初始化
    public ArrayStack(int capacity){
        array = new Array<>(capacity);
    }
    public ArrayStack(){
        array = new Array<>();
    }

    // 2. 获取栈中元素的个数
    @Override
    public int getSize() {
        return array.getSize();
    }

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

    // 3. 入栈,只需要调用自定义数组的向最后位置添加元素的方法即可
    @Override
    public void push(E e) {
        array.addLast(e);
    }

    // 4. 弹栈,只需删除最后一个元素
    @Override
    public E pop() {
        return array.removeLast();
    }

    // 5. 查看元素,只需要查看栈顶元素,也就是数组中的最后一个元素
    @Override
    public E peek() {
        return array.getLast();
    }

    @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();
    }
}

4. 测试

package com.md.java2;

/**
 * @author md
 * @Desc
 * @date 2020/9/13 22:31
 */
public class Main {

    public static void main(String[] args) {
        ArrayStack<Integer> stack = new ArrayStack<>();

        for (int i = 0; i < 10; i++) {
            stack.push(i);
        }
        System.out.println(stack);

        stack.pop();
        System.out.println(stack);

        Integer i = stack.peek();
        System.out.println("此时栈顶元素为:"+i);

    }
}

二、栈的应用:括号匹配

具体的可以看https://leetcode-cn.com/problemset/all/

package com.md.java1;


import java.util.Stack;

/**
 * @author md
 * @Desc 栈的应用:括号匹配
 * @date 2020/9/13 16:46
 */
public class Solution {

    public boolean isValid(String s){
        Stack<Character> stack = new Stack<>();

        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();

    }

    public static void main(String[] args) {
        System.out.println((new Solution()).isValid("(){}[]"));
    }

}

相关文章

【啊哈!算法】算法3:最常用的排序——快速排序       ...
匿名组 这里可能用到几个不同的分组构造。通过括号内围绕的正...
选择排序:从数组的起始位置处开始,把第一个元素与数组中其...
public struct Pqitem { public int priority; ...
在编写正则表达式的时候,经常会向要向正则表达式添加数量型...
来自:http://blog.csdn.net/morewindows/article/details/6...