【数据结构】栈和队列(上)

目录

一、栈(先进后出、后进先出的线性表)

1、栈的概念及结构

2、栈的底层结构分析

二、代码实现

1、定义一个栈

2、栈的初始化

3、入栈

3、增容

4、出栈

5、取栈顶

6、销毁栈


一、栈(先进后出、后进先出的线性表)

1、栈的概念及结构

栈:一种特殊的线性表,只允许在固定的一端进行插入和删除数据的操作。进行数据插入、删除的一端为栈顶,不可进行操作的一端则是栈底。对于任意一个数据结构,我们都要分析一下它的逻辑结构和物理结构,既然是线性表,那么说明逻辑结构一定是线性的

逻辑结构:是线性的

物理结构:也是线性的

对于栈的操作主要有如下两个:

一个是压栈,另一个则是出栈。其中压栈是栈的插入操作(也叫做进栈、入栈);出栈则是栈的删除操作,出数据也在栈顶。

2、栈的底层结构分析

既然我们已经对栈这一个数据结构的概念有了初步的了解,那么现在,我们来深入探讨一下,栈的底层结构是什么?既然他是线性的,那么他是数组还是链表呢?

我们从这里分析:

我们可以从上图看到链表的结构,由于栈只能从栈顶操作数据,假设栈的底层是链表,如果链表的尾部为栈顶的话,每一次访问栈顶都要去遍历一次链表,那么无疑使时间复杂度增加到了O(N),相反,如果链表的头部为栈顶,对数据进行插入删除时的时间复杂度就会好很多,为O(1)。

我们来画个图看看数组,从数组中插入删除数据,可以把数组的尾当做栈顶插入删除数据,时间复杂度认为O(1),既然这样,链表和数组作为栈的底层结构,入栈和出栈的时间复杂度都为O(1),那么,我们来换个维度来考虑:

以上是使用链表和数组结构写的栈的构造代码,我们可以看出,左图中的结构使用了链表,每向栈中插入一个数据,空间不仅仅会增加int类型的4字节,还会增加指针8字节的大小,相比于数组结构,链表结构对空间的使用会更大,所以,我们还是更推荐用数组作为栈的底层结构。

二、代码实现

下面,我们来实现一下栈的代码:

1、定义一个栈

我们要定义一下栈的结构,由于栈的底层是数组,又要开辟空间,我们就定义一个动态的数组好了:

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

2、栈的初始化

下面,我们来定义一个初始化方法

void StackInit(ST* ps)
{ps->arr = NULL;ps->top = ps->capacity = 0;
}

3、入栈

当要向数组插入数据首先要看栈中是否为空,若不为空插入数据后ps->top要++,指向栈顶

3、增容

注意:这里又出现一个问题,当ps->top==ps->capacity时,说明空间已经不够了,如果要继续插入数据,我们需要进行一个增容操作:

这里,ps->capacity=newcapacity

void StackPush(ST* ps,STDatatype x)
{assert(ps);//这里做一个断言操作,防止对空指针解引用if(ps->top == ps->capacity){int newcapacity = ps->capacity==0?4:2*ps->capacity;(STDataType*)tmp = (STDataType*)realloc(ps->arr,newcapacity*sizeof(STDataType));if(tmp == NULL){perror("realloc fail!");exit(1);    }ps->arr = tmp;ps->capacity = newcapacity;}ps->arr[ps->top++] = x;
}

4、出栈

出栈操作:

每当遇到数据结构中的出数据操作时,我们都要考虑其是否有数据可以为我们所用,所以写出栈操作之前,我们首先要判断栈是否为空,这里,我们可以定义一个方法:

bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;//判断top(即有效数据个数是否为零,如果为零,则返回ture)
}

其次,假设,ps->top,不为零,则出栈操作直接可以写成--ps->top;

void Stackpop(ST* ps)
{assert(ps);if(!StackEmpty(ps)){--ps->top;    }
}

5、取栈顶

