如何基于链表与数组实现栈

news2024/11/26 4:48:58

这里写目录标题

  • 栈的基础知识
  • 基于数组实现栈
  • 基于链表实现栈

栈的基础知识

栈,又名堆栈,是一种受限的线性表,这意味着该线性表只能在一段进行插入或删除操作。具体来说,栈顶是允许进行插入或删除操作的一端,而相对的另一端被称为栈底。

栈的主要特性为“后进先出”,也就是说最后存入的元素将最先被取出。这种特性也可以理解为“先进后出”,即最早存入的元素最后才能被取出。

栈的操作主要有两种:入栈和出栈。入栈是将元素放入栈顶,而出栈则是将栈顶元素移除。例如,你可以把往柜子里放东西的过程比作入栈,从柜子里取东西的过程则可比作出栈。

基于数组实现栈

数组是一种具有连续内存空间的数据结构,我们可以使用数组来实现栈。
采用数组实现栈,我们先来看一下过程:
入栈过程:
在这里插入图片描述
出栈过程:
在这里插入图片描述

class MyStack<T> {
    private Object[] stack;
    //栈顶元素
    private int top;
    MyStack() {
        stack = new Object[10];
    }
    //判断是否为空
    public boolean isEmpty() {
        return top == 0;
    }
    //返回栈顶元素
    public T peek() {
        if (top > 0) {
            return (T) stack[top - 1];
        }
        return null;
    }
    //入栈
    public void push(T t) {
        expandCapacity(top + 1);
        stack[top++] = t;
    }
    //出栈
    public T pop() {
        T t = null;
        if (top > 0) {
            t = (T) stack[top - 1];
            stack[top - 1] = null;
            top--;
            return t;
        }
        return t;
    }
    public void expandCapacity(int size) {
        int len = stack.length;
        if (size > len) {
            //扩容50%
            size = size * 3 / 2 + 1;
            stack = Arrays.copyOf(stack, size);
        }
    }
}
  1. 定义一个泛型类MyStack,其中T表示栈中元素的类型。
  2. 定义一个私有对象数组stack,用于存储栈中的元素。
  3. 定义一个私有整数变量top,表示栈顶元素的索引。
  4. 定义一个无参构造函数,初始化stack数组的大小为10。
  5. 定义一个isEmpty()方法,判断栈是否为空,如果top等于0,则返回true,否则返回false。
  6. 定义一个peek()方法,返回栈顶元素。如果栈不为空,则返回栈顶元素,否则返回null。
  7. 定义一个push(T t)方法,将元素t压入栈中。首先调用expandCapacity(top+1)方法扩容,然后将元素t存入栈顶,最后将top加1。
  8. 定义一个pop()方法,从栈中弹出元素。如果栈不为空,则将栈顶元素赋值给变量t,将栈顶元素置为null,将top减1,然后返回变量t。如果栈为空,则直接返回null。
  9. 定义一个expandCapacity(int size)方法,用于扩容。如果传入的参数size大于当前数组的长度,则将数组长度扩大到原来的50%,并将原数组的元素复制到新数组中。
    我们测试一下我们的方法正不正确:
public class test1 {
    public static void main(String[] args) {
        MyStack<String> myStack = new MyStack<>();
        System.out.println(myStack.peek());
        System.out.println(myStack.isEmpty());
        myStack.push("1");
        myStack.push("2");
        myStack.push("3");
        System.out.println(myStack.pop());
        System.out.println(myStack.isEmpty());
        System.out.println(myStack.peek());
    }
}

在这里插入图片描述

基于链表实现栈

链表是一种常见的数据结构,它由多个结点组成,每个结点包含一个数据元素和一个指向下一个结点的指针。我们可以使用链表来实现栈。

class ListStack<T> {
    class Node<T> {
        public T t;
        public Node next;
    }

    public Node<T> head;

    ListStack() {
        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() {
        if (head == null) {
            return null;
        }
        T t = head.t;
        head = head.next;
        return t;
    }

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

    //判断栈是否为空
    public boolean isEmpty() {
        return head == null;
    }
}

在ListStack类中,定义了一个内部类Node,表示栈中的节点。每个节点包含两个属性:t表示节点存储的元素,next表示指向下一个节点的引用。
ListStack类还包含以下方法:

