当前位置: 首页 > article >正文

【C】初阶数据结构5 -- 栈

  前面学习了两种最基本的数据结构 -- 顺序表和链表,接下来就可以基于这两种数据结构来实现其他数据结构了。其实,其他的数据结构的物理结构要么是数组,要么就是链表,所以学好顺序表和链表是学好其他数据结构的基础。接下里,我们就来看一个新的数据结构 -- 栈。


目录

1  栈的概念与特点

2  栈的结构 

1) 逻辑结构

2) 物理结构 

 3  栈的基本操作的实现

1) 初始化和销毁

2) 入栈与出栈、

(1) 入栈

(2) 出栈

3)  取栈顶元素、判空、获取有效元素个数

4  代码


重点一  栈的特点

1  栈的概念与特点

  栈:一种特殊的线性表,其只允许在一端进行插入和删除数据。插入和删除数据的一端叫做栈顶,另一端叫做栈底。

  入栈(压栈):往栈中插入数据的操作叫做入栈。

  出栈:栈中删除数据的操作叫做出栈。

  特点:栈中的数据遵循LIFO原则(last in first out),也就是后进先出原则。

  栈的特点特别重要,一般使用栈都是因为其后进先出的特点,下面来做一个题来理解一下其后进先出的特点:

假设有一个栈,数据入栈的先后顺序为 a b c d e ,请在以下选项中选出错误的出栈顺序()A. a b c d e                    B. c b d a eC. d b c a e                    D. e d c b a

 该题的正确答案为 C,因为如果 d 先出栈的话,说明 a,b,c 均以入栈,如何要接着出栈的话,应是 c 先出栈,而不是 b 先出栈。

  需要注意的一点就是,出栈顺序并不是等数据全部入栈之后才能出栈。比如 A 选项,就是入栈一个数据,然后出栈一个数据。


重点二  栈的结构

2  栈的结构 

1) 逻辑结构

  我们可以把栈想象成以下的一个结构:

2) 物理结构 

  栈的物理结构既可以选择用链式结构来实现,也可以选择用数组,也就是顺序表来实现。这里选择使用数组来实现,因为栈后进先出的特性,规定了其只能在尾部进行插入和删除数据,而对于顺序表来说,在尾部插入和删除数据又十分方便,所以这里选择使用顺序表来实现栈。

  既然是使用顺序表来实现栈,所以栈的结构和顺序表十分相似,只不过就是把 size 变为了 top,用来表示栈的顶部元素的位置:

//将int定义为栈里面的数据类型
typedef int STDataType;
//栈的结构
typedef struct Stack
{STDataType* arr;//栈中的存放数据的数组int capacity;//栈的容量大小int top;//栈顶
}ST;

重点三  实现栈

 3  栈的基本操作的实现

  对于一个栈来说,其主要操作只有入栈、出栈、取栈顶元素、初始化、销毁、判空、获取有效元素个数。

1) 初始化和销毁

    栈的初始化和销毁与顺序表可以说是一模一样,这里就不做多余讲解,可以去回顾一下顺序表(也可以看下面代码理解一下)。


2) 入栈与出栈、

(1) 入栈

  入栈的操作就相当于顺序表中的尾差,其基本过程如图所示:

可以看到,就是顺序表的尾插操作,只不过就是把 size 变成了 capacity 而已。

(2) 出栈

  出栈就是顺序表的尾删,所以只需要让 --top 就可以了。


3)  取栈顶元素、判空、获取有效元素个数

  这3个操作的实现都很简单。取栈顶元素就是返回 arr 数组中 top - 1 下标的数据,但要注意栈要非空,才能返回栈顶元素,所以要先对栈是否为空断言;判空就是判断 top 是否等于0;获取有效元素个数就是返回 top 。


4  代码

Stack.h文件:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int STDataType;
typedef struct Stack
{STDataType* arr;int capacity;int top;
}ST;//初始化
void STInit(ST* ps);
//销毁
void STDestroy(ST* ps);
//入栈
void STPush(ST* ps, STDataType x);
//出栈
void STPop(ST* ps);
//取栈顶元素
STDataType STTop(ST* ps);
//获取栈中有效元素个数
int STSize(ST* ps);
//栈是否为空
bool STEmpty(ST* ps);

Stack.c文件:

#include"Stack.h"//初始化
void STInit(ST* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}//销毁
void STDestroy(ST* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->capacity = ps->top = 0;
}//入栈
void STPush(ST* ps, STDataType x)
{//相当于顺序表的尾插assert(ps);//如果数组满了。需要增容if (ps->capacity == ps->top){int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, sizeof(STDataType) * newCapacity);if (tmp == NULL){perror("realloc fail!\n");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//不要忘记让top++ps->arr[ps->top++] = x;
}
//栈是否为空
bool STEmpty(ST* ps)
{assert(ps);//判断top是否为0就可以了return ps->top == 0;
}
//出栈
void STPop(ST* ps)
{//相当于顺序表的尾删assert(!STEmpty(ps));--ps->top;
}//取栈顶元素
STDataType STTop(ST* ps)
{assert(ps);//栈不能为空assert(!STEmpty(ps));//只取栈顶元素,不删除数据int pos = ps->top - 1;return ps->arr[pos];
}//获取栈中有效元素个数
int STSize(ST* ps)
{assert(ps);return ps->top;
}

test.c文件:

#include"Stack.h"
void Test4()
{ST st;STInit(&st);//测试入栈STPush(&st, 1);STPush(&st, 2);STPush(&st, 3);STPush(&st, 4);for (int i = 0; i < st.top; i++){printf("%d ", st.arr[i]);}printf("\n");//测试出栈与取栈顶元素STPop(&st);STPop(&st);STPop(&st);STPop(&st);//STPop(&st);/*int ret = STTop(&st);printf("%d ", ret);printf("\n");for (int i = 0; i < st.top; i++){printf("%d ", st.arr[i]);}printf("\n");*/bool ret1 = STEmpty(&st);if (ret1){printf("栈为空!\n");}else{printf("栈不为空!\n");}int ret = STSize(&st);printf("%d ", ret);STDestroy(&st);
}
int main()
{Test4();return 0;
}

   可以看到实现栈,其实就是实现顺序表的部分接口,学好顺序表和链表是实现其他数据结构的基础。所以一定要把基础学扎实,才能越学越好。

相关文章:

【C】初阶数据结构5 -- 栈

前面学习了两种最基本的数据结构 -- 顺序表和链表&#xff0c;接下来就可以基于这两种数据结构来实现其他数据结构了。其实&#xff0c;其他的数据结构的物理结构要么是数组&#xff0c;要么就是链表&#xff0c;所以学好顺序表和链表是学好其他数据结构的基础。接下里&#xf…...

Spring MVC Streaming and SSE Request Processing SSE可以实现chatgpt一次请求分批次响应的效果

1. Introduction This simple tutorial demonstrates the use of several asynchronous and streaming objects in Spring MVC 5.x.x. Specifically, we’ll review three key classes: ResponseBodyEmitterSseEmitterStreamingResponseBody Also, we’ll discuss how to i…...

Python学习心得格式化字符串的format

format的格式控制&#xff1a;format控制格式有6种&#xff0c;分别对所输出的内容进行控制。 语法结构&#xff1a; print({0:所设置的格式}.format(字符串)) 1.引号符号&#xff1a;&#xff1a; 2.填充&#xff1a;所设定的要填充的内容&#xff0c;比如说填充* 3.对齐…...

CNN-LSSVM卷积神经网络最小二乘支持向量机多变量多步预测,光伏功率预测

代码地址&#xff1a;CNN-LSSVM卷积神经网络最小二乘支持向量机多变量多步预测&#xff0c;光伏功率预测 CNN-LSSVM卷积神经网络最小二乘支持向量机多变量多步预测&#xff0c;光伏功率预测 一、引言 1、研究背景和意义 光伏发电作为可再生能源的重要组成部分&#xff0c;近…...

python io.StringIO类介绍

io.StringIO 是 Python io 模块中的一个类,用于在内存中创建类似文件的对象,专门用于处理 字符串数据。它的行为类似于文件对象,可以进行 读 (read)、写 (write)、查找 (seek) 等操作,而不需要实际创建物理文件。 1. io.StringIO 的作用 模拟文件操作,避免读写实际文件,提…...

架构设计系列(三):架构模式

一、概述 关于移动应用开发中常见的架构模式&#xff0c;这些模式是为了克服早期模式的局限性而引入。常见的 架构模式有&#xff1a; MVC, MVP, MVVM, MVVM-C, and VIPER 二、MVC, MVP, MVVM, MVVM-C, and VIPER架构模式 MVC、MVP、MVVM、MVVM-C 和 VIPER 是移动应用开发中…...

[C++语法基础与基本概念] std::function与可调用对象

std::function与可调用对象 函数指针lambda表达式std::function与std::bind仿函数总结std::thread与可调用对象std::async与可调用对象回调函数 可调用对象是指那些像函数一样可以直接被调用的对象&#xff0c;他们广泛用于C的算法&#xff0c;回调&#xff0c;事件处理等机制。…...

