手撕数据结构—栈

Tips

  1. 不得不再次提一下这个语法问题,当数组创建的时候,进行初始化的时候,分为全部初始化或者说部分初始化,对于不完全初始化而言,剩下的部分就全部默认为零。现在比如说你想对整型数组的1万个元素把它全部变成-1,不能够仅仅在一个花括号里面写个-1,只是第一个元素变成-1,然后其他的都变成0了。之后你只能用memset

栈以及先进后出原则

  1. 栈和队列其实也是一个线性表。线性表也就是说你这个数据至少在逻辑上都是依次线性存储,一个一个挨着挨着这样存储这么一个概念。

  1. 栈作为一种特殊的线性表,它只允许在固定的一端进行数据的插入或删除元素操作。进行数据插入和删除操作的那一端就被称为栈顶。因此很容易理解栈中的数据元素遵守后进先出原则。

压栈与出栈

  1. 栈的插入操作叫做进栈/压栈/入栈,这是在栈顶完成的。

  1. 栈的删除操作叫做出栈,这也是在栈顶完成的。所以说它是在同一端进行操作。

  1. 在这边值得一提的是,比如说现在有一堆元素,对于同一进栈的顺序,但是出栈序列可以多种多样,因为并没有规定什么时候可以出栈,你可以使所有元素放进栈里面之后再依次出栈;当然你也可以是在边进栈的过程中可以出栈。我随便举个例子好了:比如说进栈序列为1234,那么出栈序列可以比如为1432,2341,3421,但是断然断然不可能是3124。


栈的实现

  1. 栈的话可以用数组去实现,也可以用链表去实现。肯定是数组,用数组来实现栈的话嘎嘎香啊,比如说你就可以把数组的右端当成一个栈的栈顶。如果要说真有一个弊端的话,那就是说用数组来模拟栈的话需要扩容。

  1. 那如果非要用链表去实现,也是完全可以的:能用单链表就用单链表,你用双向链表的话,还多一个指针呢,能省一点就是一点。

  1. 但是用单链表的话由于尾删啊尾插啊这些操作都需要去从phead开始去往后去遍历去找尾(注意链表不支持下标访问操作),这会相当的麻烦,因此就想了一个办法。把整个链表的左端当成栈顶,那么这样子的话,我的入栈与出栈相当于单链表的头插头删,效率非常之高。

  1. 但如果说非要选一个的话,用数组和链表来模拟的话都非常可以,因为都是O(1)的插入删除(数组的话可以支持下标访问,把数组的右端当成栈顶;链表的话把他的左端当成栈顶,头插头删也是O(1))。可能你还是会选择链表,但是别忘了数组的缓存命中率与利用率比链表要高


栈的创建(创建结构体)

  1. 凡是有多个数据,都放到一个结构体里面。

  1. 对于这个结构体有三个要素,一个是容量,一个是栈顶top,还有一个我是等会儿从堆区开辟内存空间之后返回来的地址,需要用一个指针接收一下,标记一下地址。

typedef int STDataType;
typedef struct Stack
{
    STDataType* p;
    int top;
    int capacity;
}ST;

栈的初始化

  1. 在初始化的时候有一个比较容易出错的地方,就是必须得先搞清楚这个top到底是什么东西,我就假定这个top指向此时此刻的栈顶元素。那么这时候由于要初始化,此时栈顶也压根儿没有任何元素,因此top就指向-1/那如果我说这个top是栈顶元素的下一个位置,那此时此刻初始化的时候,这个top应该指向0。

  1. 我们为了跟之前的顺序表保保持一致,初始化的时候,这个top就给他弄成0。此时此刻,你只需要记住top的一个含义:他现在就表示栈中的元素个数

#define INIT_CAPACITY 5
void STInit(ST* ps)
{
    assert(ps);
    ps->p = (STDataType*)malloc(sizeof(STDataType) * INIT_CAPACITY);
    if (ps->p == NULL)
    {
        perror("STInit::Malloc");
        return;
    }
    ps->top = 0;
    ps->capacity = INIT_CAPACITY;
}

栈的销毁