  1. push(T t):将元素t压入栈顶。如果t为null,则抛出异常。如果栈为空,则创建一个新的节点作为栈顶;否则,创建一个新的节点并将其插入到栈顶。
  2. pop():从栈顶弹出元素并返回。如果栈为空,则返回null。否则,返回栈顶元素的值,并将栈顶指针指向下一个节点。
  3. peek():获取栈顶元素但不弹出。如果栈为空,则返回null。否则,返回栈顶元素的值。
  4. isEmpty():判断栈是否为空。如果栈顶指针为null,则返回true;否则返回false。
    我们依旧写一个测试方法测试一下我们的方法正不正确:
public class test2 {
    public static void main(String[] args) {
        ListStack<Object> listStack = new ListStack<>();
        System.out.println(listStack.peek());
        System.out.println(listStack.isEmpty());
        listStack.push("1");
        listStack.push("2");
        listStack.push("3");
        listStack.push("4");
        System.out.println(listStack.peek());
        System.out.println(listStack.isEmpty());
    }
}

在这里插入图片描述

总结:链表和数组都可以用来实现栈。链表基于指针的指向实现栈的操作,具有动态增加和删除元素的能力,但需要更多的内存空间。数组基于连续的内存空间实现栈的操作,具有更高的存取效率,但缺乏动态增加和删除元素的能力。在实际应用中,我们需要根据具体的需求选择合适的实现方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1170767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

零基础入门网络安全白帽黑客,挑战年薪30w!

最近好朋友老李说他想转渗透测试。 他说&#xff1a;运维这块干了3年了&#xff0c;感觉自己目前有点迷茫&#xff0c;不知该怎么去提升了。而在日常工作生活当中&#xff0c;黑客攻击可以说是很常见了&#xff0c;他感觉到网络安全越来越重要&#xff0c;对软件测试的要求也不…

大疆Livox MID-360安装ROS1/2驱动 Ubuntu20.04

文章目录 一、接线连接二、安装上位机可视化工具三、安装ROS驱动3.1 配置静态IP3.2 安装Livox SDK23.3 安装ROS驱动3.4 驱动 本文介绍如何在Ubuntu20.04中安装大疆Livox MID-360的ROS1/2驱动 一、接线连接 livox航插一分三线&#xff0c;其中航空母头连接激光雷达&#xff0c…

Spring | Sring Task (定时任务框架) 、微信小程序开发

目录&#xff1a; 一、Sring Task (定时任务框架) &#xff1a;Sring Task介绍Spring Task应用场景corn表达式corn表达式在线生成器SpringTask入门案例&#xff1a;导入maven依赖启动类上添加 EnableScheduling 注解定时方法上添加 Scheduled( cron “xxxxx” ) 注解自定义“定…

ZKP Introduction of Nova (Yu Guo) 手写笔记

ZKP学习笔记 郭宇老师Nova课程手写笔记

创建asp.net api和docker-compose项目

vs2022创建asp.net core web api项目 创建完成 添加docker-compose支持 添加成功 docker配置 docker-compose配置

腾讯云3年轻量2核2G4M服务器从366.6元三年涨价了?

2023腾讯云双11优惠活动3年轻量应用服务器涨价了&#xff1f;确实是涨价了&#xff0c;仅限于三年时长轻量应用服务器&#xff0c;一年时长并没有涨价&#xff0c;相比隔壁阿里云&#xff0c;腾讯云依旧在提供三年轻量应用服务器和5年时长云服务器CVM已经很难得了&#xff0c;想…

集线器、交换机、网桥、路由器、网关

目录 集线器(HUB)交换机(SWITCH)网桥(BRIDGE)路由器(ROUTER)网关(GATEWAY)交换机和路由器的区别参考 集线器(HUB) 功能 集线器对数据的传输起到同步、放大和整形的作用 属于物理层设备 工作机制 使用集线器互连而成的以太网被称为共享式以太网。当某个主机要给另一个主机发送单…

如何使用 SwiftUI 中新地图框架 MapKit

文章目录 前言MapKit 弃用项MapContentBuilder&#xff08;iOS 17&#xff09;地图交互地图样式地图控件地图相机位置总结 前言 了解 iOS 17 中的 MapKit 后&#xff0c;我们会发现 Apple 引入了更适合 SwiftUI 的 API。 MapKit 弃用项 一旦将你的 App 目标更新到 iOS 17&am…

OpenGL ES入门教程(二)之绘制一个平面桌子

OpenGL ES入门教程&#xff08;二&#xff09;之绘制一个平面桌子 前言0. OpenGL绘制图形的整体框架概述1. 定义顶点2. 定义着色器3. 加载着色器4. 编译着色器5. 将着色器链接为OpenGL程序对象6. 将着色器需要的数据与拷贝到本地的数组相关联7. 在屏幕上绘制图形8. 让桌子有边框…

立创eda 焊接辅助工具使用

立创EDA为板级EDA设计软件。EDA指的是通过计算机的辅助完成电路原理图、印刷电路板文件等的绘制、制作、仿真设计。 立创EDA是一款基于浏览器的&#xff0c;专为中国人设计的&#xff0c;友好易用的EDA设计工具。起于2010年&#xff0c;完全由中国人独立开发&#xff0c;拥有独…

Ubuntu下安装vscode,并解决终端打不开vscode的问题

Visual Studio Code安装 1&#xff0c;使用 apt 安装 Visual Studio Code 在官方的微软 Apt 源仓库中可用。按照下面的步骤进行即可&#xff1a; 以 sudo 用户身份运行下面的命令&#xff0c;更新软件包索引&#xff0c;并且安装依赖软件&#xff1a; sudo apt update sud…

女孩子穿这种粉粉嫩嫩~的卫衣也太好看了吧

果然女孩子穿这种粉粉嫩嫩的衣服 真的超级有甜美可爱氛围哎 软糯亲肤的面料&#xff0c;上身很舒服哦 时尚polo领加上半拉链设计 既实用又美观&#xff0c;穿脱很方便

如何使用Selenium处理Cookie,今天彻底学会了!

01、cookie介绍 HTTP协议是无状态的协议。一旦数据交换完毕&#xff0c;客户端与服务器端的连接就会关闭&#xff0c;再次交换数据需要建立新的连接&#xff0c;这就意味着服务器无法从连接上跟踪会话。也就是说即使第一次和服务器连接后并且登录成功后&#xff0c;第二次请求…

进程终止(不同情况+如何查看:strerror,echo $?),终止的方法(return,exit,_exit),exit和_exit的不同

目录 进程终止 进程终止是什么 进程终止的情况 代码跑完,结果正确/不正确 提前知道结果 不知道结果 strerror 示例 -- echo $? 代码未跑完,程序崩溃 示例 进程退出方法 return退出码 exit(status) _exit(status) exit()和_exit()的不同 示例 缓冲区位置 进…

华为云RDS数据库(Mysql)不买公网IP无法Navicate连接

前言 最近公司有一个项目甲方为了便宜购买了华为云的ECS服务器与RDS云数据库&#xff08;Mysql&#xff09;进行项目部署&#xff0c;实际部署数据库时发现&#xff0c;华为云的数据库需要购买公网IP才能使用Navicate连接数据库&#xff08;不可思议的我还提交工单确认了一下以…

FlexmonsterPivotTable-2.9.63 LICENSE

FlexmonsterPivotTable-v2.9.63用于网络报告的数据透视表组件&#xff0c;用于可视化业务数据的最强大的 JavaScript 工具 与任何技术堆栈集成 该组件可与任何技术堆栈无缝协作&#xff1a; 与Angular、React、jQuery、Vue等 完美集成 没有服务器端依赖项 只需几行代码 即可开始…

ROS笔记之TF坐标变换

ROS笔记之TF坐标变换 code review! 文章目录 ROS笔记之TF坐标变换一些相关函数的用法tf::TransFormBroadcaster tf1; tf1.sendTransform()tf::StampedTransform()tf::Transform()tf::Vector3()详解br.sendTransform(tf::StampedTransform(tf::Transform(tf::Quaternion::getI…

MacCleanse for Mac:提高Mac性能的必备工具

MacCleanse是一款专为Mac用户设计的强大系统清理垃圾软件&#xff0c;能够全面清理您的系统&#xff0c;提高Mac的速度和性能。它可以帮助您轻松删除各种无用的文件和数据&#xff0c;包括系统缓存、浏览器缓存、下载历史记录、垃圾文件、无效的日志文件和无效的应用程序。通过…

代码随想录算法训练营第23期day40|343. 整数拆分、96.不同的二叉搜索树

目录 一、&#xff08;leetcode 343&#xff09;整数拆分 1.动规五部曲 1&#xff09;确定dp数组&#xff08;dp table&#xff09;以及下标的含义 2&#xff09;确定递推公式 3&#xff09;dp的初始化 4&#xff09;确定遍历顺序 5&#xff09;举例推导dp数组 2.贪心算…

Windows安装WinDbg调试工具

一.下载 微软官网下载SDK的地址&#xff0c;有win11&#xff0c;win10&#xff0c;win8&#xff0c;win7&#xff0c;其他 https://developer.microsoft.com/en-us/windows/downloads/sdk-archive/ 二.安装 打开windbg\Installers\X64 Debuggers And Tools-x64_en-us.msi 要安…