目录

  • 一. 栈的认识
    • 1. 栈的基本概念
    • 2.栈的基本操作
  • 二. 栈的核心优势
    • 1. 高效的时间复杂度
    • 2. 简洁的逻辑设计
    • 3. 内存管理优化
  • 三. 栈的代码实现
    • 1.栈的结构定义
    • 2. 栈的初始化
    • 3. 入栈 (动态扩容)
    • 4. 出栈
    • 5. 取栈顶数据
    • 6. 判断栈是否为空
    • 7. 获取栈的数据个数
    • 8.销毁
    • 9.完整代码展示
  • 总结

一. 栈的认识

1. 栈的基本概念

栈是一种特殊的线性表,只允许在固定的一端进行插入和删除元素的操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵循后进先出的原则。

  • 压栈: 栈的插入操作叫做进栈/压栈/入栈,入数据的元素在栈顶。
  • 出栈: 栈的出栈也叫删除操作,出数据也在栈顶。

在这里插入图片描述

2.栈的基本操作

操作描述时间复杂度
Push(x)将元素x压入栈顶O(1)
Pop()出栈弹出元素O(1)
Top()返回栈顶元素不出栈O(1)
Empty()检查栈是否为空O(1)
Size()返回栈中元素数量O(1)

二. 栈的核心优势

1. 高效的时间复杂度

  • 入栈、出栈、取栈顶均为常数时间O(1)操作,适合高频调用场景。
  • 专注“顶部”操作,避免不必要的复杂度。
  • 对比其他数据结构:
    数组:随机访问快O(1),但插入删除中间元素移动数据O(n);
    链表:插入删除中间元素快O(1),但随机访问慢O(n);

2. 简洁的逻辑设计

  • 减少代码的复杂度,设计更简单。
  • 通过压栈和出栈自动维护操作顺序,无需手动跟踪索引指针。

3. 内存管理优化

  • 局部性原理:栈操作集中在顶部,数据访问具有空间局部性,利用CPU缓存命中。
  • 动态扩容策略:栈实现如动态数组通过按需扩容平衡时间和空间效率。

三. 栈的代码实现

1.栈的结构定义

typedef struct Stack
{STDataType* a; // 动态数组,存储栈里的元素int top;       // 栈顶指针(初始为0,表示空栈)int capacity; // 栈的最大容量
}ST;
  • a:用指针指向一块内存。
  • top:指向当前栈顶的元素初始为0,表示空栈
  • capacity:栈的最大容量

2. 栈的初始化

//初始化
void STInit(ST* pst)
{pst->a = NULL;//top指向栈顶数据的下一个位置pst->capacity = pst->top = 0;
}
  • 初始化指针赋值为NULL,capacity和top赋值为0。

3. 入栈 (动态扩容)

//入栈
void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top){int newcapacity = pst->top == 0 ? 4 : 2 * pst->capacity;STDataType* newnode = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (newnode == NULL){perror("realloc fail");exit(-1);}pst->a = newnode;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}
  • 当capacity等于top时,如果为空则开辟4个空间,不为空时开辟当前空间的二倍。
  • 将插入的值先存放在top下标位置再top++。

4. 出栈

//出栈
void STPop(ST* pst)
{assert(pst && pst->top>0);pst->top--;
}
  • 直接top- - 限制访问完成出栈。

5. 取栈顶数据

//取栈顶数据
STDataType STTop(ST* pst)
{assert(pst && pst->top>0);return pst->a[pst->top - 1];
}
  • top的位置是在最后一个元素的下一个位置,所以取栈顶数据直接取top减1的下标。

6. 判断栈是否为空

//判空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}
  • 返回值是bool类型,如果top == 0则返回true。

7. 获取栈的数据个数

//获取数据个数
int STSize(ST* pst)
{assert(pst);return pst->top;
}
  • 因为栈的位置是从0开始的,所以直接返回top就是栈内部的数据个数。

8.销毁

//销毁
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}
  • 释放掉开辟的空间,将开辟的空间置为NULL,把top和capacity也置为空。

9.完整代码展示

  • Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include<stdbool.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;//初始化
void STInit(ST* pst);//销毁
void STDestroy(ST* pst);//入栈
void STPush(ST* pst, STDataType x);//出栈
void STPop(ST* pst);//取栈顶数据
STDataType STTop(ST* pst);//判空
bool STEmpty(ST* pst);//获取数据个数
int STSize(ST* pst);
  • Stack.c
