【初阶数据结构】栈

目录

  • 栈的概念及结构
  • 栈的实现
    • 栈的结构
    • 栈的初始化
    • 栈的销毁
    • 入栈
    • 出栈
    • 取栈顶元素
    • 判断栈是否为空
    • 取栈中元素个数
    • 代码测试
  • 完整代码
    • Stack.h
    • Stack.c
    • test.c

请添加图片描述

栈的概念及结构

  栈:是一种特殊的线性表,它只允许在固定的一端进行插入和删除元素的操作
  栈顶:进行数据插入和删除操作的那一端。
  栈底:栈顶的另一端就是栈底。
  压栈:栈的插入数据操作就叫压栈,也称进栈,入栈,入数据在栈顶
  出栈:栈的删除数据操作叫做出栈,出数据也在栈顶
  栈不能随机访问,只能在栈顶出入数据或访问数据。
  栈数据元素遵守后进先出LIFO(Last In First Out)的原则。
在这里插入图片描述

栈的实现

  栈同样有两种存储方式,一种是链式存储,叫做链栈,一种是顺序存储,叫做顺序栈,一般情况下,用顺序栈的方式比较多。是因为用顺序表来实现对栈的操作,一方面顺序表的扩容不会像链表一样要一个个节点去malloc那么频繁,内存空间也比较大,人们也不会特别在意空间浪费的问题,并且利用顺序表尾插尾删数据的代价比链表更小;另一方面顺序表的缓存利用率高,所以我们更倾向使用顺序栈。

栈的结构

  顺序表分为了静态顺序表和动态顺序表,但是为了方便扩容,一般都采用动态顺序表,同样的,顺序栈也分为了定长的静态栈和支持动态增长的栈,我们也主要来实现动态增长的栈。
  动态增长栈的结构如下:

typedef int STDataType;
typedef struct Stack
{STDataType* a;//顺序栈,即用数组实现,a指向栈底int top;int capacity;
}ST;

这里有一个问题需要注意:
我们定义的top是什么,指向哪里,应该初始化为什么
这是有两种情况:
情况一:
top指向栈顶的那个元素:

在这里插入图片描述
由上图可知,当top指向栈顶元素时,它初始化应该为-1,而不是0,因为这样才能使得栈中有一个元素的时候,top等于0且指向那一个元素。
情况二:
top指向栈顶的下一个元素:

在这里插入图片描述
如上图,当top指向栈顶的下一个元素时,它的初始化就为0,即top可看做栈中有效元素个数。

栈的初始化

  上面我们已经说了top的两种情况,这也对应着top的两种初始化,但其实两种初始化都是正确的,看你选择哪一种,这里我们选择第二种,top为0时栈空,相当于顺序表的size。
  初始化如下:

void STInit(ST* pst)//传址调用,才能修改形参中的值,用指针接收,不再多说
{assert(pst);//传参的指针不能为空pst->a = NULL;//可以先初始化为空,后面插入数据时在添加空间pst->top = 0;pst->capacity = 0;
}

栈的销毁

void STDestory(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->top == pst->capacity)//空间不够,要扩容{int newcapacity = pst->capacity == 0 ? 4 :2 * capacity;STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (new == NULL){perror("realloc fail");return;}pst->a = tmp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}

出栈

  同样的,出栈相当于顺序表的尾删,代码如下:

void STPop(ST* pst)
{assert(pst);assert(pst->top);//栈不能为空,为空则报错pst->top--;
}

取栈顶元素

  取栈顶元素也就等于读取数组中最后一个元素的值,要注意的是,下标是top还是top-1,由于我们定义的top是指向栈顶的下一个元素,所以下标应该为top-1.

STDataType STTop(ST* pst)
{assert(pst);assert(pst->top);return pst->a[pst->top-1];
}

判断栈是否为空

  判断栈是否为空,如果为空,则返回true,不为空,则返回false,此时我们用bool类型的函数去定义。我们上面在判断top的初始化时已经提到,当top == 0,则栈为空,代码如下:

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

取栈中元素个数

  上面说到,当我们初始化top = 0时,top就相当于size,即元素个数,只要返回top即可。

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

代码测试

  至此,栈的有关操作就结束了,最后也不要忘了调试所写代码是否正确。这里要注意的是,在打印栈的时候,我们不能像顺序表或者链表一样写一个打印函数出来,因为链表是后进先出的,当我们需要打印这个栈时,需要一个个出栈然后打印,代码如下:

while (!STEmpty(&s))//判断栈是否为空
{printf("%d ", STTop(&s));//先读取栈顶元素STPop(&s);//后取出栈顶元素
}

测试代码如下:
在这里插入图片描述

  当然,栈也不仅仅只能打印这一种,可以有很多种情况,具体要看是如何出栈和入栈的

