数据结构--栈的实现

数据结构–栈的实现

1.栈的概念和结构:

栈的概念:栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

栈的应用:栈其实可以看作一个弹夹,数据就是一个一个的子弹,而子弹在弹夹中确是先进去的要后被发射,最后后进去的反而会先被发射。**进栈就是装子弹的过程,而出栈就是发射子弹的过程。**同时,向栈中插入数据的操作也被称作压栈、进栈、入栈等。取出栈中数据的的操作则被称之为出栈、弹栈。
在这里插入图片描述

栈的结构

下图是向栈中插入数据(Top),只能从栈顶插入数据。
在这里插入图片描述

下图是取出栈中的数据(Pop),只能从栈顶取出数据。
在这里插入图片描述

1.1进出栈的变化形式

  1. 请问现在向栈中顺序插入了1,2,3这三个数据的出栈顺序是不是就是3,2,1呢?
    其实这个出栈的顺序和入栈的顺序有很大的关系.比如先向栈入插入了1和2,然后将这两个取出来,那么取出的顺序就是2,1,接着将3插入栈中,接着就取出3,那么所有元素的出栈的顺序就是2,1,3,这与入栈元素的个数和出栈的情况有关.
  2. 先入栈的元素是不是就只能最后出栈呢??
    答案也是不一定的,举个例子:现在有1,2,3这三个元素,向栈中先插入1和2,接着将这两个元素取出,那么取出的顺序就是2和1,接着将3入栈,然后将3取出来,此时对于整个栈来讲,最先进栈的是1,而最后出栈的则是3.
  3. 此时还是有1,2,3这三个元素,请问有没有一种特定的插入栈顺序(保证1,2,3是按顺序进栈),使得这些元素按照3,1,2(3最先出栈)的顺序出栈呢??
    答案是没有的,无论如何都不可能是3,1,2这样的顺序出栈.因为要想第一个出3,那么肯定需要将1,2,3按次序都插入栈中,将3取出之后,接着栈顶的元素是2,要想取到1,必须先取出2.那么显然是不可能先取出1的.

2.栈的实现

栈的特点:
由于栈拥有顺序表的特点,但是由于栈的特殊性,所以针对栈在操作上会有变化,特别是插入和删除操作分别称作push和pop,英文翻译分别是压和弹,更方便理解.当作是对子弹进行操作就比较好记忆了.

实现方式:
栈的实现可以采用链表和数组两种方式,但是使用数组更方便,用数组对栈进行删除和插入操作时,只需要对数组的下标进行操作即可,代价较小,但是使用链表还需要进行释放节点,新建节点等操作,成本高.
栈中存储的数据可以使用typedef来定义,这样就可以做到自由更改栈中的数据类型.

那么针对的栈的特有的操作有哪些呢 ??

// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);

​ 针对栈这种只能支持在一端进行插入和删除操作的特殊结构,采用数组的0下标处作为栈底是比较好的,因为首元素都在栈底,变化最小.我们使用一个top指针来指向栈顶的元素,也就是在top变量中存储栈顶元素在数组中的下标.
​ top指针就相当于游标卡尺上的游标,游标来回移动就代表中栈顶元素的插入和删除,当游标到了最大容量时,也就是栈满了的时候,就需要扩容了,所以需要一个capacity变量用于记录栈的最大容量,容量满了之后就用realloc函数进行扩容,为数组动态开辟空间.所以栈的定义如下:

typedef int STDataType;
typedef struct Stack
{STDataType* a;int Capacity;//容量int top;//栈顶指针
}Stack;

​ 但是当一开始栈中没有元素时,top的值该设置为多少呢??假如top的初始值是0,想象在坐标-1处有一个元素,那么此时的top相当于就是指向了栈顶元素的下一个位置.假定top的初始值为-1,就说明top指向的是栈顶元素.本文采用的是前者这种方式.

2.1初始化栈

这里首先将栈的容量设置为0.

void StackInit(Stack* ps)
{assert(ps);ps->a = NULL;ps->Capacity = 0;ps->top = 0;//top的值为0则说明指向栈顶的下一个元素
}

2.2向栈中插入数据

向栈中插入数据是push(压)操作,注意:插入之前要注意检查栈的容量是否已经满了.并且向栈中插入数据之后,top一定要自增1.因为本文这里top永远保存的是栈顶元素的下一个位置.