#include "Stack.h"//初始化
void STInit(ST* pst)
{pst->a = NULL;//top指向栈顶数据的下一个位置pst->capacity = pst->top = 0;
}//销毁
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}//入栈
void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top){int newcapacity = pst->top == 0 ? 4 : 2 * pst->capacity;STDataType* newnode = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (newnode == NULL){perror("realloc fail");exit(-1);}pst->a = newnode;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}//出栈
void STPop(ST* pst)
{assert(pst && pst->top>0);pst->top--;
}//取栈顶数据
STDataType STTop(ST* pst)
{assert(pst && pst->top>0);return pst->a[pst->top - 1];
}//判空  等于0就为真
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}//获取数据个数
int STSize(ST* pst)
{assert(pst);return pst->top;
}

在这里插入图片描述
入栈顺序为:1 2 3 4 5
出栈顺序为:5 4 3 2 1

总结

根据上述讲解,相信大家对栈有更深层的理解了。栈是程序运行时内存管理的核心区域之一,遵循后进先出原则,由操作系统或运行时环境自动分配和释放,无需显式干预。其设计目标是高效管理函数调用和局部变量,但受限于固定大小,需谨慎使用以避免溢出。合理的使用栈能让程序又快又稳,滥用则容易崩溃。本篇文章到这里就结束了,感谢大家的阅读,你们的点赞收藏加关注就是博主最大的动力。


《前期回顾》

【数据结构】——顺序表链表(超详细解析!!!)
C语言——结构体指南(小白一看就懂!!!)
力扣(LeetCode) ——移除链表元素(C语言)

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

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

相关文章

使用TexLive与VScode排版论文

前言 中文稿目前已经完成了&#xff0c;现在要转用latex排版&#xff0c;但我对这方面没有接触过&#xff0c;这里做一个记录。 网页版Overleaf&#xff1a;Overleaf, 在线LaTeX编辑器。 TeXWorks&#xff1a;论文神器teXWorks安装与使用记录。 这里我还是决定采用Vscode作…

每日一题:2的幂数组中查询范围内的乘积;快速幂算法

题目选自2438. 二的幂数组中查询范围内的乘积 还是一样的&#xff0c;先讲解思路&#xff0c;然后再说代码。 题目有一定难度&#xff0c;所以我要争取使所有人都能看懂&#xff0c;用的方法会用最常规的思想。关于语言&#xff0c;都是互通的&#xff0c;只要你懂了一门语言…

Ceph数据副本机制详解

Ceph 数据副本机制详解 Ceph 的数据副本机制是其保证数据可靠性和高可用性的核心设计&#xff0c;主要通过多副本&#xff08;Replication&#xff09; 和 纠删码&#xff08;Erasure Coding&#xff0c;EC&#xff09; 两种方式实现。以下是对 Ceph 数据副本机制的全面解析&am…

【八股】Mysql中小厂八股

MySQL 基础 数据库三大范式&#xff08;中&#xff09; 第一范式: 要求数据库表的每一列都是不可分割的原子数据项 如详细地址可以分割为省市区等. 第二范式: 非主键属性必须完全依赖于主键, 不能部分依赖 第二范式要确保数据库表中的每一列都和主键相关, 而不能只与主键的某一…

怎么使用python查看网页源代码

使用python查看网页源代码的方法&#xff1a;1、使用“import”命令导入requests包import requests2、使用该包的get()方法&#xff0c;将要查看的网页链接传递进去&#xff0c;结果赋给变量xx requests.get(urlhttp://www.hao123.com)3、用“print (x.text)”语句把网页的内容…

C# 多线程:并发编程的原理与实践

深入探讨 C# 多线程&#xff1a;并发编程的原理与实践引言在现代应用开发中&#xff0c;性能和响应速度往往决定了用户体验的优劣。尤其在计算密集型或者IO密集型任务中&#xff0c;传统的单线程模型可能无法有效利用多核CPU的优势。因此&#xff0c;多线程技术成为了解决这些问…

react 常用组件库

1. Ant Design&#xff08;蚂蚁设计&#xff09;特点&#xff1a;国内最流行的企业级 UI 组件库之一&#xff0c;基于「中后台设计体系」&#xff0c;组件丰富&#xff08;表单、表格、弹窗、导航等&#xff09;、设计规范统一&#xff0c;支持主题定制和国际化。适用场景&…

Python 爬虫获取淘宝商品信息、价格及主图的实战指南

在电商数据分析、竞品调研或商品信息采集等场景中&#xff0c;获取淘宝商品的详细信息&#xff08;如价格、主图等&#xff09;是常见的需求。虽然淘宝开放平台提供了官方的 API 接口&#xff0c;但使用这些接口需要一定的开发和配置工作。本文将通过 Python 爬虫的方式&#x…

Ruby面向对象编程中类与方法的基础学习例子解析

代码示例&#xff1a; Ruby面向对象编程中类与方法的基础学习详细例子 1. 引言 在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;类是定义对象结构和行为的蓝图。Ruby是一种纯面向对象的编程语言&#xff0c;它将一切视为对象&#xff0c;包括基本数据类型。本文将…