比如说有三个数字1,2,3,进行出栈出栈操作
则三个数既可以先全部入栈再出栈,也可以边入栈边出栈,
则这三个数出栈后全部的可能序列为:
{3,2,1}、{2,3,1}、{2,1,3}、{1,2,3}、{1,3,2}

完整代码

Stack.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;//初始化和销毁
void STInit(ST* pst);
void STDestory(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;pst->capacity = 0;pst->top = 0;
}//销毁
void STDestory(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->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDataType* new = (STDataType*)realloc(pst->a, newcapacity*sizeof(STDataType));if (new == NULL){perror("realloc fail");return;}pst->a = new;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}//出栈
void STPop(ST* pst)
{assert(pst);assert(pst->top);pst->top--;
}//取栈顶元素
STDataType STTop(ST* pst)
{assert(pst);assert(pst->top);return pst->a[pst->top - 1];
}//判断栈是否为空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}//获取元素个数
int STSize(ST* pst)
{assert(pst);return pst->top;
}

test.c

#include"Stack.h"void test()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);printf("栈中元素个数为:%d\n", STSize(&s));STPop(&s);STPop(&s);printf("取出栈顶元素:%d\n", STTop(&s));printf("栈中元素个数为:%d\n", STSize(&s));printf("打印栈中元素:");while (!STEmpty(&s)){printf("%d ", STTop(&s));STPop(&s);}STDestory(&s);
}int main()
{test();return 0;
}

  今天的内容到此结束啦,感谢大家观看,如果大家喜欢,希望大家一键三连支持一下,如有表述不正确,也欢迎大家批评指正。

在这里插入图片描述

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

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

相关文章

Axure PR 10 下拉三级菜单设计图

在线预览地址&#xff1a;Untitled Document 程序员必备资源网站&#xff1a;天梦星服务平台 (tmxkj.top) 需要源码设计图联系我wx:19948765606,3块钱拿走

了解内存函数

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱博客 所属栏目&#xff1a;C语言 前言 内存函数不止malloc、calloc、realloc、free还有memcpy、memmove、memset、memcmp。前四个的头文件是<stdlib.h>,后四个的头文件是<strin…

【C++】-【QT】类库使用-001

1主窗口创建 1.1【makefile】配置 1 源码 QT widgetsSOURCES main.cpp2 图示 1.2源码 1 源码 #include <QWidget> #include <QApplication>using namespace std;int main(int argc,char *argv[]) {QApplication a(argc,argv);QWidget w;w.show();return a…

