数据结构(三)------栈

devtools/2024/10/21 11:57:57/

制作不易,三连支持一下呗!!!

文章目录

  • 前言
  • 一、什么是栈
  • 二、栈的实现
    • 1.栈的结构
    • 2.栈的初始化和销毁
    • 3.栈的插入数据和删除数据
    • 4.取栈顶元素
  • 总结


前言

前面我们介绍了第二种数据结构---链表,这里我们继续介绍下一种数据结构——栈!!!


一、什么是栈

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

压栈:栈的插入操作叫做进栈 / 压栈 / /入栈。

出栈:栈的删除操作叫做出栈。

二、栈的实现

1.栈的结构

栈的底层既可以用顺序表的结构来存储数据,也可以用链表的形式存储数据,但是我们一般选择顺序表。

原因:如果用链表,对于删除操作,我们就需要找到最后一个元素的前一个元素,要么用循环遍历的方式来找,这样时间复杂度为o(N),效率不高,要么使用双向链表,相较于顺序表在空间上浪费了一些。同时,由于CPU高速缓存的局部性原理,数组是连续空间在访问时效率更高!!!

注:如果非要用链表来实现栈,那么推荐用栈的插入推荐用单链表的头插和头删,这样避免了我们在删除时寻找倒数第二个节点的麻烦。

根据我们的推导:

栈的结构:

#define STDateType inttypedef struct Stack
{STDateType* a;int top;int capacity;
}ST;

2.栈的初始化和销毁

1.初始化:

void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}

二:销毁 

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

3.栈的插入和删除

1.插入数据

void STPush(ST* ps, STDateType x)
{assert(ps);if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDateType* tmp = (STDateType*)realloc(ps->a, newcapacity * sizeof(STDateType));if (tmp == NULL){perror("realloc:");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;}

 学习链表后,栈的插入和删除操作应该相对要更简单一些,这里就不做过多讲解了。


2.删除数据

删除数据时,需要检查栈是否为空,如果为空就不能再删除了

这里我们又实现了一个检查栈是否为空的函数:

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

 

删除数据:

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

4.取栈顶元素

这里特别要注意的是,因为我们在初始化时给top的值为0,也就是说这里top表示的是栈顶元素的下一个。因此栈顶元素的下标是top-1。

注:这里初始化时也可以讲top初始化成-1,这样top表示的就是栈顶元素。插入数据就是先+1再插入。两种写法都可以,无优劣之分。

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


总结

栈的实现相较于链表还是很简单的,如果有些地方不太理解,可以去看看链表部分。

全部代码:

#define STDateType inttypedef struct Stack
{STDateType* a;int top;int capacity;
}ST;void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void STPush(ST* ps, STDateType x)
{assert(ps);if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDateType* tmp = (STDateType*)realloc(ps->a, newcapacity * sizeof(STDateType));if (tmp == NULL){perror("realloc:");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;}void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}int STSize(ST* ps)
{assert(ps);return ps->top;
}STDateType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->a[ps->top - 1];
}


http://www.ppmy.cn/devtools/31026.html

相关文章

Android4.4真机移植过程笔记(一)

1、RK源码编译 获取内核源码: git clone git172.28.1.172:rk3188_kernel -b xtc_ok1000 内核编译环境: 从172.28.1.132编译服务器的/data1/ZouZhiPing目录下拷贝toolchain.tar.gz(交叉编译工具链)并解压到与rk3188_kernel同级目…

C# 字段(Field)与属性(Property)的区别

字段和属性,都是成员变量,都用于存取数据。字段读写无限制,属性通过get和set方法可以控制读写(比如可以在年龄Age属性的set方法中限制,当赋值的value大于200时,则赋值默认值100,从而确保数据准确…

【数学 排列组合】1643. 第 K 条最小指令

本文涉及知识点 数学 排列组合 LeetCode1643. 第 K 条最小指令 Bob 站在单元格 (0, 0) ,想要前往目的地 destination :(row, column) 。他只能向 右 或向 下 走。你可以为 Bob 提供导航 指令 来帮助他到达目的地 destination 。 指令 用字符串表示&am…

LeetCode 102.对称二叉树

题目描述 给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2: 输入:root [1,2,2,null,3,null,3] 输出:false提示: 树中节点数…

基于缓存注解的时间戳令牌防重复提交设计

文章目录 一,概述二,实现过程1、引入pom依赖2、定义缓存管理3、时间戳服务类4、模拟测试接口 三,测试过程1, 模拟批量获取2, 消费令牌 四,源码放送五,优化方向 一,概述 API接口由于…

数据结构和算法

目录 数据结构 算法 数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。这种“结构”可以理解为数据元素之间的逻辑关系,包括数据的逻辑结构和物理结构。精心选择的数据结构往往可以带来更高的运行或者存储效率…

Ftrans文件外发系统 构建安全可控文件外发流程

文件外发系统是企业数据安全管理中的关键组成部分,它主要用于处理企业内部文件向外部传输的流程,确保数据在合法、安全、可控的前提下进行外发。 文件外发系统的主要作用包括: 1、防止数据泄露:通过严格的审批流程和安全策略&…

[XYCTF新生赛]-PWN:fmt解析(scanf格式化字符串漏洞,任意地址写)

查看保护 查看ida 这里没什么好说的 完整exp: from pwn import* context(log_leveldebug) #pprocess(./fmt) premote(gz.imxbt.cn,20975) backdoor0x4012BEp.recvuntil(bgift: ) printf_addrint(p.recv(14),16) print(hex(printf_addr)) libcELF(./libc-2.31.so) …