void STDestroy(ST* ps)
{
    assert(ps);
    free(ps->p);
    ps->p = NULL;
    ps->top = 0;
    ps->capacity = 0;
}

入栈

void STPush(ST* ps, STDataType x)
{
    assert(ps);
    if (ps->top == ps->capacity)
    {
        STDataType* pp = (STDataType*)realloc(ps->p, sizeof(STDataType) * (ps->capacity) * 2);
        if (pp == NULL)
        {
            perror("STPush::Realloc");
            return;
        }
        ps->p = pp;
        ps->capacity *= 2;
    }
    ps->p[ps->top] = x;
    ps->top++;
}

栈的判断是否为空

bool STEmpty(ST* ps)
{
    assert(ps);
    return ps->top==0;
}

栈的求元素个数

int STSize(ST* ps)
{
    assert(ps);
    return ps->top;
}

出栈

void STPop(ST* ps)
{
    assert(ps);
    assert(!STEmpty(ps));
    ps->top--;
}

栈的求栈顶元素

int STTop(ST* ps)
{
    assert(ps);
    assert(!STEmpty(ps));
    return ps->p[ps->top - 1];
}

注:

  1. 虽然从代码上看起来与顺序表非常非常的相像。但是栈的话一定要记住他的特性,那就是后进先出。比如说:23458,我如果要访问5,那么8就必须先出去,如果说我要访问3,那么458就必须先出去。正是因为这种后进先出的特性,这也导致了我们没有写打印栈这种函数,因为栈这种玩意儿,他是不支持去遍历的,这是规定死的。

  1. 这些都是由栈的性质决定的,否则他就不叫做栈了。对于先进栈的数据,想要对他进行任何的操作,包括访问与打印,都必须把它之前栈顶的元素全部弹出去才可以,不然永远只能对栈顶的那个元素动手。

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

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

相关文章

简介SpringBoot

目录 一、简介SpringBoot 二、SpringBoot项目的创建与使用 1、创建SpringBoot项目 2、使用SpringBoot项目 三、 SpringBoot中的配置文件 .properties配置文件 读取配置文件信息 .yml配置文件 读取配置文件信息 四、SpringBoot中的日志文件 1、日志文件简介 2、…

(数据结构)八大排序算法

目录一、常见排序算法二、实现1. 直接插入排序2.🌟希尔排序3. 选择排序4.🌟堆排序5. 冒泡排序7. 🌟快速排序7.1 其他版本的快排7.2 优化7.3 ⭐非递归7. 🌟归并排序7.1 ⭐非递归8. 计数排序三、总结1. 分析排序 (Sorting) 是计算机…

网络安全的特性

0x00 前言 网络安全的特性包括,机密性,完整性,可用性,真实性和不可否认性。详细的内容可以参考如下的内容。 Xmind资源请下载~ 0x01 机密性 机密性(Confidentiality) 意味着阻止未经授权的实体&#x…

【springcloud 微服务】Spring Cloud Alibaba Sentinel使用详解

目录 一、前言 二、分布式系统遇到的问题 2.1 服务可用性问题 2.1.1 单点故障 2.1.2 流量飙升 2.1.3 容错机制 2.2 服务雪崩问题 三、 服务可用性解决方案 3.1 服务容错机制 3.1.1 超时机制 3.1.2 服务限流 3.1.3 隔离 3.2 服务熔断 3.2.1 什么是服务熔断 3…

springcloud学习总结

springcloud 构建微服务项目步骤 导入依赖编写配置文件开启这个功能 Enablexxx配置类 于2023年2月24日下午17点38分开始学习于2023年3月17日晚上20点26分学完总结代码地址:https://gitee.com/liang-weihao/StudySpringcloud学习笔记地址:https://www.…

JavaEE简单示例——基于注解的AOP实现

简单介绍: 之前我们介绍了关于XML的面向切面的编程,通过配置文件的方法,在不修改源代码的情况下完成了对已有方法的增强 除了基于XML配置文件的方式,我们还可以使用更简单的,基于注解的方式。 每一次,我们…

