数据结构和算法之【栈】

目录

栈的定义

自实现栈

定义栈接口

基于链表实现栈

基于数组实现栈

LeetCode-102题

题解

测试结果

LeetCode-232题

题解

测试结果

LeetCode-225题

题解

测试结果


栈的定义

计算机科学中,栈是一种线性数据结构,只能在它的一端添加或移除元素

  • 可以操作元素的一端叫做栈顶,另一端不能操作元素叫做栈底
  • 添加元素的操作叫做入栈(或压栈),移除元素的操作叫出栈(或弹栈)
  • 先进后出

自实现栈

可以通过多种方式来实现栈,如:链表、数组等。下面先定义栈的功能接口,然后分别用链表和数组来实现栈

定义栈接口

java 复制代码
package algorithm.stack;

/**
 * 栈接口:定义栈功能
 */
public interface Stack {
    // 栈的最大容量:1024
    int MAX_CAPACITY = 1 << 10;

    /**
     * 入栈/压栈
     */
    boolean push(Object e);

    /**
     * 出栈/弹栈
     */
    Object pop();

    /**
     * 查看栈顶元素
     */
    Object peek();

    /**
     * 栈是否空
     */
    boolean isEmpty();

    /**
     * 栈是否满
     */
    boolean isFull();
}

基于链表实现栈

只能从栈顶操作元素是栈的特点之一,即只从一端添加元素或者移除元素就行,所以这里我选择用单项链表来实现栈

java 复制代码
package algorithm.stack;

import java.util.Iterator;

/**
 * 基于链表实现栈
 */
public class LinkedListStack implements Stack, Iterable<Object> {
    // 虚拟头节点
    private final Node dummyHead = new Node();
    // 元素个数
    private int size;

    @Override
    public boolean push(Object e) {
        if (e == null) {
            throw new NullPointerException();
        }
        if (isFull()) {
            return false;
        }
        dummyHead.next = new Node(e, dummyHead.next);
        size++;
        return true;
    }

    @Override
    public Object pop() {
        Object e = peek();
        if (e != null) {
            dummyHead.next = dummyHead.next.next;
            size--;
        }
        return e;
    }

    @Override
    public Object peek() {
        if (isEmpty()) {
            return null;
        }
        return dummyHead.next.val;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == MAX_CAPACITY;
    }

    @Override
    public Iterator<Object> iterator() {
        return new Iterator<Object>() {
            Node p = dummyHead;

            @Override
            public boolean hasNext() {
                return p.next != null;
            }

            @Override
            public Object next() {
                Node node = p.next;
                p = p.next;
                return node.val;
            }
        };
    }

    /**
     * 定义数据节点
     */
    private static class Node {
        Object val;

        Node next;

        public Node() {
        }

        public Node(Object val, Node next) {
            this.val = val;
            this.next = next;
        }
    }
}

基于数组实现栈

这里再使用数组来实现栈,从数组的尾部来操作元素,性能要高一些,因为从数组0索引处添加或移除元素,会涉及到后续元素的移动,影响性能

java 复制代码
package algorithm.stack;

import java.util.Arrays;
import java.util.Iterator;

/**
 * 基于数组实现栈
 */
public class ArrayStack implements Stack, Iterable<Object> {
    // 元素个数
    private int size;
    // 存储元素的数组
    private Object[] container;
    // 默认初始化容量
    private static final int DEFAULT_INIT_CAPACITY = 16;
    // 定义一个指针,方便栈顶操作元素
    private int p = 0;

    @Override
    public boolean push(Object e) {
        if (e == null) {
            throw new NullPointerException();
        }
        if (isFull()) {
            return false;
        }
        grow(size + 1);
        addToContainer(e);
        return true;
    }

    /**
     * 扩容
     */
    private void grow(int minCapacity) {
        if (isEmpty()) {
            container = new Object[DEFAULT_INIT_CAPACITY];
            return;
        }
        int oldCapacity = container.length;
        // 扩容为原来的两倍容量
        int newCapacity = oldCapacity << 1;
        newCapacity = Math.min(MAX_CAPACITY, newCapacity);
        container = Arrays.copyOf(container, newCapacity);
    }

    /**
     * 执行添加元素
     */
    private void addToContainer(Object e) {
        container[p] = e;
        size++;
        p++;
    }

    @Override
    public Object pop() {
        Object e = peek();
        if (e != null) {
            container[p--] = null;
            size--;
        }
        return e;
    }