[ Mybatis 多表关联查询 ] resultMap

目录 一. resultMap 1. 使用场景: 2. 查询映射: (1)单表查询映射: (2)多表查询映射: a. 在学生表里查专业 b. 在专业表里查学生 二. 其他注意事项 1. 插件下载 2. #{ } 和 ${ }的区别 一. resultMap 1. 使用场景: (1)当数据库列名和java类中的属性名不同时,可⽤ r…

Rust 性能提升“最后一公里”:详解 Profiling 瓶颈定位与优化|得物技术

一、Profiling&#xff1a;揭示性能瓶颈的“照妖镜”在过去的一年里&#xff0c;我们团队完成了一项壮举&#xff1a;将近万核的 Java 服务成功迁移到 Rust&#xff0c;并收获了令人瞩目的性能提升。我们的实践经验已在《RUST练习生如何在生产环境构建万亿流量》一文中与大家分…

STM32H5 的 PB14 引脚被意外拉低的问题解析 LAT1542

关键字&#xff1a;STM32H5&#xff0c; GPIO 1. 问题现象 客户反馈&#xff0c;使用 STM32H523RET6 应用中配置了两个 IO 口&#xff0c;PC9 为输出模式&#xff0c;内部下拉&#xff1b;PB14 为输入模式&#xff0c;内部上拉。在程序中将 PC9 引脚输出高电平&#xff0c;结…

【办公自动化】如何使用Python让Word文档处理自动化?

在日常办公中&#xff0c;Word文档是最常用的文本处理工具之一。通过Python自动化Word文档操作&#xff0c;可以大幅提高工作效率&#xff0c;减少重复劳动&#xff0c;特别适合批量生成报告、合同、简历等标准化文档。本文将介绍几种常用的Python操作Word文档的方法&#xff0…

顺序表的总结及模拟实现

目录 一.线性表 二.顺序表 1.概念 2.结构 3.要实现的接口函数 三.模拟实现顺序表 1.定义出顺序表的基本结构 2.实现检查扩容功能 3.实现尾插 4.实现尾删 5.实现头插和头删 6.查找 7.修改 8.遍历 9.在指定位置插入和删除 四.顺序表的优缺点及思考 a.顺序表的弊端 …

Vue3 vs Vue2:全面对比与面试宝典

文章目录Vue3 vs Vue2&#xff1a;全面对比与面试宝典引言&#xff1a;Vue框架的进化之路一、核心架构对比二、响应式系统的革命Vue2的响应式&#xff1a;像老式监控摄像头Vue3的响应式&#xff1a;像智能AI监控系统三、API风格的进化Vue2的Options API&#xff1a;像填表格Vue…

Java Web开发:Session与Cookie详细入门指南

在Web开发中&#xff0c;状态管理是核心需求之一。本文将深入讲解Java中Session和Cookie的使用方法&#xff0c;帮助你掌握用户状态管理的核心技术。 一、Session与Cookie基础概念 特性SessionCookie存储位置服务器内存/持久化存储客户端浏览器安全性较高&#xff08;敏感数据…

HTTPS与CA证书:安全通信全解析

CA&#xff08;Certificate Authority&#xff09;&#xff1a;证书颁发机构&#xff0c;负责签发和管理数字证书&#xff0c;验证证书持有者的身份。HTTPS&#xff1a;基于 SSL/TLS 协议的 HTTP&#xff0c;通过证书实现客户端与服务器的身份验证和数据加密。HTTPSHTTPSSL/TLS…

AI生成代码时代的商业模式重构:从“软件即产品”到“价值即服务”

2025年,全球AI代码生成市场规模突破63亿元(数据来源:《中国AI代码生成行业发展报告》),开发者效率提升40%以上,软件开发成本下降30%。这一技术浪潮正在颠覆传统软件行业的商业逻辑——当代码生成变得像文字编辑一样简单时,企业如何构建可持续的商业模式? 本文将从硬件…

C#特性与反射知识梳理

C#中的**特性&#xff08;Attributes&#xff09;和反射&#xff08;Reflection&#xff09;**是两个非常重要的概念&#xff0c;它们通常用于代码的元编程&#xff0c;允许你在运行时获取类型信息并对其进行操作。下面对这两个概念进行详细梳理&#xff1a;一、C#中的特性&…

SQL 语法详解

SQL 语法详解 引言 SQL&#xff08;Structured Query Language&#xff09;是一种用于数据库管理的标准语言&#xff0c;它允许用户进行数据的查询、更新、插入和删除等操作。SQL语法是数据库管理和编程的基础&#xff0c;本篇文章将详细介绍SQL的基本语法和常用操作&#xff0…