线性数据结构之栈结构

栈(Stack)是一种线性数据结构,遵循“后进先出”(Last In, First Out,LIFO)的原则。栈主要有两种基本操作:push(入栈)和 pop(出栈)。在栈中,最新添加的元素最先被移除,类似于一摞盘子:放在最上面的盘子是最后放上去的,但却是最先拿走的。

栈的实现可以基于数组和链表,各有优缺点,适合不同的应用场景。下面将详细介绍栈的定义、特点、优缺点、应用场景以及用数组和链表实现栈的方式。

栈的基本概念

1. 特点

  • LIFO:栈遵循“后进先出”原则。
  • 基本操作
    • Push:将元素放入栈顶。
    • Pop:移除栈顶元素并返回其值。
    • Peek(Top):返回栈顶元素但不移除它。
    • isEmpty:检查栈是否为空。
    • Size:返回栈中元素的数量。

2. 优点

  • 操作简单:只允许在栈顶进行添加或删除操作。
  • 快速:只需要在栈顶操作,时间复杂度为 O(1)。

3. 缺点

  • 容量限制:基于数组的栈实现通常有固定容量,需要判断是否溢出。
  • 仅支持栈顶操作:无法直接访问中间元素。

4. 应用场景

  • 函数调用:程序执行时的调用栈,用来管理方法的调用和返回。
  • 表达式求值:如计算器中的中缀表达式转后缀表达式、表达式求值。
  • 撤销操作:用于实现文本编辑器、图片编辑器的撤销和重做功能。

一、数组实现栈

定义与实现原理

在数组实现的栈中,数组的最后一个位置作为栈顶。入栈时将元素添加到数组末尾,出栈时从数组末尾移除元素。数组实现的栈通常具有固定的大小,且在栈满时可能会引发溢出错误。

1. 优点

  • 访问速度快:数组在内存中是连续存储的,因此访问栈顶元素非常快。
  • 实现简单:操作简单,入栈和出栈仅涉及数组末尾元素。

2. 缺点

  • 固定大小:数组的大小在初始化时确定,不灵活。
  • 栈满溢出:当栈达到数组容量时,将无法继续入栈操作。

3. 适用场景

  • 静态数据栈:如数据量固定的递归栈、调用栈等。

4. 示例代码(Java)

class ArrayStack {
    private int[] stack;
    private int top;       // 栈顶指针
    private int capacity;  // 栈的最大容量

    // 构造函数,初始化栈
    public ArrayStack(int size) {
        stack = new int[size];
        top = -1;  // 栈为空时,top 指向 -1
        capacity = size;
    }

    // 入栈操作
    public void push(int value) {
        if (isFull()) {
            throw new StackOverflowError("栈已满,无法入栈");
        }
        stack[++top] = value;
    }

    // 出栈操作
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空,无法出栈");
        }
        return stack[top--];
    }

    // 返回栈顶元素,但不删除
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空,无法查看栈顶");
        }
        return stack[top];
    }

    // 判断栈是否为空
    public boolean isEmpty() {
        return top == -1;
    }

    // 判断栈是否已满
    public boolean isFull() {
        return top == capacity - 1;
    }

    // 返回栈中元素个数
    public int size() {
        return top + 1;
    }
    
    // 打印栈元素
    public void display() {
        for (int i = 0; i <= top; i++) {
            System.out.print(stack[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(5);
        stack.push(10);
        stack.push(20);
        stack.push(30);
        stack.display(); // 输出:10 20 30

        System.out.println("栈顶元素: " + stack.peek()); // 输出:栈顶元素: 30
        stack.pop();
        stack.display(); // 输出:10 20
    }
}

二、链表实现栈

定义与实现原理

链表实现的栈使用链表的头节点作为栈顶。每次入栈时在链表头部插入一个新节点,每次出栈时删除链表的头节点。这种实现方式可以动态扩展栈的大小。

1. 优点

  • 动态大小:链表实现的栈大小可以动态增长,不受固定容量限制。
  • 内存管理灵活:在需要的时候才分配内存,适合大型数据或频繁变化的数据。

2. 缺点

  • 内存开销大:链表节点需要存储数据和指针,内存消耗较大。
  • 访问速度慢:链表节点在内存中不连续,访问时间相对较长。

3. 适用场景

  • 动态数据栈:如大量动态数据的进出,或内存受限且数据量不确定的场景。

4. 示例代码(Java)

class LinkedListNode {
    int data;
    LinkedListNode next;

    LinkedListNode(int data) {
        this.data = data;
        this.next = null;
    }
}

class LinkedListStack {
    private LinkedListNode top; // 栈顶指针

    // 构造函数,初始化栈
    public LinkedListStack() {
        top = null;
    }

    // 入栈操作
    public void push(int value) {
        LinkedListNode newNode = new LinkedListNode(value);
        newNode.next = top; // 新节点指向当前的栈顶
        top = newNode;      // 栈顶指针指向新节点
    }

    // 出栈操作
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空,无法出栈");
        }
        int value = top.data;
        top = top.next; // 栈顶指针指向下一个节点
        return value;
    }

    // 返回栈顶元素,但不删除
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空,无法查看栈顶");
        }
        return top.data;
    }

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

    // 返回栈中元素个数
    public int size() {
        int count = 0;
        LinkedListNode current = top;
        while (current != null) {
            count++;
            current = current.next;
        }
        return count;
    }

    // 打印栈元素
    public void display() {
        LinkedListNode current = top;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        LinkedListStack stack = new LinkedListStack();
        stack.push(10);
        stack.push(20);
        stack.push(30);
        stack.display(); // 输出:30 20 10

        System.out.println("栈顶元素: " + stack.peek()); // 输出:栈顶元素: 30
        stack.pop();
        stack.display(); // 输出:20 10
    }
}

