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

栈的基础知识

栈的特征

特征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;
    }
}
相关推荐
c++初学者ABC1 分钟前
GESP2级2403 小杨的日字矩阵
c++·算法
大写-凌祁21 分钟前
2024国赛A题第一问
线性代数·算法·机器学习·数学建模
代码小将26 分钟前
PTA数据结构编程题7-1最大子列和问题
数据结构·c++·笔记·学习·算法
pk_xz1234561 小时前
R 和 Origin 完成细菌 OTU 表、土壤理化性质数据的微生物 Beta 多样性分析
算法·机器学习·r语言
Ning_.1 小时前
力扣第116题:填充每个节点的下一个右侧节点指针 - C语言解法
c语言·算法·leetcode
yangjiwei02071 小时前
数据结构-排序
数据结构·python
小小unicorn1 小时前
第二章:算法练习题2
算法
坊钰1 小时前
【Java 数据结构】合并两个有序链表
java·开发语言·数据结构·学习·链表
抓住鼹鼠不撒手1 小时前
力扣 429 场周赛-前两题
数据结构·算法·leetcode
神经网络的应用2 小时前
C++程序设计例题——第三章程序控制结构
c++·学习·算法