// 入栈
void StackPush(Stack* ps, STDataType data)
{assert(ps);//先检查容量if (ps->top == ps->Capacity){int newCapacity = ps->Capacity == 0 ? 4 : ps->Capacity * 2;ps->Capacity = newCapacity;STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType)*newCapacity);if (tmp == NULL){perror("realloc fail:");exit(-1);}ps->a = tmp;}ps->a[ps->top] = data;ps->top++;
}

2.3获取栈顶数据

获取栈顶数据之前,要检查top是否为0.为0则说明栈已经为空,没有数据了,由于top存储的是栈顶元素的下一个位置,所以返回的值是top-1位置处的值.

// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top);return ps->a[(ps->top)-1];
}

2.4删除栈顶数据

删除栈顶数据之前,要检查top是否为0.为0则说明栈已经为空,没有数据了,同时只需要将top–即可,因为top指向的栈顶元素的下一个位置,相当于此时就把栈顶元素等效删除了.

void StackPop(Stack* ps)
{assert(ps);assert(ps->top);//防止元素个数为0(ps->top)--;//让栈顶指针后移
}

2.5销毁栈

// 销毁栈
void StackDestroy(Stack* ps)
{assert(ps);free(ps->a);ps->Capacity = ps->top = 0;ps = NULL;
}

2.6获取栈中有效元素的个数

既然top指向的是栈顶元素的下一个位置的下标,那么top的值刚好就是栈中的元素的个数.

// 获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps);return ps->top;
}

2.7检测栈是否为空

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{assert(ps);return (ps->top) == 0;
}

3.栈的作用

有的小伙伴可能会想,可以直接使用数组或链表实现这些功能即可.为什么还需要单独设计出来这个栈的数据结构呢?其实,栈的引入简化了程序设计问题,划分了不同层次,使得思考范围缩小,更加聚焦于我们要解决的问题的核心,反之,像数组等,需要我们分散精力取考虑元素的下标的增减问题等问题,反而掩盖了问题的本质.

4.结束

栈就讲到这里啦,欢迎各位小伙伴在评论区中指正本文的不足.下期见!

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

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

相关文章

PostMan的学习

PostMan的学习 目录 环境变量和全局变量接口关联内置动态参数以及自定义动态参数实现业务闭环Postman断言批量运行collection数据驱动之CSV文件和JSON文件测试必须带请求头的接口Mock Serviers 服务器Cookie鉴权NewmanPostManNewManjenkins实现接口测试持续集成 参考资料&am…

Kerberos常见报错汇总

一.kdb5_util: Password mismatch while reading master key from keyboard 1>.错误复现 2>.错误原因分析 在初始化Kerberos数据库时需要输入密码,2次密码输入不一致就会导致该错误。 3>.解决方案 重新执行"kdb5_util -r YINZHENGJIE.COM create -s…

Mendix中的依赖管理:npm和Maven的应用

序言 在传统java开发项目中,我们可以利用maven来管理jar包依赖,但在mendix项目开发Custom Java Action时,由于目录结构有一些差异,我们需要自行配置。同样的,在mendix项目开发Custom JavaScript Action时,…

数据集笔记:旧金山共享单车OD数据

数据地址:System Data | Bay Wheels | Lyft

使用不同尺寸的传感器拍照时,怎么保证拍出同样视场范围的照片?

1、问题背景 使用竞品机做图像效果对比时,我们通常都会要求拍摄的照片要视场范围一致,这样才具有可比性。之前我会考虑用同样焦距、同样分辨率的设备去拍照对比就可以了,觉得相机的视场范围只由镜头焦距来决定。 但如果对于不同尺寸的传感器…

【Java 进阶篇】MySQL 数据控制语言(DCL):管理用户权限

MySQL 是一个强大的关系型数据库管理系统,提供了丰富的功能和选项来管理数据库和用户。数据库管理员(DBA)通常使用数据控制语言(Data Control Language,简称 DCL)来管理用户的权限和访问。 本文将详细介绍…

定义现代化实时数据仓库,SelectDB 全新产品形态全面发布

导读:9 月 25 日,2023 飞轮科技产品发布会在线上正式召开,本次产品发布会以 “新内核、新图景” 为主题,飞轮科技 CEO 马如悦全面解析了现代化数据仓库的演进趋势,宣布立足于多云之上的 SelectDB Cloud 云服务全面开放…

数据结构——堆(C语言)

