【数据结构】线性表----栈详解

栈(Stack)是一种常见的数据结构,它具有**后进先出(Last In, First Out, LIFO)**的特点。栈的运作类似于物理世界中的叠盘子:最新放上去的盘子最先被拿走,而最底部的盘子最后才能被取出。

如果你先拿底下的盘子,那么就有可能出现整个盘子组全部倒塌碎落一地——这也就是所谓的栈出错。

出栈和入栈

栈有着先进后出的特点。所以它的出栈和入栈也遵循着这个特点。
我们在存取元素的时候,一般是在栈顶进行——也就是所谓的盘子顶;
而另一端称为栈底,一般就是数据结构的头结点。

入栈出栈的顺序只需记住:顺序必须有规律,例如

入栈:1234

出栈可以是:

1 432

234 1

但不能是:

3 1 4 2

在这里插入图片描述

栈的实现

栈既可以用数组也可以用链表形式实现,但由于栈本来就是连续的数据结构,所以使用数组刚好。如果非要使用链表,那么就使用单链表。(单链表可以解决的问题没必要使用双链表)

在这里插入图片描述

栈的基本操作

栈的主要操作包括:

  1. 入栈(Push): 将一个元素放入栈顶。
  2. 出栈(Pop): 移除并返回栈顶的元素。
  3. 查看栈顶元素(Peek/Top): 返回栈顶的元素但不移除它。
  4. 判断栈是否为空(IsEmpty): 检查栈中是否有元素。
  5. 获取栈的大小(Size): 返回栈中元素的数量。

接下来对其进行具体介绍和代码实现。

1.初始化和前期准备

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX 100  // 栈的最大容量,根据情况设置

typedef struct {
    int items[MAX];//容量
    int top;//栈顶元素
} Stack;

// 初始化栈
void initStack(Stack* s) {
    s->top = -1;栈顶指针指向-1的位置
}

// 检查栈是否为空
bool isEmpty(Stack* s) {
    return s->top == -1;
}

// 检查栈是否已满
bool isFull(Stack* s) {
    return s->top == MAX - 1;
}

2.入栈

// 入栈
void push(Stack* s, int item) {
    if (isFull(s)) {
        printf("Stack overflow\n");
        return;
    }
    s->items[++(s->top)] = item;
}

3.出栈

// 出栈
int pop(Stack* s) {
    if (isEmpty(s)) {
        printf("Stack underflow\n");
        exit(EXIT_FAILURE);
    }
    return s->items[(s->top)--];
}

在这里插入图片描述

4.删除和插入元素

// 删除栈中的元素(第n个位置)
void deleteElement(Stack* s, int position) {
    if (isEmpty(s) || position < 0 || position > s->top)//不在栈中无法进行删除 
    {
        printf("Invalid position\n");
        return;
    }

    for (int i = position; i < s->top; i++)//进行遍历寻找要删除的元素
    {
        s->items[i] = s->items[i + 1];
    }
    s->top--;
}

// 在栈中插入元素(第n个位置)
void insertElement(Stack* s, int position, int item) {
    if (isFull(s))//栈溢出
    {
        printf("Stack overflow\n");
        return;
    }
    if (position < 0 || position > s->top + 1) {
        printf("Invalid position\n");
        return;
    }

    for (int i = s->top; i >= position; i--) {
        s->items[i + 1] = s->items[i];
    }
    s->items[position] = item;
    s->top++;
}

栈的使用场景

栈在计算机科学和编程中有广泛的应用,如:

  • 函数调用管理: 编译器使用栈来管理函数调用和返回地址。
  • 表达式求值: 中缀表达式转换为后缀表达式,以及后缀表达式求值。
  • 撤销操作: 许多软件中的撤销(Undo)功能基于栈实现。

栈的注意事项

  1. 溢出问题: 在某些编程语言或环境中,栈的大小是有限的。如果不断入栈而不出栈,可能会导致栈溢出(Stack Overflow)。
  2. 访问限制: 栈只允许对栈顶进行操作,这意味着在栈中间的元素无法直接访问或修改。
  3. 异常处理: 在出栈或查看栈顶元素时,需要处理栈为空的情况,否则会引发错误。

另一种栈

实际上,以上都是栈在计算机科学以及数据结构中的解释,而在另一个计算机领域——计算机系统中,栈实际上是另一种事物。接下来对其进行简单的介绍。

在计算机系统中,栈(堆栈,Stack)是一种用于管理函数调用和局部变量的内存区域。它是计算机内存的一部分,负责存储函数调用过程中的临时数据,包括函数的参数、局部变量、返回地址等。