YOLOv8改进 | 独家创新篇 | 利用MobileNetV4的UIB模块二次创新C2f(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是利用MobileNetV4的UIB模块二次创新C2f&#xff0c;其中UIB模块来自2024.5月发布的MobileNetV4网络&#xff0c;其是一种高度优化的神经网络架构&#xff0c;专为移动设备设计。它最新的改动总结主要有两点&#xff0c;采用了通用反向瓶…

C语言:指针(1)

1. 内存和地址 内存划分为⼀个个的内存单元&#xff0c;每个内存单元的⼤⼩取1个字节。 计算机中常⻅的单位&#xff08;补充&#xff09;&#xff1a; ⼀个⽐特位可以存储⼀个2进制的位1或者0 C语⾔中给地址起了新的名字叫&#xff1a;指针。 内存单元的编号地址指针。 1.…

介绍 ffmpeg.dll 文件以及ffmpeg.dll丢失怎么办的五种修复方法

ffmpeg.dll 是一个动态链接库文件&#xff0c;属于 FFmpeg运行库。它在计算机上扮演着非常重要的角色&#xff0c;因为它提供了许多应用程序和操作系统所需的功能和组件。当 ffmpeg.dll 文件丢失或损坏时&#xff0c;可能会导致程序无法正常运行&#xff0c;甚至系统崩溃。下面…

树莓派4b红外检测

1.红外检测连接图 2.红外检测工作原理 红外传感器的工作原理类似于物体检测传感器。该传感器包括一个红外LED和一个红外光电二极管&#xff0c;因此通过将这两者结合起来&#xff0c;可以形成一个光耦合器。 红外LED是一种发射红外辐射的发射器。该LED看起来与标准LED相似&a…

嫦娥六号近月制动成功,建立月球基地又迈进一步!

嫦娥六号探测器在近月制动的关键时刻&#xff0c;北京航天飞行控制中心内弥漫着紧张而庄重的氛围。每一个航天科技工作者都屏息以待&#xff0c;他们的眼神中充满了期待与自豪。随着一系列精妙绝伦的指令如同琴弦上的音符般流畅地奏响&#xff0c;嫦娥六号探测器在万众瞩目的目…

排序算法(Java版)

目录 1、直接插入排序2、希尔排序3、直接选择排序4、堆排序5、冒泡排序6、快速排序6.1 递归实现6.2 非递归实现 7、归并排序7.1 递归实现7.2 非递归实现 8、性能分析 今天我们学习一种算法&#xff1a;排序算法&#xff08;本文的排序默认是从小到大顺序&#xff09;&#xff0…

红帽为 Red Hat OpenShift AI 扩大与 Elasticsearch 向量数据库的合作

作者&#xff1a;来自 Elastic Aditya Tripathi 红帽和 Elastic 今天宣布开展合作&#xff0c;以便在 Red Hat OpenShift AI 上集成 Elasticsearch 向量数据库。 Red Hat OpenShift 用户现在可以通过红帽生态系统目录实施 Elasticsearch 以进行向量搜索和检索增强生成 (RAG) 应…

Flink DataSink介绍

介绍 Flink DataSink是Apache Flink框架中的一个重要组件&#xff0c;它定义了数据流经过一系列处理后最终的输出位置。以下是关于Flink DataSink的详细介绍&#xff1a; 概念&#xff1a;DataSink主要负责对经过Flink处理后的流进行一系列操作&#xff0c;并将计算后的数据结…

Hive Transaction事务表(含实现原理)

Hive Transaction事务表 在Hive中&#xff0c;事务表&#xff08;Transactional Tables&#xff09;允许用户执行事务性操作&#xff0c;包括ACID&#xff08;原子性、一致性、隔离性、持久性&#xff09;特性。事务表是在Hive 0.14版本引入的&#xff0c;并且在后续版本中不断…

wangEditor富文本编辑器与layui图片上传

记录&#xff1a;js 显示默认的wangEditor富文本编辑器内容和图片 <style>body {background-color: #ffffff;}.layui-form-select dl{z-index:100000;} </style> <div class"layui-form layuimini-form"><div class"layui-form-item"…

【Android项目】“追茶到底”项目介绍

没有多的介绍&#xff0c;这里只是展示我的项目效果&#xff0c;后面会给出具体的代码实现。 一、用户模块 1、注册&#xff08;第一次登陆的话需要先注册账号&#xff09; 2、登陆&#xff08;具有记住最近登录用户功能&#xff09; 二、点单模块 1、展示饮品列表 2、双向联动…

缓存雪崩、击穿、击穿

缓存雪崩&#xff1a; 就是大量数据在同一时间过期或者redis宕机时&#xff0c;这时候有大量的用户请求无法在redis中进行处理&#xff0c;而去直接访问数据库&#xff0c;从而导致数据库压力剧增&#xff0c;甚至有可能导致数据库宕机&#xff0c;从而引发的一些列连锁反应&a…

【vue+vue-treeselect】根据指定字段,如isLeaf(是否末级节点),设置只允许末级节点可以选

1、当项目有特殊要求&#xff0c;必须根据某个字段的值去判断&#xff0c;是否节点可以选&#xff0c;即使已经是末级节点了&#xff0c;还是需要根据字段判断是否禁用 &#xff08;1&#xff09; :flat"true"一定要设置 (2)获取数据源的时候&#xff0c;设置下禁用…

【进程间通信】共享内存

文章目录 共享内存常用的接口指令利用命名管道实现同步机制总结 System V的IPC资源的生命周期都是随内核的。 共享内存 共享内存也是为了进程间进行通信的&#xff0c;因为进程间具有独立性&#xff0c;通信的本质是两个不同的进程看到同一份公共资源&#xff0c;所以共享内存…

【web网页制作】html+css旅游家乡河南开封主题网页制作(4页面)【附源码】

HTMLCSS家乡河南主题网页目录 &#x1f354;涉及知识&#x1f964;写在前面&#x1f367;一、网页主题&#x1f333;二、页面效果Page1 首页Page2 开封游玩Page 3 开封美食Page4 留言 &#x1f308; 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 &#x1f40b;四…

centos8.5 安装 redis 7.2.4 详细步骤

1 下载Index of /releases/ (redis.io) 通过xftp等方式上传到服务器&#xff0c;安装依赖包 yum install gcc gcc-c make tcl -y [rootlocalhost software]# ll total 3308 -rw-r--r--. 1 root root 3386861 May 3 21:56 redis-7.2.4.tar.gz [rootlocalhost software]# ll…

CoPilot 产品体验:提升 OpenNJet 的控制管理和服务提供能力

文章目录 前言系统架构介绍CoPilot 配置CoPilot 插件规范 体验 CoPilot 实例CoPilot: Broker 实例CoPilot: Ctrl 实例 开发其他语言编写的 CoPilot目标主要思路具体实现执行 go 程序代码 功能扩展总结 前言 CoPilot 是 OpenNJet 的一个重要组成部分&#xff0c;它在 Master-Wo…