总结对比

实现方式优点缺点适用场景
数组实现栈访问速度快,适合小规模、静态数据的栈固定大小,可能导致溢出数据量固定、性能要求高的场景,如递归栈
链表实现栈动态大小,适合大量动态数据内存消耗较大,访问速度稍慢数据量不确定且变化频繁的场景,如动态堆栈
  • 数组实现的栈:适合数据量固定或可以预估的情况,比如递归函数调用栈。
  • 链表实现的栈:适合大量数据动态进出,或不确定数据量的情况,比如模拟浏览器前进后退操作栈。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

精心整理教育研究专题数据资源大全-最新出炉_附下载链接

教育研究专题数据资源大全V1.0 下载链接-点它&#x1f449;&#x1f449;&#x1f449;&#xff1a;教育研究专题数据资源大全-最新出炉.zip 资源介绍 一、中国教育统计年鉴面板数据 简介&#xff1a;《中国教育统计年鉴》是由教育部发展规划司根据全国各省、自治区、直辖市…

【论文速读】| PathSeeker:使用基于强化学习的越狱攻击方法探索大语言模型的安全漏洞

基本信息 原文标题: PathSeeker: Exploring LLM Security Vulnerabilities with a Reinforcement Learning-Based Jailbreak Approach 原文作者: Zhihao Lin, Wei Ma, Mingyi Zhou, Yanjie Zhao, Haoyu Wang, Yang Liu, Jun Wang, Li Li 作者单位: Beihang University, Nany…

越权访问漏洞

V2Board Admin.php 越权访问漏洞 ## 漏洞描述 V2board面板 Admin.php 存在越权访问漏洞&#xff0c;由于部分鉴权代码于v1.6.1版本进行了修改&#xff0c;鉴权方式变为从Redis中获取缓存判定是否存在可以调用… V2Board Admin.php 越权访问漏洞 漏洞描述 V2board面板 Admin.ph…

27.旅游推荐管理系统(基于springboot和vue)

目录 1.系统的受众说明 2. 系统需求分析 2.1 任务概述 2.2 功能性需求 2.3 非功能性需求 2.3.1正确性需求 2.3.2安全性需求 2.3.3界面需求 2.3.4时间特殊性需求 2.3.5稳定性需求 2.3.6故障处理能力需求 2.4 开发技术简介 2.4.1 开发工具简介 2.4.2 开发技术…

CCS下载安装(以12.3.0版本为例)

Code Composer Studio 是一个集成开发环境 (IDE)&#xff0c;简称CCS软件。支持 TI 的微控制器和嵌入式处理器产品的开发。Code Composer Studio 包含一整套用于开发和调试嵌入式应用程序的工具。 CCS9.3.0及以上版本不需要License文件&#xff0c;但是CCS旧版本比如CCS5.5.0需…

基于单片机的变频空调系统设计(论文+源码)

1系统总体方案设计 本次基于单片机的变频空调系统设计&#xff0c;选用STC89C52单片机作为系统的主控核心&#xff0c;结合DHT11温湿度传感器实现家居环境中温湿度数据的检测&#xff0c;并设有自动和手动两种模式&#xff0c;在自动模式下&#xff0c;系统会根据按键设定的温…

Visual Studio Code从安装到正常使用

Visual Studio Code的汉化 下载的Visual Studio Code的话可以去应用商店也可以去官网下载。 Visual Studio Code只是一个编译器&#xff0c;不具备编译器功能。因此需要下载一个编译器MinGW MinGW的安装 官网链接MinGW官网链接 一步到位的链接 添加环境变量 进入cmd界面…

图神经网络初步实验

