算法通关村第四关——如何基于数组(链表)实现栈

栈的基础知识

栈的特征

特征1

栈和队列是比较特殊的线性表,又被称为 访问受限的线性表。栈是很多表达式、符号等运算的基础,也是递归的底层实现(递归就是方法自己调用自己,在JVM的虚拟机栈中,一个线程中的栈帧就是一个要调用的方法,栈帧的实现就是栈结构,其会将正在执行的方法(栈帧)设在栈顶)。理论上递归能够做的题目,栈都可以做,只是有些问题用栈会比较复杂。

特征2

栈的底层实现依然是链表或者顺序表。栈与线性表的最大区别就是:数据的存取操作被限制了,其插入和删除操作只允许在线性表的一端进行。

一般而言,把2允许操作的一端称为栈顶(top),不可操作的一端称为栈底(bottom)

把插入元素的操作称为入栈(Push),把删除元素的操作称为出栈(pop);若栈中没有任何元素则称为空栈。其结构如下:

栈的操作

栈的常用操作主要有:

  • push(E):增加一个元素E
  • pop():弹出一个元素E
  • peek():只显示栈顶元素,不弹出元素
  • empty():判断栈是否为空
    在自定义栈时,不管用数组还是链表,都要实现上面的几个方法。

检测对栈的理解:

入栈顺序为1234,所有可能的出栈序列是什么?
4个元素的全排列共有24种,栈要求符合后进先出,按此衡量排除后即得:

1234√ 1243√ 1324√ 1342√

1432√ 2134√ 2143√ 4321√

2314√ 2341√ 2431√3421√

3214√ 3241√ 3124x 3142x

3412x 4123x 4132x 2413x

4213x 4231x 4312x 1423x

14种可能,10种不可能,如上所示。

Java中的栈

java的util中提供了栈Stack类,使用不复杂,看下面例子

java 复制代码
public class MainTest {
public static void main(string[] args) {
    Stack<Integer> stack = new stack();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    System.out.println("栈顶元素为:" + stack.peek());
    while (!stack.empty()){
    //只显示没出栈
    System.out.printIn(stack.peek());//出栈并且显示
    System.out.println(stack.pop());
    }
  }
}

自定义栈

如果要自己实现栈,可以有数组、链表和java提供的LinkedList三种基本方式我们都看一下。

采用顺序表实现的的栈,内部以数组为基础,实现对元素的存取操作。在应用中还要注意每次入栈之前先判断栈的容量是否够用,如果不够用,可以进行扩容。

入栈过程如下图所示:

出栈过程如下图所示:

基于数组实现栈

top先将栈顶元素取出,然后再执行top--。完整的实现代码如下

java 复制代码
package org.example.stack;

import java.util.Arrays;

public class MyStackByArray<T>{
    // 实现栈的数组
    private Object[]  stack;
    // 栈顶元素
    private int top;
    //初始化栈容量

    public MyStackByArray(int top) {
        stack = new Object[top];
    }

    //判断栈是否为空
    public boolean isEmpty(){
        return top == 0;
    }
    //返回栈顶元素
    public T peek(){
        T t = null;
        if (top > 0){
            t = (T) stack[top -1];
        }
        return t;
    }

    // 入栈
    public void push(T t){
        extendCapacity(top + 1);
        stack[top] = t;
        top++;
    }

    // 出栈
    public T pop(){
        T t = peek();
        if (top > 0){
            stack[top-1] = null;
            top--;
        }
        return t;
    }

    //扩大容量
    private void extendCapacity(int size) {
        int len = stack.length;
        if (len < size){
            size = size * 3/2 + 1;
            stack = Arrays.copyOf(stack, size);
        }
    }


}

基于链表实现栈

链表实现栈,只需要把删除和修改的操作都限制在头节点即可,如下图:

实现代码如下:

java 复制代码
package org.example.stack;

public class MyStackByLinkedList <T>{
    // 构造节点
    class Node<T>{
            public   T t;
            public Node next;
    }
    // 头指针
    public Node<T> head;
    // 初始化
    MyStackByLinkedList(){
        head = null;
    }

    // 入栈
    public void push(T t){
        if (t==null){
            throw new NullPointerException("形参不能为空");
        }
        // 如果是空链表,就将入栈的元素设为第一个元素
        if (head == null){
            head = new Node<>();
            head.t = t;
            head.next = null;
        }else {
            Node<T> temp = head;
            head = new Node<>();
            head.t = t;
            head.next = temp;
        }
    }
    // 出栈
    public T pop(){
        T t = null;
        if (head == null){
            return null;
        }else {
            t = head.t;
            head = head.next;
        }
        return t;
    }

    // 取栈顶元素
    public T peek(){
        if (head == null){
            return null;
        }
        return head.t;
    }

    //栈空
    public boolean isEmpty(){
        return head == null;
    }
}
相关推荐
huang5791471 小时前
哈希算法的抗碰撞机制与安全性增强策略4
算法
林浩杨_1 小时前
SIGIR 2026|南京大学:Video-GAR:“通过生成 Query 来验证视频语义理解”的生成增强范式
论文阅读·人工智能·算法
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出货船中的“独特载货量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Elsa️7462 小时前
算法一周刷题总结
c++·算法
小小程序猴12 小时前
深圳乘路资讯AI培训怎么样?课程靠谱吗?——一套课程可信度评估模型与实证分析
人工智能·算法
云上先途2 小时前
标签化服务适合哪些人?常见适用场景一次讲清
大数据·人工智能·算法·音视频
彧azz2 小时前
DFS与BFS:图遍历的两大核心算法
数据结构·学习·算法·深度优先·广度优先
宣宣猪的小花园.3 小时前
【机器学习】损失函数与梯度下降:机器如何通过“犯错”不断变好
人工智能·算法·机器学习
青山木3 小时前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划
土司大王4 小时前
LeetCode hot100——33.搜索旋转排序数组:Java 二分模板与 O(log n) 实现
数据结构·算法·leetcode