初阶数据结构之栈的实现(五)

news2024/11/25 11:28:13

文章目录

  • 😏专栏导读
  • 🤖文章导读
    • 🙀什么是栈?
    • 🙀画图描述
  • 😳栈的代码实现及其各类讲解
    • 😳栈的初始化代码实现及其讲解
      • 😳栈的初始化
    • 😳栈的销毁代码实现及其讲解
    • 😳栈的入栈代码的实现及其讲解
    • 😳栈的出栈(也称弹栈)的代码实现及其讲解
      • 😳栈的判空函数的代码实现
    • 😳栈的栈顶结点的取得
  • 😳栈的整体代码的实现
  • 总结


😏专栏导读

👻作者简介:M malloc,致力于成为嵌入式大牛的男人
👻专栏简介:本文收录于 初阶数据结构,本专栏主要内容讲述了初阶的数据结构,如顺序表,链表,栈,队列等等,专为小白打造的文章专栏。
👻相关专栏推荐:LeetCode刷题集,C语言每日一题。


🤖文章导读

本章我将详细的讲解关于栈的知识点
在这里插入图片描述

🙀什么是栈?

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

栈的两种概念:
1、压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
2、出栈:栈的删除操作叫做出栈。出数据也在栈顶

🙀画图描述

如下图所示,就是出栈入栈全过程啦!关于栈有一个特点就是后进先出不要忘记啦!

在这里插入图片描述

😳栈的代码实现及其各类讲解

😳栈的初始化代码实现及其讲解

首先我们要清晰栈是如何实现的
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
所以这里我们选择用数组来实现顺序栈!

如图所示:假设用数组实现的话,就像有限制条件的顺序表,尾插就相对的方便一些。

在这里插入图片描述

如果用链式栈实现的话,就相对的消耗会更大一些

在这里插入图片描述

😳栈的初始化

这里我们采用的是动态开辟版的顺序栈,所以首先我们先定义一个结构体类型

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDatatype;
typedef struct Stack
{
	STDatatype* a;
	int top;
	int capacity;
}ST;

这是类型的定义。
初始化函数代码如下:

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

那么我们为什么要这样初始化呢?为什么我们的top初始化要赋值为0呢?这里就是方便于我们正常的理解啦,因为正常的来说,我们数组的下标一般都是从0开始的!但是如果这样考虑的话,

我们就应该清楚top所处于的位置了,当a1插入数据时,我们的top就应该是在下一个位置了,而不是相对应的位置。

在这里插入图片描述

😳栈的销毁代码实现及其讲解

代码如下:

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

由于我们用的是顺序栈,它是一块连续的地址,所以我们只需要free掉首结点,它那一块连续的空间都会被销毁,并且我们再把对应的容量和栈顶指向的位置都归回原位就行啦!

😳栈的入栈代码的实现及其讲解

栈的入栈实现其实是有限制条件的,就是要从栈顶入数据,然后还从栈顶出数据,其实就是根据我们的top位置去插入元素,下面我们进入画图讲解!

最初的栈是空的图:
在这里插入图片描述

然后我们开始入栈元素,此时的元素是从栈顶开始入栈,此时的数据已经入进去了,我们发现此时的top也向前移动了一个位置,此时也就是当数据成功入栈时,我们的top会自动的进行++

在这里插入图片描述

下面是代码实现

在实现代码的过程中,我们发现有一个if然后一大串的看不懂的一堆代码对不对。

这一段的代码主要的作用就是当我们的入栈满了的时候,我们可以进行动态扩容,那么这个realloc的作用是啥呢?我们可以登录cplusplus查看一下,网址时这个噢!这就是cplusplus网站点我就好啦

我们可以发现这里面有两个参数一个是指针,一个是大小,我就直接告诉大家啦,这里的指针是指向我们要扩容的地址处,然后大小是指我们要在这块需要扩容的地方开辟多少大小。

在这里插入图片描述