工作原理

  1. 栈帧(Stack Frame)

    • 每次函数调用时,都会在栈上分配一个新的栈帧。栈帧包含该函数的局部变量、参数和一些控制信息(如返回地址)。
    • 函数执行完毕后,其对应的栈帧会被弹出,返回控制权给调用它的函数。
  2. 入栈(Push)和出栈(Pop)

    • 入栈:当一个函数被调用时,相关数据(如参数和返回地址)会被推入栈中。
    • 出栈:当函数执行完毕后,其栈帧会被弹出,恢复之前的状态。
  3. 栈指针(Stack Pointer, SP)

    • 栈指针是一个寄存器,用于指向当前栈的顶端。每次入栈和出栈操作都会更新栈指针。
  4. 调用约定(Calling Convention)

    • 调用约定定义了函数如何传递参数、如何返回值以及如何维护堆栈。常见的调用约定有Cdecl、Stdcall、Fastcall等。

栈的用途

  1. 函数调用管理

    • 栈用于管理函数调用和返回,确保函数可以正确地调用其他函数,并在完成后返回调用点。
  2. 局部变量存储

    • 函数的局部变量通常存储在栈帧中,便于管理和清理。
  3. 递归支持

    • 栈结构天然支持递归调用,每次递归调用都会在栈上创建新的栈帧。

栈溢出(Stack Overflow)

栈的空间是有限的,如果函数调用层次过深(如递归调用过多),可能会导致栈空间耗尽,发生栈溢出。这种情况下,程序通常会崩溃或抛出异常。

这种栈的机制确保了函数调用的有序进行和局部变量的有效管理。

通过以上的介绍和代码示例,相信你对栈这种数据结构有了一个基本的了解。栈作为一种基础而重要的数据结构,我们会经常使用到它,所以需要熟练掌握。
ck Overflow)**

栈的空间是有限的,如果函数调用层次过深(如递归调用过多),可能会导致栈空间耗尽,发生栈溢出。这种情况下,程序通常会崩溃或抛出异常。

这种栈的机制确保了函数调用的有序进行和局部变量的有效管理。

通过以上的介绍和代码示例,相信你对栈这种数据结构有了一个基本的了解。栈作为一种基础而重要的数据结构,我们会经常使用到它,所以需要熟练掌握。

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

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

相关文章

企业文档加密软件推荐丨2024企业用什么加密软件

在数字化时代&#xff0c;信息安全已经成为企业和个人不可忽视的问题。文档加密软件作为一种保护敏感信息不被非法访问或篡改的有效工具&#xff0c;其重要性日益凸显。通过加密技术&#xff0c;可以确保文档内容在传输和存储过程中的安全性&#xff0c;防止数据泄露和未经授权…

谷粒商城学习笔记-使用renren-fast-vue框架时安装依赖包遇到的问题及解决策略

文章目录 1&#xff0c;npm error Class extends value undefined is not a constuctor or null2&#xff0c;npm warn cli npm v10.8.1 does not support Node.js v16.20.2.3&#xff0c;npm error code CERT_HAS_EXPIRED学习心得 这篇文章记录下使用renren-fast-vue&#xff…

Spring Boot:连接MySQL错误Public Key Retrieval is not allowed

环境&#xff1a; MySQL版本&#xff1a;8.0.17 SpringBoot版本&#xff1a;2.5.15 解决 解决方式很简单&#xff0c;在数据库配置连接字符串spring.datasource.url末尾添加&allowPublicKeyRetrievaltrue即可&#xff0c;如下图&#xff1a; 重新启动&#xff0c;恢复正常…

Ai Native应用开发(一)--数字人

背景 刚参加完24年世界人工智能大会&#xff08;WAIC&#xff09;&#xff0c;聊聊自己的一些感受。这次会明显比去年多很多人&#xff0c;用人山人海来形容应该也不为过。根据我自己粗浅观察参会的人员也比去年更多样化。去年更多还是从业者或者是这块研究人员。今年每个论坛…

Pytorch实战(二):VGG神经网络

文章目录 一、诞生背景二、VGG网络结构2.1VGG块2.2网络运行流程2.3总结 三、实战3.1搭建模型3.2模型训练3.3训练结果可视化3.4模型参数初始化 一、诞生背景 从网络结构中可看出&#xff0c;所有版本VGG均全部使用33大小、步长为1的小卷积核&#xff0c;33卷积核同时也是最小的能…

Linux网络配置管理

目录 一、网络配置 1. 网卡配置 2. 路由 二、 网络信息查看 1.netstat 2. ss 三、 额外的命令 time 一、网络配置 之前我们学过 ifconfig &#xff0c;这个命令可以查看网络接口的地址配置信息&#xff0c;我们只知道它可以查看接口名称、IP 地址、子网掩码等。 但是&a…

java —— tomcat 部署项目

一、通过 war 包部署 1、将项目导出为 war 包&#xff1b; 2、将 war 包放置在 tomcat 目录下的 webapps 文件夹下&#xff0c;该 war 包稍时便自动解析为项目文件夹&#xff1b; 3、启动 tomcat 的 /bin 目录下的 startup.bat 文件&#xff0c;此时即可从浏览器访问项目首页…