强化学习-NPG

NPG来源于PG算法&#xff0c;是TRPO算法的前身。 随机梯度策略算法的输入输出问题&#xff08;不得不考虑的&#xff09;&#xff1a; PG算法用函数表示策略&#xff0c;该表示方法不直接输出动作&#xff08;有别于“确定性梯度策略”&#xff09;&#xff0c;那么就有两种可以…...

JVM学习与理解

目录 JVM介绍&#xff1a; 解释&#xff1a; 特点&#xff1a; 整体构成&#xff1a; 执行过程&#xff1a; 运行时数据区&#xff1a; Java堆剖析&#xff1a; 堆内存区域划分 为什么要分代呢&#xff1f; 内存分配&#xff1a; 新生区与老年区配置比例&#xff1a…...

ArrayList、LinkedList、Vector

ArrayList 和 LinkedList 的区别是什么&#xff1f; 数据结构实现&#xff1a;ArrayList 是动态数组的数据结构实现&#xff0c;而 LinkedList 是双向链表的数据结构实 现。 随机访问效率&#xff1a;ArrayList 比 LinkedList 在随机访问的时候效率要高&#xff0c;因为 Linked…...

数据守护者:备份文件的重要性及自动化备份实践

在信息化社会&#xff0c;数据已成为企业运营和个人生活的重要组成部分。无论是企业的核心业务数据&#xff0c;还是个人的珍贵照片、重要文档&#xff0c;数据的丢失或损坏都可能带来无法估量的损失。因此&#xff0c;备份文件的重要性愈发凸显&#xff0c;它不仅是数据安全的…...

【LLM强化学习】Deep使用的强化学习方法 GRPO 理论理解与实践