void STPush(ST* pst, STDatatype x)
{
	if (pst->capacity == pst->top)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDatatype* tmp = (STDatatype*)realloc(pst->a, newCapacity * sizeof(STDatatype));
		if (tmp == NULL)
		{
			perror("mallo fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newCapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

😳栈的出栈(也称弹栈)的代码实现及其讲解

顺序站的出栈,其实就和顺序表的尾删很像,就直接把栈顶的top–就行啦,但是我们得确定一件事,就是当这个顺序栈是空的时候,我们就应该停止删除了,所以这里我选择用assert直接暴力一点。

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

😳栈的判空函数的代码实现

我们在写一个判空的接口函数吧!根据下图我们可以发现,当top==0时,此时的栈就是空的。

在这里插入图片描述

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

😳栈的栈顶结点的取得

首先我们得确定我们的栈不能是一个空栈,其次我们会发现去栈顶元素其实就是去栈顶结点的位置的数,但是我们得注意了,我们的思维其实时偏向于数组的,所以我们取栈顶数据时,应该让top-1,就跟我们正常思考一样。

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

😳栈的整体代码的实现

stack.c

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.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.h

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}
void STPush(ST* pst, STDatatype x)
{
	if (pst->capacity == pst->top)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDatatype* tmp = (STDatatype*)realloc(pst->a, newCapacity * sizeof(STDatatype));
		if (tmp == NULL)
		{
			perror("mallo fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newCapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}
STDatatype STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	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;
}

总结

今天的代码讲解就到这里啦,如果你们觉得还可以的话可以一键三连!!
下一期我们讲的时队列的实现噢!!

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

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

相关文章

【面试题】2023vue面试题

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 1、说说你对 SPA 单页面的理解&#xff0c;它的优缺点分别是什么&#xff1f; SPA&#xf…

【运维知识进阶篇】集群架构-Nginx高可用Keepalived

高可用是指2台机器启动着完全相同的业务系统&#xff0c;一台机器宕机后&#xff0c;另一台可以快速启用&#xff0c;用户是无感知的。高可用硬件通常使用F5&#xff0c;软件通常使用keepalived。keepalived软件是基于VRRP协议实现的&#xff0c;VRRP虚拟路由冗余协议&#xff…

详解Node.js开发中不可或缺的7个库

在Node.js开发中&#xff0c;选择合适的库对于提高开发效率和优化应用程序性能至关重要。本文将介绍七个备受关注的Node.js库&#xff0c;它们在各自的领域中展现了出色的功能和性能。这些库分别是&#xff1a;Config、Fetch、Ioredis、Multer、Cache、Fast-xml-parser和Cron。…

一图看懂 pkg_resources 模块:包资源API,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 pkg_resources 模块&#xff1a;包资源API&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块图&#x1f9ca;类关系图&#x1f9…

JavaEE(系列15) -- 多线程(JUC中常见的类)

JUC----- java.util.concurrent(并发) 1. ReentrantLock 1. 可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全. 2. ReentrantLock 也是可重入锁. "Reentrant" 这个单词的原意就是 "可重入". 1. ReentrantLock 的用法: lock():…

【花雕学AI】微软 Bing 图像魔法师:让你的描述变成图像,让你的图像变成现实

你有没有想过&#xff0c;如果你能够用语言来创造图像&#xff0c;那该有多么神奇和有趣&#xff1f;你有没有想过&#xff0c;如果你能够看到你想象中的图像&#xff0c;那该有多么震撼和美妙&#xff1f;现在&#xff0c;这一切都可以实现了&#xff0c;因为微软 Bing 图像魔…

NetApp EF 系列全闪存阵列——性能极佳,性价比优势突出

NetApp EF 系列全闪存阵列——性能极佳&#xff0c;性价比优势突出 如果您需要为实时分析、HPC 和数据库等性能敏感型工作负载提供强劲动力&#xff0c;NetApp EF 系列全闪存阵列的性价比优势不言自明。其可为要求最苛刻的应用程序提供微秒级响应&#xff0c;最大限度地延长正…

电源方案对比

电源 1.方案选择&#xff1a;1 LM2596 2 MP1584 3&#xff1a;TPS54301LM25962.MP1584&#xff1a;3.TPS5430 2.1输出2A电流的纹波2.2 输出3A电流的纹波3.动态响应4.发热5.电源转换效率6.综合指标reference 1.方案选择&#xff1a;1 LM2596 2 MP1584 3&#xff1a;TPS5430 1LM…

Unity之ShaderGraph节点介绍 Channel通道

目录 Channel&#xff08;通道&#xff09;  1、Combine&#xff08;合并&#xff09;  2、Flip&#xff08;反转&#xff09;  3、Split&#xff08;拆分&#xff09;  4、Swizzle&#xff08;通道调配&#xff09; Channel&#xff08;通道&#xff09; 1、Combine&am…

win可以上网,但是右下方显示“无internet链接“

使用了下面链接的方法&#xff0c;成功解决 Win10可以联网但右下角显示无法连接到Internet怎办 首先&#xff0c;打开控制面板(control)&#xff0c;右上角&#xff0c;将查看方式切换为小图标 调整计算机的设置下&#xff0c;找到并点击网络和共享中心 网络和共享中心窗口&a…

即时通讯软件(企业IM)对企业的作用

随着网络时代的来临&#xff0c;即时通讯软件也开始逐渐在企业中流行起来&#xff0c;甚至很多公司都已经将即时通讯软件作为内部沟通的主要工具&#xff0c;那么这种情况下&#xff0c;即时通讯软件对企业究竟有什么作用呢&#xff1f; 首先&#xff0c;即时通讯软件对于企业内…

20年前,微软给金山那刀,现今一举将WPS推上领奖台,WPS,赢了

WPS&#xff0c;赢了 正如姚冬&#xff08;金山办公副总裁&#xff09;所说&#xff1a; 文本的命令行到图形界面的那次&#xff0c;改变整个人机交互的方式&#xff0c;我们公司历史上最大的一次危机也是那一次&#xff0c; 但我们依然挺过来了&#xff0c;我们相信这次技术浪…

走进Linux世界,学习Linux系统的必备指南

随着计算机技术的不断发展&#xff0c;Linux操作系统已成为IT行业中备受关注的操作系统之一。Linux以其安全性、稳定性和开放性&#xff0c;受到了广泛的认可和欢迎。学习Linux系统对于IT行业的从业者来说是非常重要的。但是&#xff0c;对于初学者来说&#xff0c;学习Linux可…

CANopenNode Master 配置

文章目录 CANopenNode 简介CANopenNode 主栈SDO ClientPDO 通讯参数RPDO 通讯参数RPDO 通信参数设置实例TPDO 通讯参数TPDO 通信参数设置实例 PDO 映射参数RPDO 映射参数设置实例TPDO 映射参数设置实例 CANopenNode 简介 CANopenNode 是一个开源的免费的开源 CANopen 协议栈。…

【谷粒商城笔记】1.基于docker的mysql、redis环境配置

0.系统 宝塔 v7.5.1 Centos v8.2 1. 安装Docker 直接yum install docker会提示找不到 > docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine Loaded plugins: fastestmirror No Match for argument: …

Ae:常用内置抠像效果

Ae 中的抠像都是基于效果控件来实现的&#xff0c;最终生成动态遮罩来控制画面像素的透明度。 常用的内置抠像效果有&#xff1a;提取、线性颜色键、颜色差值键、内部/外部键等。 黑色或白色背景的抠像 对于白色或黑色背景的素材&#xff0c;可直接尝试图层混合模式。 或者&…

一文打通File类

目录 基本概述 常用构造器 构造方法 路径分隔符 常用方法 File类的获取功能 File类的重命名功能 File类的判断功能 File类的创建功能 File类的删除功能 在 Java 中&#xff0c;File 类是 java.io 包中唯一代表磁盘文件本身的对象&#xff0c;也就是说&#xff0c;如果…

一大波智能AI对话机器人来袭——一共20个可以白嫖的ChatGPT网站供您使用,总有一款能打开~

文心一言https://yiyan.baidu.com 小莓用AIhttps://ai.usesless.com/chat NotGPTNotGPT,AI问答,AI绘画,AI协助提升工作效率https://chat2.pypig.com https://chatgptmirror.comhttps://chatgptmirror.com 超大模型AI对话https://chat.ktoai.com ChatGPTYour personal ChatGPT B…

使用nsenter检查docker网络

文章目录 一 环境准备二 需求三 解决 一 环境准备 虚拟机IP&#xff1a;10.0.0.100 拉取的三个镜像&#xff0c;镜像名称与ID如下&#xff1a; [rootcanway01 ~]# docker image ls REPOSITORY TAG IMAGE ID CREATED …

flink 解决udf重复调用的问题(亲测有效)

问题 针对如图的情况,udf会被调用4次,如果udf是计算型的,后果很严重。接下来介绍一下解决的办法。 更改底层源码 大神的博客继续往下看,有测试过程测试UDF 1.写两个udf public class Udf1 extends ScalarFunction {public long eval(long ordernumber