windows 11 + kali wsl二合一配置步骤与踩坑

windows 11 kali wsl二合一配置步骤与踩坑 在前几天的某市攻防演练中&#xff0c;在攻防前期&#xff0c;我的虚拟机经常无缘无故出现断网、卡顿等现象&#xff0c;但找不出原因。 为了不影响后续的这些天的攻防演练&#xff0c;我选择在一个晚上通宵 在我的windows 11系统上…

2.作业2

目录 1.作业题目 A图 B代码 2.css盒子模型 0.css盒子模型 1.外边距&#xff08;margin&#xff09; 2.边框&#xff08;border&#xff09; 3.内边距&#xff08;padding&#xff09; ​编辑 3.GET方法与POST方法的区别 学习产出&#xff1a; html的作业 1.作业题目 A图…

无向图中寻找指定路径:深度优先遍历算法

刷题记录 1. 节点依赖 背景: 类似于无向图中, 寻找从 起始节点 --> 目标节点 的 线路. 需求: 现在需要从 起始节点 A, 找到所有到 终点 H 的所有路径 A – B &#xff1a; 路径由一个对象构成 public class NodeAssociation {private String leftNodeName;private Stri…

文华财经盘立方期货通鳄鱼指标公式均线交易策略源码

文华财经盘立方期货通鳄鱼指标公式均线交易策略源码&#xff1a; 新建主图幅图类型指标都可以&#xff01; VAR1:(HL)/2; 唇:REF(SMA(VAR1,5,1),3),COLORGREEN; 齿:REF(SMA(VAR1,8,1),5),COLORRED; 颚:REF(SMA(VAR1,13,1),8),COLORBLUE;

离线查询+线段树,CF522D - Closest Equals

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 522D - Closest Equals 二、解题报告 1、思路分析 考虑查询区间已经给出&#xff0c;我们可以离线查询 对于这类区间离线查询的问题我们通常可以通过左端点排序&#xff0c;然后遍历询问同时维护左区间信息…

数据泄露态势(2024年5月)

监控说明&#xff1a;以下数据由零零信安0.zone安全开源情报系统提供&#xff0c;该系统监控范围包括约10万个明网、深网、暗网、匿名社交社群威胁源。在进行抽样事件分析时&#xff0c;涉及到我国的数据不会选取任何政府、安全与公共事务的事件进行分析。如遇到影响较大的伪造…

《金山 WPS AI 2.0:重塑办公未来的智能引擎》

AITOP100平台获悉&#xff0c;在 2024 世界人工智能大会这一科技盛宴上&#xff0c;金山办公以其前瞻性的视野和创新的技术&#xff0c;正式发布了 WPS AI 2.0&#xff0c;犹如一颗璀璨的星辰&#xff0c;照亮了智能办公的新征程&#xff0c;同时首次公开的金山政务办公模型 1.…

支持图片识别语音输入的LobeChat保姆级本地部署流程

文章目录 前言1. LobeChat对我们有哪些帮助?2. 本地安装LobeChat3. 如何使用LobeChat工具4. 安装Cpolar内网穿透5. 实现公网访问LobeChat6. 固定LobeChat公网地址 前言 本文主要介绍如何在Windows系统电脑本地部署LobeChat&#xff0c;一款高颜值的开源AI大模型智能应用&…

5-google::protobuf命名空间下常用的C++ API----message.h

#include <google/protobuf/message.h> namespace google::protobuf 假设您有一个消息定义为: message Foo {optional string text 1;repeated int32 numbers 2; } 然后&#xff0c;如果你使用 protocol编译器从上面的定义生成一个类&#xff0c;你可以这样使用它: …

Studying-代码随想录训练营day31| 56.合并区间、738.单调递增的数字、968.监控二叉树、贪心算法总结

第31天&#xff0c;贪心最后一节(ง •_•)ง&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 56.合并区间 738.单调递增的数字 968.监控二叉树 贪心算法总结 56.合并区间 文档讲解&#xff1a;代码随想录合并区间 视频讲解&#xff1a;手撕合并区间 题目&#xf…

C语言下结构体、共用体、枚举类型的讲解

主要内容 结构体结构体数组结构体指针包含结构体的结构链表链表相关操作共用体枚举类型 结构体 结构体的类型的概念 结构体实现步骤 结构体变量的声明 struct struct 结构体名{ 数据类型 成员名1; 数据类型 成员名2; ..…

绝地求生PUBG兰博基尼怎么兑换 兰博基尼怎么获得

绝地求生采用虚幻4引擎制作&#xff0c;玩家们会在一个偏远的岛屿上出生&#xff0c;然后展开一场赢家通吃的生存竞赛&#xff0c;最后只会有1个人存活。当然&#xff0c;和其他生存游戏一样&#xff0c;玩家需要在广袤复杂的地图中收集武器、车辆、物资&#xff0c;而且也会有…