下一个操作是:取栈顶操作,与出栈顶(有效的数据个数会减少)操作不同,去栈顶操作不会删除数据,而只是将栈顶的数据复制一下并使用。

STDataType StackTop(ST* ps)
{assert(!StackEmpty(ps);return ps->arr[ps->top-1];
}

6、销毁栈

接下来,我们看一下对于栈的销毁操作:

void StackDestroy(ST* ps)
{if(ps->arr)free(ps->arr);ps->arr = NULL;//这里有一点ps->top = ps->capacity = 0;
}

这里有一个小tips:将ps->arr = NULL,这里可能有同学会有疑问,为什么写出栈操作时,只需要--ps->top,不需要将数据free,这是因为,在数组中,arr表示数组首元素的地址,如果你将ps->arr free掉,那么整个数组的数据都会被销毁,而链表的每一个空间都是独立存在的,假设你将上一个结点的空间销毁了,不会影响下一个结点,数组则不然。

以下是测试代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"void test01()
{ST st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 5);/*StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);*//*while (!StackEmpty(&st)){int top = StackTop(&st);printf("%d ", top);StackPop(&st);}*/int size = StackSize(&st);printf("size:%d", size);StackDestroy(&st);
}int main()
{test01();return 0;
}

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

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

相关文章

Vue 3 官方 Hooks 的用法与实现原理

Vue 3 引入了 Composition API,使得生命周期钩子(hooks)在函数式风格中更清晰地表达。本篇文章将从官方 hooks 的使用、实现原理以及自定义 hooks 的结构化思路出发,全面理解 Vue 3 的 hooks 系统。 📘 1. Vue 3 官方生…

大语言模型 17 - MCP Model Context Protocol 介绍对比分析 基本环境配置

MCP 基本介绍 官方地址: https://modelcontextprotocol.io/introduction “MCP 是一种开放协议,旨在标准化应用程序向大型语言模型(LLM)提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…

云原生安全之PaaS:从基础到实践的技术指南

🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 云原生安全之PaaS:从基础到实践的技术指南 一、基础概念 PaaS(Platform as a Service)平台 PaaS是一种云计算服务模型,为开发者提供应用程序的开发、部署和运行环境,涵…

Chrome中http被强转成https问题

原因:2023年11月1日,chrome发布HTTPS-Upgrades功能,在用户访问 http:// 的旧链接之后,会自动尝试跳转到通过加密的 https:// 协议,访问该网站。且探测到 https 服务存在也会自动改成 https。 亲测两种方案可行&#x…

Linux 操作文本文件列数据的常用命令

文章目录 Linux 操作文本文件列数据的常用命令基本列处理命令高级列处理列数据转换和排序列数据统计和分析 Linux 操作文本文件列数据的常用命令 Linux 提供了多种强大的命令来处理文本文件中的列数据,以下是一些最常用的命令和工具: 基本列处理命令 c…

如何理解线性判别分析(LDA)算法?

在高维数据空间中,特征变量呈指数级增长,信息分布密集且复杂。研究者在面对海量特征时,仿佛置身于一幅结构高度抽象且维度交织的多变量图景之中,其解析与建模犹如在一幅复杂的数据宇宙图谱中导航,既需理论框架的指引,也依赖于算法工具的精确刻画。如何从众多维度中筛选出…

鸿蒙UI开发——Builder函数的封装

1、问题引入 我们在开发中可能会遇到这样一个问题:将一个Builder修饰后的函数用变量或者数组记录下来,在业务其他地方使用这些Builder函数。 举个例子,有下面一段代码: Builderfunction builderElement() {}let builderArr: Fu…

ARM笔记-ARM指令集

第三章 ARM指令集 3.1 ARM指令集简介 ARM微处理器的ARM指令集 ,所有的指令长度都是32位 ,并且大多数指令都在一个单独指令周期内执行。 主要特点: 指令是条件执行的ARM微处理器的指令集是加载/存储型的在多寄存器操作指令中一次最多可以完成…

