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

栈的基础知识

栈的特征

特征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;
    }
}
相关推荐
sp_fyf_202423 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
ChoSeitaku42 分钟前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表
偷心编程43 分钟前
双向链表专题
数据结构
香菜大丸43 分钟前
链表的归并排序
数据结构·算法·链表
jrrz082843 分钟前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time1 小时前
golang学习2
算法
@小博的博客1 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生2 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步3 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara3 小时前
函数对象笔记
c++·算法