一、写在前面 预训练 赋予了 LLMs 广阔的知识和强大的语言能力,但模型本身并不知道 什么是好的,什么是坏的,什么是符合人类偏好的。我们需要 引导 LLMs 学习人类的价值观,理解指令背后的意图,并生成更安全、更可靠、更符合人类期望的文本。强化学习(Reinforcement Learn…...

初阶c语言(练习题,猜随机数,关机程序)

目录 第一题&#xff0c;使用函数编写一个随机数&#xff0c;然后自己猜&#xff0c;猜随机数 第二道题&#xff08;关机程序&#xff09; 实现代码&#xff08;关机程序&#xff09; 实现代码&#xff08;猜数字&#xff09; 前言&#xff1a; 学习c语言&#xff0c;学习…...

TypeScript 与后端开发Node.js

文章目录 一、搭建 TypeScript Node.js 项目 &#xff08;一&#xff09;初始化项目并安装相关依赖 1、创建项目目录并初始化2、安装必要的依赖包 &#xff08;二&#xff09;配置 TypeScript 编译选项&#xff08;如模块解析方式适合后端&#xff09; 二、编写服务器代码 &a…...

基于SSM+uniapp的鲜花销售小程序+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、商户功能模块&#xff1a;用户管理、商户管理、鲜花分类管理、鲜花管理、订单管理、收藏管理、购物车、充值、下单等技术选型&#xff1a;SSM&#xff0c;Vue&#xff08;后端管理web&#xff09;&#xff0c;uniapp等测试环境&#x…...

数据开放共享和平台整合优化取得实质性突破的智慧物流开源了

智慧物流视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本可通过边缘计算技术…...

2025互联网医院系统源码解析:AI陪诊问诊APP的未来发展

2025年&#xff0c;AI陪诊问诊APP将如何在技术上创新&#xff0c;如何推动互联网医院的进一步发展&#xff0c;成为了我们今天探讨的核心内容。在本文中&#xff0c;我们将通过源码解析&#xff0c;深入分析这一前沿技术的未来发展趋势&#xff0c;帮助广大从业者更好地理解这一…...

【NLP 22、语言模型 language model】

有时候我也想听听&#xff0c;我在你心里&#xff0c;是什么样子 —— 25.1.12 一、什么是语言模型 语言是灵活的&#xff0c;也是有规律的 了解一门语言的人可以判断一句话是否“合理” 通俗来讲&#xff0c;语言模型用来评价一句话(句子可以看作是字的组合)是否“合理”或…...

(萌新入门)如何从起步阶段开始学习STM32 —— 0.碎碎念

目录 前言与导论 碎碎念 所以&#xff0c;我到底需要知道哪些东西呢 从一些基础的概念入手 常见的工具和说法 ST公司 MDK5 (Keil5) CubeMX 如何使用MDK5的一些常用功能 MDK5的一些常见的设置 前言与导论 非常感谢2301_77816627-CSDN博客的提问&#xff0c;他非常好奇…...

Eclipse:关闭多余的工具条

Eclipse默认的工具条非常多&#xff0c;可以通过如下方法选择关闭一些不常用的&#xff1a; 1.选择菜单Window -> Perspective -> Customize Perspective 2.根据需要勾选Toolbar Visbility下面的工具条项...

Git标签管理:从基础到高阶自动化实践

引言 在软件发布过程中&#xff0c;88%的生产事故与版本标记错误相关。Git标签&#xff08;Tag&#xff09;作为版本控制的关键锚点&#xff0c;不仅是发布流程的里程碑&#xff0c;更是代码审计和问题追溯的重要依据。本文将深入Git标签的底层机制&#xff0c;揭示企业级标签…...

【第3章:卷积神经网络(CNN)——3.6 CNN的高级特性与优化策略】

在2012年ImageNet竞赛的颁奖现场,当AlexNet以超出第二名10%的惊人准确率夺冠时,整个计算机视觉界都意识到:这个叫CNN的架构正在重写游戏规则。十年后的今天,当我们站在YOLOv8、Vision Transformer等新架构的肩膀上回望,会发现经典CNN的进化史就是一部浓缩的深度学习发展史…...

【R语言】非参数检验

一、Mann-Whitney检验 在R语言中&#xff0c;Mann-Whitney U检验&#xff08;也称为Wilcoxon秩和检验&#xff09;用于比较两个独立样本的中位数是否存在显著差异。它是一种非参数检验&#xff0c;适用于数据不满足正态分布假设的情况。 1、独立样本 # 创建两个独立样本数据…...

250214-java类集框架

单列集合是list和set&#xff0c;list的实现类有ArrayList和LinkedList&#xff0c;前者是数组实现&#xff0c;后者是链表实现。list和set&#xff0c;前者有序、可重复&#xff0c;后者无序不可重复。 1.单列集合 1.1. list java.util.List接口继承自Collection接口&#…...

集成测试总结文档

1. 集成测试的定义 集成测试&#xff08;Integration Testing&#xff09;是在单元测试之后&#xff0c;将多个独立的软件模块或组件组合在一起进行测试的过程&#xff0c;目的是验证这些模块之间的接口、数据传递、协作逻辑是否符合设计要求&#xff0c;并发现因集成引发的缺…...

POI 的 Excel 读写操作教程

POI 的 Excel 读写操作教程 一、POI 简介 Apache POI 是一款在 Java 开发中广受欢迎的开源库&#xff0c;主要用于处理各种 Microsoft Office 文件格式&#xff0c;Excel 文件便是其中之一。凭借其功能强大的 API&#xff0c;POI 不仅支持对 Excel 文件的读取、写入和修改&am…...

ROS2 话题通信

1. 基本概念 发布-订阅模型&#xff1a;节点间通过话题&#xff08;Topic&#xff09;异步通信&#xff0c;发布者&#xff08;Publisher&#xff09;发送消息&#xff0c;订阅者&#xff08;Subscriber&#xff09;接收消息。 话题&#xff08;Topic&#xff09;&#xff1a;…...

【学习资源】时间序列数据分析方法(1)

时间序列数据分析是一个有趣的话题&#xff0c;让我们多花一些时间来研究。此篇为第一篇文章。主要介绍特征提取方法、深度学习时序数据分析模型、参考资源。期望能帮助大家解决工业领域的相关问题。 1 特征提取方法&#xff1a;信号处理 (来源:INTELLIGENT FAULT DIAGNOSIS A…...

Hadoop集群安装与配置指南(CentOS 7)

Hadoop集群安装与配置指南&#xff08;CentOS 7&#xff09; 一、虚拟机准备 安装虚拟机软件 下载VMware或VirtualBox&#xff0c;完成安装并激活。 注意&#xff1a;选择NAT模式&#xff0c;配置子网IP&#xff08;如192.168.10.0&#xff09;。 CentOS 7安装 下载CentOS 7…...

Streamlit与Qlib:量化投资策略可视化实战

Streamlit与Qlib&#xff1a;量化投资策略可视化实战 1. 项目背景 在量化投资领域&#xff0c;数据可视化是理解和展示投资策略的关键。本文将详细介绍如何使用Streamlit和Qlib构建一个交互式的量化投资策略可视化应用。 2. 环境准备 2.1 安装依赖 # 安装必要的库 pip ins…...