Spring Boot接口通用返回值设计与实现最佳实践

一、核心返回值模型设计(增强版) package com.chat.common;import com.chat.util.I18nUtil; import com.chat.util.TraceUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter;import java.io.Serializable;/*** 功能: 通…

2025年上半年软件架构师考试回忆版【持续更新】

文章目录 案例分析1、端AI相对于云AI的优势2、redis持久化,主从库3、解释器架构风格4、知识图谱5、区块链 论文1、基于事件驱动的模型2、多模型数据库及其应用3、负载均衡设计方法4、论软件测试理论及其应用 考试感受 2025年软件考试架构考试于5月24日如期举行&…

Windows下编译Zipios

本文记录在Windows下编译Zipios的流程。 注1:文章内容会不定期更新。 零、环境 操作系统Windows 11VS Code1.92.1Git2.34.1Visual StudioVisual Studio Community 2022CMake3.22.1 一、安装依赖 二、编译 2.1 下载代码 git clone https://github.com/Zipios/Zi…

SOC-ESP32S3部分:11-任务创建

飞书文档https://x509p6c8to.feishu.cn/wiki/EH3owsPahisvl6kL6k3cqaQ3n0g 在我们学习单片机的时候,main函数入口中一般有一个while大循环在不停轮询,如果我们需要实现多种不同的业务,就需要用到状态机,根据不同时刻的要求执行不…

[Git] 如何进行版本回退

版本控制系统最重要的能力之一,就是能够轻松地在项目的不同历史版本之间切换。有时,你可能发现最近的修改引入了严重问题,或者需要回到之前的某个节点重新开始。这时,“版本回退”功能就派上用场了。 版本回退:反方向…

易贝平台关键字搜索技术深度解析

一、核心搜索机制 关键词匹配原理 采用TF-IDF算法计算关键词权重 支持同义词扩展(如"phone"匹配"cellphone") 标题权重 > 副标题 > 商品描述 搜索排序因素 # 搜索权重模拟计算 def calculate_rank(keyword, item): title…

深度剖析 MCP SDK 最新版:Streamable HTTP 模式

好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受. 目录 一、概述 二、快速上手:开启 Streamable HTTP 服务端开启 客户端连接 三、深入两个核心参数 stateless_http json_resp…

树莓派开箱上手教程(无需显示器版)

树莓派开箱上手教程(无需显示器版) 硬件准备 名称参数电源适配器5V电源适配器,至少需要3A的额定电流,配备USB Type-C输出接头microSD卡用来将树莓派的操作系统安装到上边,至少需要8GB容量,一般建议16GB及以…

MySQL强化关键_015_存储过程

目 录 一、概述 1.说明 2.优点 3.缺点 二、存储过程的操作 1.创建 2.调用 3.查看 4.删除 三、变量 1.系统变量 (1)说明 (2)查看系统变量 (3)设置系统变量 2.用户变量 (1&…

动态规划dp

这里写目录标题 动态规划01背包完全背包多重背包混合背包二维费用的背包分组背包有依赖的背包背包问题求方案数背包问题求具体方案数位 DP状压 DP常用例题 动态规划 01背包 有 n n n 件物品和一个容量为 W W W 的背包,第 i i i 件物品的体积为 w [ i ] w[i] w…

arcgis js统计FeatureLayer的椭球面积、平面面积

1、导入依赖 import FeatureLayer from arcgis/core/layers/FeatureLayer import { geodesicArea, planarArea, simplify } from arcgis/core/geometry/geometryEngine; import { project, load as projectionLoad } from arcgis/core/geometry/projection2、初始化project o…

2.2.1 05年T2

引言 本文将从一预习、二自习、三学习、四复习等四个阶段来分析2005年考研英语阅读第二篇文章。为了便于后续阅读,我将第四部分复习放在了首位。 四、复习 方法:错误思路分析总结考点文章梳理 4.1 错题分析 题目:26(细节题&…