    @Override
    public Object peek() {
        if (isEmpty()) {
            return null;
        }
        return container[p - 1];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == MAX_CAPACITY;
    }

    @Override
    public Iterator<Object> iterator() {
        return new Iterator<Object>() {
            private int index = size - 1;

            @Override
            public boolean hasNext() {
                return index >= 0;
            }

            @Override
            public Object next() {
                return container[index--];
            }
        };
    }
}

LeetCode-102题

题解

java 复制代码
class Solution {
    public boolean isValid(String s) {
        // check param
        if (s == null || s.length() < 2) {
            return false;
        }
        // 借助栈来解题(Java中的LinkedList可以用作栈)
        LinkedList<Character> stack = new LinkedList<>();
        for (int i = 0; i < s.length(); i++) {
            char item = s.charAt(i);
            if ('(' == item) {
                stack.push(')');
            } else if ('{' == item) {
                stack.push('}');
            } else if ('[' == item) {
                stack.push(']');
            } else {
                if (!stack.isEmpty() && item == stack.peek()) {
                    stack.pop();
                } else {
                    return false;
                }
            }
        }
        return stack.isEmpty();
    }
}

测试结果

LeetCode-232题

题解

java 复制代码
/**
 * 注:题目上说明了所有的操作都是有效的,不会抛异常
 */
class MyQueue {

    // 用于添加元素的栈
    private LinkedList<Integer> stackEnter = new LinkedList<>();
    // 用于移除元素的栈
    private LinkedList<Integer> stackExit = new LinkedList<>();

    public void push(int x) {
        stackEnter.push(x);
    }

    public int pop() {
        transferStack();
        return stackExit.pop();
    }

    private void transferStack() {
        if (!stackExit.isEmpty()) {
            return;
        }
        while (!stackEnter.isEmpty()) {
            stackExit.push(stackEnter.pop());
        }
    }

    public int peek() {
        transferStack();
        return stackExit.peek();
    }

    public boolean empty() {
        return stackEnter.isEmpty() && stackExit.isEmpty();
    }
}

测试结果

LeetCode-225题

题解

java 复制代码
/**
 * 注:题目中说明所有操作都是有效操作
 */
class MyStack {
    // Java中,LinkedList可以用作队列
    // 定义两个队列
    private final LinkedList<Integer> queueEnter = new LinkedList<>();
    private final LinkedList<Integer> queueExit = new LinkedList<>();

    public MyStack() {

    }

    public void push(int x) {
        queueEnter.offer(x);
    }

    public int pop() {
        transferQueue();
        return queueExit.poll();
    }

    private void transferQueue() {
        while (!queueEnter.isEmpty()) {
            queueExit.offer(queueEnter.poll());
        }
        int size = queueExit.size();
        for (int i = 0; i < size - 1; i++) {
            queueExit.offer(queueExit.poll());
        }
    }

    public int top() {
        int pop = pop();
        queueExit.offer(pop);
        return pop;
    }

    public boolean empty() {
        return queueEnter.isEmpty() && queueExit.isEmpty();
    }
}

测试结果

相关推荐
逻辑驱动的ken4 小时前
Java高频面试考点场景题20
java·开发语言·深度学习·面试·职场和发展
bzmK1DTbd4 小时前
Java游戏服务器:Netty框架的高并发网络通信
java·服务器·游戏
longxibo4 小时前
【Flowable 7.2 源码深度解析与实战-前言】
java·后端·流程图
小龙报4 小时前
【Coze-AI智能体平台】低代码省时高效:Coze 应用开发全流程指南
java·人工智能·python·深度学习·低代码·chatgpt·交互
Sarvartha4 小时前
N 个字符串最长公共子序列(LCS)求解问题
数据结构·算法
m0_629494734 小时前
LeetCode 热题 100-----16.除了自身以外数组的乘积
数据结构·算法·leetcode
勿忘初心12214 小时前
【Java实战】SpringBoot 集成 freemarker 导出 Word 模板
java·spring boot·freemarker·模板引擎·word导出·后端实战
绿草在线4 小时前
SpringBoot项目实战:从零搭建高效开发环境
java·spring boot·后端
J2虾虾5 小时前
Java Lambda 表达式详解文档
java·开发语言
longxibo5 小时前
【第1章 环境搭建与项目结构解析】
java·后端·流程图