【DBC专题】-12-不同类型报文(应用/诊断/网关/测量标定)在DBC中配置,以及在Autosar各模块间的信号数据流向

点击返回「Autosar从入门到精通-实战篇」总目录 案例背景(共18页精讲):该篇博文将告诉您: 1)Autosar中,不同类型报文(App应用,UDS/OBD诊断,NM网络管理报文,XCP测量标定)的信号数据流向; 2)CAN …

【IoT】嵌入式驱动开发:IIC子系统

IIC有三种接口实现方式 三种时序对比: 图1 IIC子系统组成 图2 图3 IIC操作流程 设备端 1.i2c_get_adapter 2.i2c_new_device(相当于register设备) 3.I2c_put_adapter 驱动端 1.填充i2c_driver 2.i2c_add_driver(相当于register驱动) 3.在probe中建立访问方式 client相…

蓝桥杯刷题冲刺 | 倒计时22天

作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.选数异或2.特殊年份1.选数异或 题目 链接: 选数异或 - 蓝桥云课 (lanqiao.cn) 给定…

C++修炼之筑基期第一层——认识类与对象

文章目录🌷专栏导读🌷什么是面向对象?🌷类的引入🌷什么是类🌷类的定义方式🌷类的访问限定符与封装🌺访问限定符🌺封装🌷类的作用域🌷类的实例化&a…

基于STM32的ADC采样及各式滤波实现(HAL库,含VOFA+教程)

前言:本文为手把手教学ADC采样及各式滤波算法的教程,本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学,通过各式常见滤波的实验结果进行分析对比,搭配VOFA工具直观的展示滤波效果。ADC与滤波算法都是嵌入式较为…

今天,我终于学懂了C++中的引用

文章目录一、前言二、概念介绍三、引用的五大特性1、引用在定义时必须初始化2、一个变量可以有多个引用3、一个引用可以继续有引用4、引用一旦引用一个实体,再不能引用其他实体5、可以对任何类型做引用【变量、指针....】四、引用的两种使用场景1、做参数a.案例一&a…

vue大型商城系统中遇到的问题(上)

一:创建仓库1.领导创建git仓库(参考————这篇文章),新手下载git2.打开cmd终端,将git仓库拉到本地3.进入文件目录,查看分支(新手向——为什么需要创建分支,查看---)4.创…

SAP 发出商品业务配置

SAP发出商品业务配置,即: 出具销售发票时结转成本 一、业务背景: 发出商品业务简单的理解为跨月开票,即出库与开票不在同一个月份。 该业务在系统内的实现方式,为保证成本与收入的配比,在出库时不计算成…

JDBC概述

1.1 数据的持久化持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库来完成。…

LeetCode-复制带随机指针的链表

题目描述: 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的…

蓝桥杯备赛 [day01]|python|迷宫问题|乘积尾零|平方和|切面条|付账问题

目录 0 题目类型 1 迷宫问题 图解 2 乘积尾零 算法解释 用Python处理大数 用C编码 3 平方和 解题技巧 4 切面条 算法解释 5 贪心问题——付账问题 ​编辑 思路 求解步骤 0 题目类型 (1)杂题。不需要算法和数据结构,只需要逻辑、推理的题目&#x…

C/C++每日一练(20230319)

目录 1. 反转链表 II 🌟🌟 2. 解码方法 🌟🌟 3. 擅长编码的小k 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 …

解决win10任何程序打开链接仍然为老旧IE的顽固问题[修改默认浏览器]

文章目录一、问题与修改原因1、着手修改吧2、弯路上探索3、发现祸根二、后话文章原出处: https://blog.csdn.net/haigear/article/details/129344503一、问题与修改原因 我们发现,很多程序默认的网页打开浏览器都是IE,这个很是郁闷&#xff…

jira提交bug规范

一、目的 1)方便开发人员根据bug描述快速进行定位问题原因,减少沟通成本。 2)规范bug编写,可以提现测试团队的专业性、严谨性。 3)可以帮助产品、项目经理及其它人员快速了解bug。 二、说明 本文档主要描述了技术产…
最新文章