本篇会解决一下几个问题: 1.堆是什么? 2.如何形成一个堆? 3.堆的应用场景 堆是什么? 堆总是一颗完全二叉树堆的某个节点总是不大于或不小于父亲节点 如图,在小堆中,父亲节点总是小于孩子节点的。 如图&a…

华为ensp单臂路由及OSPF实验

单臂路由及OSPF实验 1.1实验背景 在这个实验中,我们模拟了一个复杂的网络环境,该网络环境包括多个子网和交换机。这个实验旨在帮助网络工程师和管理员了解如何配置单臂路由和使用开放最短路径优先(OSPF)协议来实现不同子网之间的…

从 低信噪比陆上地震记录 解决办法收集 到 走时层析反演中的折射层析调研

目录 (前言1) 关于背景的回答:(前言2) 现有的降低噪声, 提高信噪比的一些特有方法的论文资料 (传统策略):1. 关于波形反演与走时层析反演2. 折射层析3. 用一个合成数据来解释折射层析反演的思路4. 其他层析反演方法:5. 关于层析反演的一些TIPS (可补充)参考文献: 降噪有关资料参…

SpringBoot使用Docker并上传至DockerHub

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情 文章目录 1.系列文章2.构建docker镜像的方式3.docker操作3.1 安装docker3.2 查看docker镜像3.3 本地运行docker3.4 修改tag3.5 推送docker镜像3.6 远端server拉取d…

FOC控制算法

目录 一、FOC介绍 二、FOC基本概念 1、为什么是三相? 2、FOC矢量控制总体算法简述 3、为什么FOC不一定需要电流采样?参考链接 4、FOC的分类 (1)有感FOC与无感FOC 三、FOC中电流采样 参考链接 1、高端采样 2、低端采样 …

AI项目十三:PaddleOCR训练自定义数据集

若该文为原创文章,转载请注明原文出处。 续上一篇,PaddleOCR环境搭建好了,并测试通过,接下来训练自己的检测模型和识别模型。 paddleocr检测模型训练 1、准备数据集 在PaddleOCR目录下新建文件夹:train_data, 这个…

深度学习:模型训练过程中Trying to backward through the graph a second time解决方案

1 问题描述 在训练lstm网络过程中出现如下错误&#xff1a; Traceback (most recent call last):File "D:\code\lstm_emotion_analyse\text_analyse.py", line 82, in <module>loss.backward()File "C:\Users\lishu\anaconda3\envs\pt2\lib\site-packag…

【0223】源码剖析smgr底层设计机制(3)

1. smgr设计机制 PG内核中smgr完整磁盘存储介质的管理是通过下面三部分实现的。 1.1 函数指针结构体 f_smgr 函数指针结构体 f_smgr。 通过该函数指针类型,可完成类似于UNIX系统中的VFD功能,上层只需要调用open()、read()、write()等系统函数,用户不必去关系底层的文件系统…

「网页开发|前端开发|Vue」09 Vue状态管理Vuex:让页面根据用户登录状态渲染不同内容

本文主要介绍如何通过Vue的状态管理框架Vuex来管理一些被不同组件或不同页面共同使用的数据&#xff0c;然后展示如何通过状态管理用户信息&#xff0c;并且在具体页面获取用户信息&#xff0c;并且根据用户信息的不同展示不同的页面内容。 文章目录 本系列前文传送门一、场景…

C++核心编程--对象篇

4.2、对象 4.2.1、对象的初始化和清理 用于对对象进行初始化设置&#xff0c;以及对象销毁前的清理数据的设置。 构造函数和析构函数 防止对象初始化和清理也是非常重要的安全问题 一个对象或变量没有初始化状态&#xff0c;对其使用后果是未知的同样使用完一个对象或变量&…

【C++学习】多态

目录 一、多态的概念 1. 概念 二、多态的定义及实现 2.1 多态的构成条件 2.2 虚函数 2.3 虚函数的重写 2.4 C11 override 和 final 2.5 重载、覆盖(重写)、隐藏(重定义)的对比 三、抽象类 3.1 概念 3.2 接口继承和实现继承 四、多态的原理 4.1 虚函数表 4.2 多态的…

【大规模 MIMO 检测】基于ADMM的大型MU-MIMO无穷大范数检测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

CCF CSP认证 历年题目自练Day17

CCF CSP认证 历年题目自练Day17 题目一 试题编号&#xff1a; 201803-1 试题名称&#xff1a; 跳一跳 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   近来&#xff0c;跳一跳这款小游戏风靡全国&#xff0c;受到不少玩家的喜爱…