实验复现来源 https://zhuanlan.zhihu.com/p/603486955 该文章主要解决问题&#xff1a; 1.加深对图神经网络数据集的理解 2.加深对图神经网络模型中喂数据中维度变化的理解 原理问题在另一篇文章分析&#xff1a; 介绍数据集&#xff1a;cora数据集 其中的主要内容表示为…

雪花算法生成的ID在返回给前端之后和生成的不一样,到底是什么原因?

一、背景&#xff1a; 最近在做项目的时候发现用雪花算法生成的id传给前端以后跟生成的不一样&#xff0c;就纳闷&#xff0c;在想为什么会出现这样的问题&#xff1f; 二、问题分析&#xff1a; 最开始以为是序列化的问题导致的仔细对比以后发现前端是后几位不一样都是0&…

【大数据学习 | kafka高级部分】kafka中的选举机制

controller的选举 首先第一个选举就是借助于zookeeper的controller的选举 第一个就是controller的选举&#xff0c;这个选举是借助于zookeeper的独享锁实现的&#xff0c;先启动的broker会在zookeeper的/contoller节点上面增加一个broker信息&#xff0c;谁创建成功了谁就是主…

js例轮播图定时器版

要求 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthdevice-width, ini…

jvm学习笔记-轻量级锁内存模型

一&#xff0c;轻量级锁 LockRecord的那个第一个成员变量是拷贝对应锁定了的java对象资源的MarkWord&#xff0c;Lock Record有一个Ptr指针刚开始指向自己&#xff0c;后面这个指针存储在锁定资源的java对象的markword中&#xff0c;后续可以通过java对象的MarkWord快速定位到…

职场浅谈:情商高的“4”种表现,情商高的人才更容易走向成功

职场上&#xff0c;情商高的人总是让人感觉很舒服&#xff0c;也让人情不自禁的愿意和他交往。高情商的人&#xff0c;最大的优点就是让人感觉舒服&#xff0c;这种舒服由内自外&#xff0c;让你情不自禁的对他产生好感&#xff0c;并且发自内心的愿意和他在一起&#xff0c;也…

win11电脑无法找到声音输出设备怎么办?查看解决方法

电脑无法找到声音输出设备是一个常见的问题&#xff0c;尤其是在使用Windows操作系统时。幸运的是&#xff0c;大部分问题都可以通过以下几种方法来解决。 一、检查物理连接 在深入诊断之前&#xff0c;首先要检查硬件连接是否正常。这包括&#xff1a; 确保耳机、扬声器或其…

大模型微调技术 --> LoRA 系列之 QLoRA (省资源能手)

QLoRA 1.摘要 作者提出了QLoRA&#xff0c;一种有效的微调方法&#xff0c;可以减少内存使用&#xff0c;足以在单个48 GB GPU上微调 65B 参数模型&#xff0c;同时保留完整的 16位 微调任务性能。 QLoRA 通过冻结的4位量化预训练语言模型将梯度反向传播到低秩适配器&#x…

Vert.x,应用监控 - 基于Micrometer / Prometheus

对于企业级的应用程序来说&#xff0c;我们需要通过运行指标(metrics)的监控&#xff0c;来了解(监控)程序的运行状态。Vert.x的核心组件内置了大量的运行指标&#xff0c;并支持通过Micrometer来管理这些运行指标并向后端报告。 目前Vertx内置运行指标的核心组件包括: TCP/HTT…

如何用PPT画箭头?用这2个ppt软件快速完成绘图!

ppt怎么画箭头&#xff1f; 有时在ppt中绘制流程图或传达承上启下的含义时&#xff0c;会用到箭头形状&#xff0c;运用到箭头元素来增强表达的清晰度和逻辑性。那可能有人会问&#xff0c;ppt怎么画箭头&#xff1f; 这似乎是一个小问题&#xff0c;但如果你对ppt工具不够熟…

java: 无法访问org.springframework.web.bind.annotation.RequestMapping

一、报错问题 java: 无法访问org.springframework.web.bind.annotation.RequestMapping 二、原因分析 SpringBoot使用了3.0或者3.0以上&#xff0c;因为Spring官方发布从Spring6以及SprinBoot3.0开始最低支持JDK17。所以仅需要将SpringBoot版本降低为3.0以下即可&#xff08;或…

[ DOS 命令基础 3 ] DOS 命令详解-文件操作相关命令

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

【TS】九天学会TS语法——3.TypeScript 函数

今天学习 TypeScript 的函数&#xff0c;包括函数类型、可选参数、默认参数、剩余参数。 函数声明和表达式函数类型可选参数和默认参数剩余参数 在 TypeScript 中&#xff0c;函数是编程的核心概念之一。它们允许我们将代码组织成可重用的块&#xff0c;并提供了强大的抽象能力…